注: コード サンプルは簡略化されていますが、全体的な構造はそのままです。
メイン インターフェイスがシステム トレイ アイコンである Win32 アプリケーションに取り組んでいます。HWND_MESSAGE
を親として使用して、アイコンのメッセージを受け取るダミー ウィンドウを作成します。
WNDCLASSEX wndClass;
wndClass.lpfnWndProc = &iconWindowProc;
// ...
iconWindowHandle = CreateWindow(wndClass.lpszClassName, _T(""), 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_MESSAGE, NULL, GetModuleHandle(NULL), 0);
次に、このメッセージのみのウィンドウを参照して、アイコンが作成されます。
NOTIFYICONDATA iconData;
iconData.hWnd = iconWindowHandle;
iconData.uCallbackMessage = TRAYICON_MESSAGE;
// ...
Shell_NotifyIcon(NIM_ADD, &iconData)
トレイ アイコンがダブルクリックされると、プロパティ シートを作成して表示します (からcomctl32.dll
):
LRESULT CALLBACK iconWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case TRAYICON_MESSAGE:
switch (lParam) { // that contains the "real" message
case WM_LBUTTONDBLCLK:
showPropertySheet();
return 0;
// ...
}
break;
// ...
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
プロパティ シートに親ウィンドウがありません。メッセージ専用ウィンドウのPropertySheet
ウィンドウプロシージャから関数を呼び出します。PSH_MODELESS
フラグは設定されていません。したがって、PropertySheet
プロパティ シート ウィンドウが再び閉じられた後にのみ返されます。
void showPropertySheet() {
PROPSHEETPAGE pages[NUM_PAGES];
pages[0].pfnDlgProc = &firstPageDialogProc;
// ...
PROPSHEETHEADER header;
header.hwndParent = NULL;
header.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK;
header.ppsp = pages;
// ...
PropertySheet(&header);
}
プロパティ シートのいずれかのページのダイアログ プロシージャ内にブレークポイントを設定するまで、これはすべて正常に機能します。
BOOL CALLBACK firstPageDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
return FALSE; // breakpoint here
}
プログラムがブレークポイントで停止すると、タスクバー全体がロックされます!
コール スタックはまったく役に立ちません。これは、ダイアログ プロシージャが、 内comctl32.dll
のいくつかの呼び出しを介して、 内のどこかから呼び出されることを示していますuser32.dll
。私自身のウィンドウプロシージャは間にありません。
プロパティ シートをモードレスにしても効果がないようです。また、コードが複雑になるため、これは避けたいと思います。
ダイアログ プロシージャが十分に迅速に返される限り、これは問題にはなりません。しかし、ダイアログ プロシージャ内でより長い操作を行うと、ダイアログ自体だけでなく、シェル全体がロックされるのは非常に奇妙に思えます。メッセージのみのウィンドウ プロシージャは、トレイ アイコンと密接に関連しているため、この動作を引き起こす力があると想像できますが、この関数はコール スタックには表示されません。
私は根本的に間違ったことをしていますか?誰でもこの問題に光を当てることができますか?