Reputation: 19981
[EDITED to add: It turns out that the answer is very boring and has nothing to do with Win32, dialog boxes, etc. I just had an idiotic bug in my code. Thanks to Hans Passant for spotting it.]
(This is kinda long. Executive summary: I have a simple Win32 application which creates an icon in the notification area, never shows its main window, and has an "about" box that can be displayed via a right-click on the notification-area icon. For no reason I can fathom, when the "about" box is shown and then closed, the application's main message loop gets a quit message and it exits. What could I have done wrong to cause this?)
I'm writing a little program that sits in the notification area ("system tray") and does various not-relevant-here bits of processing in the background. Its UI is almost trivial: you can right-click on the notification-area icon to get a menu, with options "Exit" and "About"; the former quits, the latter pops up a little about-this-program modal dialog.
The application is written in C++ and uses Win32 directly (no MFC or anything). My apologies for being stuck in the stone age.
The only problem is this: when the "About" dialog is closed, the program exits! What could be causing this?
I'm not sure what further information is most useful in figuring this out. Here are a few observations.
Perhaps there's something crazy, or something missing, in my code. Here are some extracts (with a few details, which may not be relevant, elided for brevity).
The rough structure of my WinMain is as follows:
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;
The main window's WndProc looks like this:
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;
and the dialog box's proc looks like this:
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;
Upvotes: 4
Views: 2393
Reputation: 942257
There's a bug in your WndProc() function. The WM_COMMAND case is missing a break. So when it executes, say, IDM_ABOUT then it falls through into the WM_DESTROY case. Sayonara.
I recommend PC-lint.
Upvotes: 4