在 Win32 中处理 SDL 事件 window

Handling SDL events inside Win32 window

我在 Win32 window 中处理 SDL 事件有困难。我做了一个小程序来显示洋红色背景。基本上当用户按下 'q' 键时,背景颜色应该从洋红色切换到红色,反之亦然。

sdlwin.c

#include <windows.h>

#include <SDL2/SDL.h>

const int win_width = 500;
const int win_height = 450;

int b = 0;

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static SDL_Window *sdlWnd;
    SDL_Surface *surface;

    switch (msg)
    {
    case WM_CREATE:
        if(SDL_Init(SDL_INIT_VIDEO) < 0)
        {
            MessageBox(hWnd, TEXT("SDL cannot be initialized!"), TEXT("Error!"),
                MB_ICONEXCLAMATION | MB_OK);
            PostQuitMessage(0);
        }

        sdlWnd = SDL_CreateWindowFrom(hWnd);

        if (sdlWnd == NULL)
        {
            MessageBox(hWnd, TEXT("SDL window cannot be created!"), TEXT("Error!"),
                MB_ICONEXCLAMATION | MB_OK);
            SDL_Quit();
            PostQuitMessage(0);
        }

        SDL_SetWindowTitle(sdlWnd, "SDL Window");

        break;
    case WM_PAINT:
        surface = SDL_GetWindowSurface(sdlWnd);
        SDL_FillRect(surface, &surface->clip_rect, b ? 0xFFFF00FF : 0xFFFF0000);
        SDL_UpdateWindowSurface(sdlWnd);
        break;
    case WM_CLOSE:
        SDL_DestroyWindow(sdlWnd);
        SDL_Quit();
        DestroyWindow(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }

    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    const TCHAR szClassName[] = TEXT("MyClass");

    WNDCLASS wc;
    HWND hWnd;
    MSG msg;

    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = szClassName;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClass(&wc))
    {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    hWnd = CreateWindow(szClassName,
        TEXT("SDLWin"),
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT, win_width, win_height,
        NULL, NULL, hInstance, NULL);

    if (hWnd == NULL)
    {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    SDL_Event e;

    while (GetMessage(&msg, NULL, 0, 0))
    {
        while (SDL_PollEvent(&e) != 0)
        {
            if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_q)
            {
                b = !b;
                //MessageBox(NULL, TEXT("bar"), TEXT("foo"), MB_ICONEXCLAMATION | MB_OK);
            }
        }

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

当我取消注释这一行 MessageBox(NULL, TEXT("bar"), TEXT("foo"), MB_ICONEXCLAMATION | MB_OK); 时,当我按下 'q' 键时 window 没有响应,但是如果我添加这一行, window 背景颜色关闭消息框后更改。我不确定为什么会发生这种奇怪的行为。我的问题是如何在 Win32 window 中正确处理 SDL 事件。感谢任何形式的帮助。

你需要调用 InvalidateRect(hWnd, NULL, TRUE/FALSE);改变后 b. 这将 post 一条 WM_Paint 消息供您 Window 重绘。