Win32应用程序在关闭对话框时立即退出
问题描述:
[编辑添加:事实证明,答案非常无聊,与Win32,对话框等无关。我只是在我的代码中有一个白痴错误。感谢Hans Passant发现它。]Win32应用程序在关闭对话框时立即退出
(这是有点长。内容提要:我有一个简单的Win32应用程序,在通知区域创建一个图标,从不显示其主窗口,并有一个“约”框这可以通过右键单击通知区域图标来显示,因为我无法理解,当“about”框显示然后关闭时,应用程序的主消息循环会收到退出消息并退出。我做了错误的原因?)
我正在写一个小程序,在通知区域位于(“系统托盘”),并做处理各种不相关的,在此位的背景。它的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;
答
WndProc()函数存在一个错误。 WM_COMMAND案例缺少一个中断。所以,当它执行时,比如说IDM_ABOUT,它会进入WM_DESTROY的情况。再见。
我推荐PC-lint。
哟,你说得对。多么可怕。谢谢! – 2012-04-18 14:40:41