C++ 如何正确处理win32 GUI消息循环?

C++ 如何正确处理win32 GUI消息循环?,c++,winapi,C++,Winapi,为了好玩,我正在制作一个简单的文本编辑器win32应用程序。我的程序有一个特殊的问题。我的程序退出时似乎没有返回零。相反,它返回了1385929。当我的主GUI窗口被破坏时,我使用PostQuitMessage 0,但这似乎不是我的主函数message.wParam中返回的内容。这是我到目前为止的代码 #define WIDTH 500 #define HEIGHT 400 #define EDIT_ID 10 LRESULT CALLBACK windowProc( HWND window

为了好玩,我正在制作一个简单的文本编辑器win32应用程序。我的程序有一个特殊的问题。我的程序退出时似乎没有返回零。相反,它返回了1385929。当我的主GUI窗口被破坏时,我使用PostQuitMessage 0,但这似乎不是我的主函数message.wParam中返回的内容。这是我到目前为止的代码

#define WIDTH 500
#define HEIGHT 400

#define EDIT_ID 10

LRESULT CALLBACK windowProc( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
{
    static HDC deviceContext = INVALID_HANDLE_VALUE;
    static HWND editControl = INVALID_HANDLE_VALUE;

    switch ( message )
    {
        case WM_CREATE :
            deviceContext = GetDC( window );

            if ( !deviceContext )
            {
                showWindowsError( "Creating Device Context", FALSE );
                DestroyWindow( window );
            }

            editControl = CreateWindow(
                                       "EDIT",
                                       NULL,
                                       WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT |
                                       ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL,
                                       0,
                                       0,
                                       0,
                                       0,
                                       window,
                                       ( HMENU )EDIT_ID,
                                       ( HINSTANCE )GetWindowLong( window, GWL_HINSTANCE ),
                                       NULL
                                      );

            if ( !editControl )
            {
                showWindowsError( "Creating Edit Control", TRUE );
                DestroyWindow( window );
            }

            return 0;
        break;

        case WM_COMMAND :
            switch ( wParam )
            {
                case WM_UNDO :
                    SendMessage( editControl, WM_UNDO, 0, 0 );
                break;

                case WM_CUT :
                    SendMessage( editControl, WM_CUT, 0, 0 );
                break;

                case WM_COPY :
                    SendMessage( editControl, WM_COPY, 0, 0 );
                break;

                case WM_PASTE :
                    SendMessage( editControl, WM_PASTE, 0, 0 );
                break;

                case WM_CLEAR :
                    SendMessage( editControl, WM_CLEAR, 0, 0 );
                break;

                default:
                    return DefWindowProc( window, message, wParam, lParam );
            }

        case WM_SIZE :
            MoveWindow( editControl, 0, 0, LOWORD( lParam ), HIWORD( lParam ), TRUE );

            return 0;
        break;

        case WM_DESTROY :
            ReleaseDC( window, deviceContext );
            DestroyWindow( editControl );
            PostQuitMessage( 0 );

            return 0;
        break;
    }

    return DefWindowProc( window, message, wParam, lParam );
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR CmdArgs, int nCmdShow )
{
    WNDCLASSEX windowClass = { 0 };
    HWND window = INVALID_HANDLE_VALUE;

    MSG message = { 0 };
    HBRUSH windowColor = CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );

    windowClass.cbSize = sizeof( windowClass );
    windowClass.style = CS_HREDRAW | CS_VREDRAW;
    windowClass.lpfnWndProc = windowProc;
    windowClass.hInstance = hInstance;
    windowClass.hCursor = LoadCursor( NULL, IDC_ARROW );
    windowClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    windowClass.hbrBackground = windowColor;
    windowClass.lpszClassName = "TextEditorWindow";

    if ( !RegisterClassEx( &windowClass ) )
    {
        DeleteObject( windowColor );
        showWindowsError( "Registering Windows Class", TRUE );
    }

    window = CreateWindow(
                           "TextEditorWindow",
                           "Text Editor",
                           WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
                           CW_USEDEFAULT,
                           CW_USEDEFAULT,
                           WIDTH,
                           HEIGHT,
                           NULL,
                           NULL,
                           hInstance,
                           NULL
                        );

    if ( !window )
    {
        DeleteObject( windowColor );
        showWindowsError( "Creating GUI", TRUE );
    }

    ShowWindow( window, SW_SHOW );
    UpdateWindow( window );

    do
    {
        TranslateMessage( &message );
        DispatchMessage( &message );
    } while ( GetMessage( &message, window, 0, 0 ) > 0 );

    DeleteObject( windowColor );
    return message.wParam;
}
对GetMessage的调用将第二个参数设置为窗口的HWND,这将接收的消息限制为仅发送到该窗口的消息-请参阅API函数的第页

另一方面,WM_QUIT是发送到运行消息泵的线程的消息,没有任何特定窗口。由于该筛选器,您不会收到它,并且message.wParam永远不会设置为该0

但是为什么循环结束,程序关闭了呢?由于窗口中的HWND在窗口关闭后无效,因此GetMessage以错误结束并返回-1

此外,您当前正在调用TranslateMessage和DispatchMessage with message,然后在第一次迭代中使用任何正确的数据填充它。循环应该是这样的:

while ( GetMessage( &message, NULL, 0, 0 ) > 0 )
{
    TranslateMessage( &message );
    DispatchMessage( &message );
}
对GetMessage的调用将第二个参数设置为窗口的HWND,这将接收的消息限制为仅发送到该窗口的消息-请参阅API函数的第页

另一方面,WM_QUIT是发送到运行消息泵的线程的消息,没有任何特定窗口。由于该筛选器,您不会收到它,并且message.wParam永远不会设置为该0

但是为什么循环结束,程序关闭了呢?由于窗口中的HWND在窗口关闭后无效,因此GetMessage以错误结束并返回-1

此外,您当前正在调用TranslateMessage和DispatchMessage with message,然后在第一次迭代中使用任何正确的数据填充它。循环应该是这样的:

while ( GetMessage( &message, NULL, 0, 0 ) > 0 )
{
    TranslateMessage( &message );
    DispatchMessage( &message );
}

首先,您应该在循环中首先调用GetMessage,然后再调用TranslateMessage和DispatchMessage。首先,您应该在循环中首先调用GetMessage,然后再调用TranslateMessage和DispatchMessage。+1解释循环终止的原因。您可能需要指出,传递无效HWND是其中一个条件,其中GetMessage返回的值低于零。除此之外,还有一个非常可靠的分析。+1用于解释循环为何终止。您可能需要指出,传递无效HWND是其中一个条件,其中GetMessage返回的值低于零。除此之外,一个非常可靠的分析。