麻烦关闭仅消息窗口 - C ++

时间:2011-04-26 22:05:53

标签: c++ winapi messagewindow

我的应用程序有一个仅从新创建的线程启动的消息窗口。线程函数创建仅消息窗口并运行消息泵。我遇到的问题是消息泵似乎永远不会得到WM_CLOSE消息。我删除了错误处理以简化发布的代码。有谁知道我做错了什么?

构造

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 );

1 个答案:

答案 0 :(得分:2)

当Windows要求您的应用关闭窗口时,会发送WM_CLOSE。当用户单击右上方的“关闭”按钮或按Alt + F4时。这些都不会发生,你叫DestroyWindow()。您需要使用WM_DESTROY。哪个没问题,不需要否决关闭请求。