2011-04-26 120 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