2012-04-17 46 views
3

[追加された編集:非常に退屈で、Win32、ダイアログボックスなどとは何の関係もないことが判明しました。エグゼクティブサマリー:通知エリアにアイコンを作成し、メインウィンドウを表示せず、「約」ボックスを持っているシンプルなWin32アプリケーションがあります。通知領域アイコンを右クリックして表示することができます。なぜなら、「約」ボックスが表示されて閉じられると、アプリケーションのメインメッセージループは終了メッセージを受け取って終了します。私はこれを引き起こすことが間違って行っている?)ダイアログボックスが閉じられるとすぐにWin32アプリケーションが終了する


を私は通知領域(「システムトレイ」)に座っていると、バックグラウンドでの処理の様々な関連はない - ここにビットを行う小さなプログラムを書いています。そのUIはほとんどありません。通知領域アイコンを右クリックするとメニューが表示され、「Exit」と「About」のオプションがあります。前者は終了し、後者はこのプログラムのモーダルダイアログを少しポップアップさせます。

アプリケーションはC++で書かれており、Win32を直接使用します(MFCなどはありません)。私は石の時代に立ち往生して謝っています。

唯一の問題は次のとおりです。「バージョン情報」ダイアログが閉じると、プログラムが終了します。これは何が原因でしょうか?

これを理解する上で、どのような詳細情報が最も有用かはわかりません。ここにいくつかの観察があります。

  • ダイアログの[OK]ボタンをクリックした後、アプリケーションの終了時に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を取得します。
    • アプリケーションウィンドウは、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はメインメッセージループ(メッセージはWM_QUIT)で0を返し、それはすべて終了します。
  • 私のコードで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

よろしいですか。なんてひどい。ありがとう! –

関連する問題