【问题标题】:Win32 application exits immediately when dialog box is closedWin32 应用程序在对话框关闭时立即退出
【发布时间】:2012-04-29 01:05:09
【问题描述】:

[编辑补充:原来答案很无聊,和Win32、对话框等无关。我只是在我的代码中有一个愚蠢的错误。感谢 Hans Passant 发现它。]

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


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

该应用程序是用 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;

对话框的过程如下所示:

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;

【问题讨论】:

    标签: c++ c


    【解决方案1】:

    您的 WndProc() 函数中存在错误。 WM_COMMAND 案例缺少休息。所以当它执行时,比如说,IDM_ABOUT 然后它落入 WM_DESTROY 情况。再见。

    我推荐 PC-lint。

    【讨论】:

      猜你喜欢
      • 2011-04-11
      • 2013-03-15
      • 1970-01-01
      • 2018-12-06
      • 2017-04-14
      • 2020-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多