Why is my property bar shown in the system tray icon blocking the taskbar?

Note: The code examples have been simplified, but the general structure remains intact.

I am working on a Win32 application whose main interface is the system tray icon. I am creating a dummy window using HWND_MESSAGE

as parent to receive icon messages:

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);

      

Then the icon is created by referencing this message-only window:

NOTIFYICONDATA iconData;
iconData.hWnd = iconWindowHandle;
iconData.uCallbackMessage = TRAYICON_MESSAGE;
// ...
Shell_NotifyIcon(NIM_ADD, &iconData)

      

When the tray icon is double clicked, I create and show a property sheet (from 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);
}

      

There is no parent window in the property sheet. The function PropertySheet

is called from a message-only window procedure. The flag is PSH_MODELESS

not set; thus, it PropertySheet

only returns after the properties window is closed:

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);
}

      

This all works fine now, until I set a breakpoint in a dialog routine of one of the property sheet pages:

BOOL CALLBACK firstPageDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  return FALSE; // breakpoint here
}

      

When the program stops at a breakpoint, the entire taskbar is locked !

The call table is completely useless; it shows that the dialog procedure is being called somewhere inside comctl32.dll

through some calls inside user32.dll

. No window procedure is in between.

Creating a model of modelessness doesn't help. Also, I would prefer not to do this, because it makes the code more complex.

As long as my dialog routine returns quickly enough this shouldn't be a problem. But it seems strange that a longer operation within the dialogue procedure will not only close the dialogue itself, but also the entire shell. I can imagine that the message-only window routine has the power to invoke this behavior as it is more closely related to the tray icon ... but this function does not appear on the call stack.

Am I doing something fundamentally wrong? Can anyone shed some light on this issue?

+2


source to share


1 answer


Actually, this is pretty obvious, and the confusion must have been due to the lack of coffee.

The taskbar is probably using SendMessage

to send a message to my app, which causes it to block until the message is processed. SendMessageTimeout

is apparently not used.



It still seems strange to me that my function doesn't appear on the call stack. Surely such a message must go through my message loop for processing? Perhaps the warning that "the frame stack below this line may be incomplete or missing" was indeed correct.

+1


source







All Articles