2009-09-30 3 views
2

Примечание: образцы кода были упрощены, но общая структура остается нетронутой.Почему моя панель свойств, показанная на значке в системном трее, блокирует панель задач?

Я работаю над приложением 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. Никакая оконная процедура не находится между ними.

Выполнение этой функции не помогает. Кроме того, я бы предпочел не делать этого, потому что это делает код более сложным.

До тех пор, пока моя процедура диалога вернется достаточно быстро, это не должно быть проблемой. Но кажется странным, что более длительная операция внутри процедуры диалога не только закроет сам диалог, но и всю оболочку. Я могу представить, что процедура окна только для сообщений имеет право вызвать такое поведение, поскольку оно более тесно связано с значком в трее ... но эта функция не отображается в стеке вызовов.

Я делаю что-то принципиально неправильно? Может ли кто-нибудь пролить свет на эту проблему?

ответ

1

На самом деле, это довольно очевидно, и путаница, должно быть, была из-за нехватки кофе.

Панель задач, вероятно, использует SendMessage для отправки сообщения в мое приложение, которое заставляет его блокировать до тех пор, пока сообщение не будет обработано. SendMessageTimeout, по-видимому, не используется.

Я все еще думаю, что странно, что в стеке вызовов нет никакой функции. Разумеется, такое сообщение должно проходить через мой цикл сообщений для обработки? Возможно, предупреждение о том, что «стеки кадров ниже этой строки может быть неполным или отсутствующим», на самом деле было правильным.

 Смежные вопросы

  • Нет связанных вопросов^_^