私がやりたいことは、Windows Mobile Winforms の MainMenu を拡張して、2 番目のメニュー レベルを持つことです。メニュー ボタンを短く傾けると、イベント アクションが実行されますが、長く押すと、2 番目のメニュー レベルがポップアップします。MainMenu はマネージ機能が非常に不足しているため、別の方法を見つける必要がありました。MainMenu を派生させてこれをアーカイブし、いくつかの SubClassing を追加しました。
public delegate IntPtr Win32WndProc(IntPtr hWnd, int msg, int wParam, int lParam);
[DllImport("coredll.dll", EntryPoint = "FindWindow", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, IntPtr lpWindowName);
[DllImport("coredll.dll")]
public static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
[DllImport("coredll")]
public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, Win32WndProc newProc);
int GWL_WNDPROC = (-4);
int GW_CHILD = 5;
IntPtr _oldToolbarProc;
IntPtr _oldMenuWorkerProc
void Hookup()
{
//find the window to hook
var hWndHooked = FindWindow("HHTaskbar", IntPtr.Zero);
if (hWndHooked == IntPtr.Zero)
return;
//enable the taskbar, not realy necessary
EnableWindow(hWndHooked, true);
//find the menu_worker window
var menuWorkerWnd = FindWindow("menu_worker", IntPtr.Zero);
if (menuWorkerWnd == IntPtr.Zero)
return;
var toolbarWnd = GetWindow(menuWorkerWnd, GW_CHILD);
if (toolbarWnd == IntPtr.Zero)
return;
Win32WndProc newMenuWorker = MenuWorkerProc;
_oldMenuWorkerProc = SetWindowLong(menuWorkerWnd, GWL_WNDPROC, newMenuWorker);
Win32WndProc newToolbar = ToolbarProc;
_oldToolbarProc = SetWindowLong(newToolbarWnd, GWL_WNDPROC, newToolbar);
}
ツールバーのサブクラス化は、WM_LBUTTONDOWN と WM_LBUTTONUP の間の時間を測定し、これらのイベント間の時間経過に応じて、コンテキスト メニューが呼び出されます。
コンテキスト メニューが呼び出される場合、menu_worker サブクラスは、押されたボタンの WM_COMMAND を抑制しなければなりません。
これは、単一のウィンドウでうまく機能します。しかし、2 番目のフォームで使用すると、同じツールバーとメニューワーカーの両方が認識され、アプリケーションがクラッシュします。
私が試みたのは、親フォームの onFocus /onLostFocus イベントでフックおよびアンフックすることです。しかし、悲しいことに、正しいウィンドウが表示される前に onFocus が呼び出され、間違ったウィンドウハンドルも取得します:(
私が今やったこと (私は非常に悪いハックを知っています) は、onFocus イベントで時間を開始し、1000 ミリ秒待ってから接続することです。これにより、右側のウィンドウをフックする 50:50 の変更が行われます。
適切なウィンドウをサブクラス化するためのより良い解決策はありませんか?