2012-04-17 395 views
3

[編輯添加:事實證明,答案非常無聊,與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; 

回答

4

WndProc()函數存在一個錯誤。 WM_COMMAND案例缺少一箇中斷。所以,當它執行時,比如說IDM_ABOUT,它會進入WM_DESTROY的情況。再見。

我推薦PC-lint。

+0

喲,你說得對。多麼可怕。謝謝! – 2012-04-18 14:40:41

相關問題