Hinweis: Die Codebeispiele wurden vereinfacht, die Gesamtstruktur bleibt jedoch erhalten.
Ich arbeite an einer Win32-Anwendung, deren Hauptschnittstelle ein Symbol in der Taskleiste ist. Ich erstelle ein Dummy-Fenster, indem ich HWND_MESSAGE
als übergeordnetes Element, um die Nachrichten des Symbols zu empfangen:
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);
Dann wird das Symbol erstellt, das auf dieses Fenster verweist, das nur Nachrichten enthält:
NOTIFYICONDATA iconData;
iconData.hWnd = iconWindowHandle;
iconData.uCallbackMessage = TRAYICON_MESSAGE;
// ...
Shell_NotifyIcon(NIM_ADD, &iconData)
Wenn das Tray-Symbol doppelt angeklickt wird, wird ein Eigenschaftsblatt erstellt und angezeigt (aus 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);
}
Das Eigenschaftsblatt hat kein übergeordnetes Fenster. Das PropertySheet
Funktion wird von der Fensterprozedur des reinen Nachrichtenfensters aufgerufen. Die PSH_MODELESS
Flagge nicht gesetzt ist; daher, PropertySheet
kehrt erst zurück, wenn das Eigenschaftsblattfenster wieder geschlossen wird:
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);
}
All dies funktioniert gut, bis ich einen Haltepunkt in der Dialogprozedur auf einer der Seiten des Eigenschaftsblatts setze:
BOOL CALLBACK firstPageDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
return FALSE; // breakpoint here
}
Wenn das Programm an dem Haltepunkt anhält, die gesamte Taskleiste wird blockiert !
Der Aufrufstapel ist ziemlich nutzlos; er zeigt, dass die Dialogprozedur von irgendwo innerhalb von comctl32.dll
über einige Aufrufe innerhalb user32.dll
. Kein eigenes Fensterverfahren liegt dazwischen.
Das Eigenschaftsblatt modellfrei zu machen, scheint nicht zu helfen. Außerdem würde ich lieber nicht tun dies, weil es den Code komplexer macht.
Solange mein Dialogverfahren schnell genug zurückkehrt, sollte dies kein Problem sein. Aber es scheint so seltsam, dass eine längere Operation innerhalb der Dialogprozedur nicht nur den Dialog selbst, sondern die gesamte Shell sperren würde. Ich kann mir vorstellen, dass die Prozedur "message-only window" die Macht hat, dieses Verhalten zu verursachen, da sie enger mit dem Tray-Icon verbunden ist... aber diese Funktion wird nicht auf dem Aufrufstapel angezeigt.
Mache ich etwas grundlegend falsch? Kann jemand etwas Licht in diese Angelegenheit bringen?