2011-04-26 151 views
1

我的應用程序有一個消息窗口,它是從新創建的線程啓動的。線程函數創建消息窗口並運行消息泵。我遇到的問題是消息泵永遠不會得到WM_CLOSE消息。我刪除了錯誤處理來簡化發佈的代碼。有誰知道我做錯了什麼?無法關閉僅消息窗口 - C++

構造:

this->m_hInstance = ::GetModuleHandle(NULL); 

this->m_wcx.cbSize = sizeof(WNDCLASSEX); // size of structure 
this->m_wcx.style = CS_HREDRAW | CS_VREDRAW; // initially minimized 
this->m_wcx.lpfnWndProc = &WndProc;  // points to window procedure 
this->m_wcx.cbClsExtra = 0;    // no extra class memory 
this->m_wcx.cbWndExtra = 0;    // no extra window memory 
this->m_wcx.hInstance = m_hInstance;  // handle to instance 
this->m_wcx.hIcon = ::LoadIcon(NULL, IDI_APPLICATION); // default app icon 
this->m_wcx.hCursor = ::LoadCursor(NULL, IDC_ARROW); // standard arrow cursor 
this->m_wcx.hbrBackground = NULL;   // no background to paint 
this->m_wcx.lpszMenuName = NULL;   // no menu resource 
this->m_wcx.lpszClassName = s_pwcWindowClass; // name of window class 
this->m_wcx.hIconSm = NULL;    // search system resources for sm icon 

this->m_atom = ::RegisterClassEx(&m_wcx); 

this->m_hNotifyWindowThread = ::CreateThread(
    NULL,       // no security attributes 
    0,        // use default initial stack size 
    reinterpret_cast<LPTHREAD_START_ROUTINE>(NotifyWindowThreadFn), // function to execute in new thread 
    NULL,       // thread parameters 
    0,        // use default creation settings 
    NULL       // thread ID is not needed 
    ); 

析構函數:

::DestroyWindow(this->m_hWnd); 
::WaitForSingleObject(this->m_hNotifyWindowThread, NW_DEFAULT_TIMEOUT); // <-- Seems to get stuck here. 
::UnregisterClass(s_pwcWindowClass, this->m_hInstance); 

線程功能:

s_ptInterface->pobjNotifyWindow->m_hWnd = ::CreateWindow(
    s_pwcWindowClass,    // window class name 
    s_pwcWindowName,    // window name 
    WS_ICONIC,      // window style is minimized 
    0,        // initial horizontal position 
    0,        // initial vertical position 
    CW_USEDEFAULT,     // window width 
    0,        // window height 
    NULL,       // no parent window 
    NULL,       // no menu 
    s_ptInterface->pobjNotifyWindow->GetInstanceHandle(), // associated instance 
    NULL       // no additional info for WM_CREATE 
    ); 

::ShowWindow(s_ptInterface->pobjNotifyWindow->GetWindowHandle(), SW_HIDE); 
::UpdateWindow(s_ptInterface->pobjNotifyWindow->GetWindowHandle(); 

dbt.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); 
dbt.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 
dbt.dbcc_classguid = s_guidForCP210xDevices; 

m_hNotify = RegisterDeviceNotification(m_hWnd, &dbt, DEVICE_NOTIFY_WINDOW_HANDLE); 

while ((blRetVal = ::GetMessage(
    &msg,       // message structure 
    NULL,       // retrieve messages for all windows on this thread 
    0,        // lowest message value to retrieve 
    0        // highest message value to retrieve 
    )) != 0) 
{ 
    if (blRetVal == -1) 
    { 
     return ::GetLastError(); 
    } 
    else 
    { 
     ::TranslateMessage(&msg); 
     ::DispatchMessage(&msg); 
    } 
} 

窗口過程:

switch (uMsg) 
{ 
case WM_CLOSE: 
    if (m_hNotify != NULL) 
    { 
     ::UnregisterDeviceNotification(m_hNotify); 
     m_hNotify = NULL; 
    } 

    ::DestroyWindow(hWnd); 
    break; 

case WM_DESTROY: 
    ::PostQuitMessage(0); 
    break; 

case WM_DEVICECHANGE: 
    if (pHeader != NULL) 
    { 
     if (pHeader->dbch_devicetype == DBT_DEVTYP_PORT) 
     { 
      switch (wParam) 
      { 
      case DBT_DEVICEREMOVECOMPLETE:  // Device is gone 
       ::EnterCriticalSection(&(s_ptInterface->csSerialPort)); 
       s_ptInterface->pobjSerialPort->Close(); 
       ::LeaveCriticalSection(&(s_ptInterface->csSerialPort)); 
       break; 

      case DBT_DEVICEARRIVAL:    // System detected device 
       ::EnterCriticalSection(&(s_ptInterface->csSerialPort)); 
       s_ptInterface->pobjSerialPort->Open(); 
       ::LeaveCriticalSection(&(s_ptInterface->csSerialPort)); 
       break; 

      default: 
       // Do nothing. 
       break; 
      } 
     } 
    } 
    break; 

default: 
    // Do nothing. 
    break; 
} 

return ::DefWindowProc(hWnd, uMsg, wParam, lParam); 

回答

2

當Windows要求您的應用程序關閉窗口時,會發送WM_CLOSE。當用戶點擊右上角的關閉按鈕或按下Alt + F4時。沒有這種情況發生,你調用DestroyWindow()。您需要使用WM_DESTROY。這很好,不需要否決關閉請求。

+0

如果我理解正確,因爲這是一個只有消息的窗口(隱藏給用戶)並且從析構函數調用DestroyWindow,所以不需要處理WndProc中的WM_CLOSE消息。這仍然會讓PC在析構函數中陷入'WaitForSingleObject'問題。我如何向窗口發送一條WM_DESTROY消息?我以爲'DestroyWindow'做到了。 – 2011-04-27 13:36:18

+0

唯一想到的是我使用's_ptInterface-> pobjNotifyWindow->'這樣的指針來訪問我爲此只消息窗口編寫的'CNotifyWindow'類的公共成員。你認爲我應該讓這些共享資源成爲靜態全局變量,而不是公共類成員?我在過去遇到過很多關鍵部分的問題。 – 2011-04-27 13:39:43

+1

好的,我明白了。消息使用SendMessage發送。通過在析構函數中用'SendMessage'切換出DestroyWindow來發送'WM_CLOSE'解決了這個問題。感謝您指點我正確的方向! – 2011-04-27 14:45:13