user18490
user18490

Reputation: 3839

Windows 10 Window Resizing Stuck After Forcing Immediate Redraw

I'm experiencing unexpected behavior when resizing a Windows 10 window while forcing an immediate redraw.

Questions:

  1. Why does this happen?

  2. Is it possible to force an immediate redraw while keeping normal resizing behavior? If so, how can I ensure that the window stops resizing once I release the mouse?

Context: I think I understand what RedrawWindow does—it schedules a WM_PAINT event, meaning that other events can be processed before the window is actually redrawn(?) Ideally, I would like to force an immediate redraw so that I can process data as a result of that redraw in the main loop after RedrawWindow is executed. This is why I attempted to switch to RedrawWindow(window, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); however, I then realized that resizing breaks with this change—likely due to my lack of understanding of the Windows API.

Here is a (hopefully) reproducible example that demonstrates this behavior.

// clang -std=c23 -o win_resize_stuck.exe -luser32 -lgdi32 ./win_resize_stuck.c

#include <stdio.h>
#include <assert.h>
#include <string.h>

#include <windows.h>
#include <windowsx.h>

static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CREATE:
            //DragAcceptFiles(hWnd, TRUE);
            break;
        case WM_CLOSE:
            PostQuitMessage(/* exit code */ 0);
            break;
        case WM_PAINT:
            break;
        case WM_SIZE:
            break;
        case WM_LBUTTONDOWN:
        case WM_MBUTTONDOWN:
        case WM_RBUTTONDOWN:
            break;
        case WM_LBUTTONUP:
        case WM_MBUTTONUP:
        case WM_RBUTTONUP:
            break;
        case WM_MOUSEMOVE:
            break;
        case WM_MOUSEWHEEL:
            break;
        case WM_KEYDOWN:
            break;
        case WM_KEYUP:
            break;
        default:
            break;
    }
    return (DefWindowProc(hWnd, uMsg, wParam, lParam));
}


//HINSTANCE connection;
HWND window;
#define WIN_CLASS_NAME "tmp"
#define APP_NAME "tmp"

static void create_window() {
    WNDCLASSEX win_class;
    win_class.cbSize = sizeof(WNDCLASSEX);
    win_class.style = CS_HREDRAW | CS_VREDRAW;
    win_class.lpfnWndProc = WndProc;
    win_class.cbClsExtra = 0;
    win_class.cbWndExtra = 0;
    win_class.hInstance = GetModuleHandle(NULL);
    win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
    win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    win_class.lpszMenuName = NULL;
    win_class.lpszClassName = "tmp";
    win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
    if (!RegisterClassEx(&win_class)) {
        fprintf(stderr, "Unexpected error trying to start the application!\n");
        fflush(stderr);
        exit(1);
    }
    RECT wr = {0, 0, 500, 500};
    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
    window = CreateWindowEx(0,
                            WIN_CLASS_NAME,
                            APP_NAME,
                            WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_SYSMENU,
                            100, 100,
                            wr.right - wr.left,
                            wr.bottom - wr.top,
                            NULL,
                            NULL,
                            GetModuleHandle(NULL),
                            NULL);
}

int main(int argc, const char** argv) {
    (void)argc;
    (void)argv;

    create_window();

    MSG msg;
    bool done = false;
    while (!done) {
        PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
        if (msg.message == WM_QUIT) {
            done = true;
        }
        else {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        RedrawWindow(window, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); //RDW_INTERNALPAINT);
    }
    return 0;
}

Upvotes: 2

Views: 57

Answers (0)

Related Questions