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。私自身のウィンドウプロシージャは間にありません。

プロパティ シートをモードレスにしても効果がないようです。また、コードが複雑になるため、これは避けたいと思います。

ダイアログ プロシージャが十分に迅速に返される限り、これは問題にはなりません。しかし、ダイアログ プロシージャ内でより長い操作を行うと、ダイアログ自体だけでなく、シェル全体がロックされるのは非常に奇妙に思えます。メッセージのみのウィンドウ プロシージャは、トレイ アイコンと密接に関連しているため、この動作を引き起こす力があると想像できますが、この関数はコール スタックには表示されません。

私は根本的に間違ったことをしていますか?誰でもこの問題に光を当てることができますか?

4

1 に答える 1