关闭对话框时,Win32应用程序立即退出

时间:2012-04-17 16:50:38

标签: c++ c

[编辑补充说:事实证明答案很无聊,与Win32,对话框等无关。我的代码中只有一个愚蠢的错误。感谢Hans Passant发现它。]

(这有点长。执行摘要:我有一个简单的Win32应用程序,它在通知区域中创建一个图标,从不显示其主窗口,并且有一个“about”框,可以通过右键单击显示通知区域图标。我无法理解,当显示“关闭”框然后关闭时,应用程序的主消息循环会收到退出消息并退出。我可能做错了导致这种情况?)< / p>


我正在编写一个位于通知区域(“系统托盘”)中的小程序,并在后台执行各种不相关的处理。它的UI几乎是微不足道的:您可以右键单击通知区域图标以获取菜单,选项“退出”和“关于”;前者退出,后者弹出一点关于这个程序模态对话框。

应用程序是用C ++编写的,直接使用Win32(没有MFC或任何东西)。我为陷入石器时代而道歉。

唯一的问题是:当“关闭”对话框关闭时,程序会退出! 可能导致此问题的原因是什么?

我不确定哪些进一步的信息对于解决这个问题最有用。以下是一些观察结果。

  • 在单击对话框的“确定”按钮后,应用程序生命周期结束时的Windows消息序列如下所示。
    • 对话框的proc获取WM_CTLCOLORBTN
    • 应用程序(不可见)主窗口获取WM_ENABLE(TRUE)。
    • 对话框获取WM_CTLCOLORBTN,WM_IMESETCONTEXT,WM_SETFOCUS,WM_WINDOWPOSCHANGING,WM_WINDOWPOSCHANGED,3xWM_GETICON,WM_NCACTIVATE,2xWM_GETICON,WM_ACTIVATE,WM_WINDOWPOSCHANGING。
    • 应用程序的窗口ges WM_WINDOWPOSCHANGING,WM_NCACTIVATE,消息0x93,0x93,0x91,0x92,0x92(这些是什么?),WM_ACTIVATE。
    • 对话框获取WM_KILLFOCUS,WM_IME_SETCONTEXT。
    • 应用程序窗口获取WM_IME_SETCONTEXT。
    • 对话框获取WM_IME_NOTIFY;应用程序的主窗口也是如此。
    • 应用程序窗口获取WM_SETFOCUS。
    • 对话框获取消息0x90,WM_DESTROY,WM_NCDESTROY。
  • 在这些对话窗口的proc或主应用程序窗口之后没有其他消息。
  • 然后GetMessage在主消息循环中返回0(消息是WM_QUIT),它全部结束。
  • 我的代码中对PostQuitMessage的唯一调用是在主窗口的WndProc中,它发生在主窗口获得WM_DESTROY时,实际上并没有在这种情况下调用它。

在我的代码中可能有一些疯狂或缺失的东西。以下是一些摘录(有一些细节,可能不相关,为简洁而省略)。

我的WinMain的粗略结构如下:

WNDCLASSEX wc;
// fill in fields of wc
RegisterClassEx(&wc);

HWND w = CreateWindow(...);

NOTIFYICONDATA nid;
memset(&nid, 0, sizeof(nid));
// fill in fields of nid
Shell_NotifyIcon(NIM_ADD, &nid);

// (start a background thread to do the real work,
// which is of no interest here)

MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
  if (TranslateAccelerator(msg,hwnd, accel, &msg)) continue;
  TranslateMesage(&msg);
  DispatchMessage(&msg);
}

Shell_NotifyIcon(NUM_DELETE, &nid);
return (int)msg.wParam;

主窗口的WndProc如下所示:

switch (message) {
  case WM_USER_SHELLICON: // my own, attached to the icon's menu
    if (LOWORD(lParam) == WM_RBUTTONDOWN) // ... create menu and return TRUE
    break;
  case WM_COMMAND:
    // menu item
    switch (LOWORD(wParam)) {
      case IDM_ABOUT:
        DialogBox(the_instance, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutProc);
        break;
      case IDM_EXIT:
        DestroyWindow(hWnd);
        break;
      default: return DefWindowProc(hWnd, message, wParam, lParam);
    }
  case WM_DESTROY:
    PostQuitMessage(0);
    break;
  default: return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;

并且对话框的proc看起来像这样:

switch (message) {
  case WM_INITDIALOG:
    // fill in a version string
    return (INT_PTR)TRUE;
  case WM_COMMAND:
    if (LOWORD(wParam)==IDOK || LOWORD(wParam)==IDCANCEL) {
      EndDialog(hDlg, LOWORD(wParam));
      return (INT_PTR)TRUE;
    }
    break;
}
return (INT_PTR)FALSE;

1 个答案:

答案 0 :(得分:4)

您的WndProc()函数中存在错误。 WM_COMMAND案例没有中断。因此,当它执行时,比如IDM_ABOUT,然后它会进入WM_DESTROY案例。再见。

我推荐使用PC-lint。