(Win32/GDI+) Real-time rendering uses too much CPU

thebluetropics 1,046 Reputation points
2023-03-19T14:53:05.85+00:00

Hi.

I am currently trying to build a win32 program that shows a constantly updating window, using GDI+.

Here is the code to paint the window:

bool PaintWindow(HWND _phwnd, HDC hdc) {
    RECT clientRect;
    GetClientRect(_phwnd, &clientRect);

    HDC hdcMemory = CreateCompatibleDC(hdc);
    HBITMAP hbitmapMemory = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom);
    HBITMAP hbitmapOld = static_cast<HBITMAP>(SelectObject(hdcMemory, hbitmapMemory));
    // Draw begin
    
    Gdiplus::Graphics graphics(hdcMemory);
    graphics.SetPixelOffsetMode(Gdiplus::PixelOffsetModeNone);

    Gdiplus::SolidBrush brush(Gdiplus::Color(255, color, color, color));
    graphics.FillRectangle(&brush, Gdiplus::Rect(0, 0, clientRect.right, clientRect.bottom));
    
    // Draw end
    BitBlt(hdc, 0, 0, clientRect.right, clientRect.bottom, hdcMemory, 0, 0, SRCCOPY);
    SelectObject(hdcMemory, hbitmapOld);
    DeleteDC(hdcMemory);
    DeleteObject(hbitmapMemory);

    color++;

    return true;
}

Here is the WM_PAINT message handle:

case WM_PAINT: {
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(_phwnd, &ps);

    if (!PaintWindow(_phwnd, hdc)) return 1;

    EndPaint(_phwnd, &ps);
    return 0;
}

And, here is the window loop:

while (true) {
    if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
        if (msg.message == WM_QUIT) break;

        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    } else {
        HDC hdc = GetDC(hwnd);
        if (!PaintWindow(hwnd, hdc)) break;
    }
}

The things that I want to achieve is, constantly update the entire client area, matching the monitor's refresh rate.

I have successfully do that in several way, including:

  1. Calling InvalidateRect() after every WM_PAINT
  2. The example above

But all of my trial end up with one of these problems:

  1. High CPU usage
  2. The client area doesn't update when the window is being dragged

I know that High CPU usage is due to the behavior of PeekMessageW(). But, how do most apps update their frequently updating their client area without having such high CPU usage?

And, is it also possible to constantly update only part of the client area? As updating the entire client area would be expensive.

Any help would be appreciated. Thanks!

Windows development | Windows API - Win32
{count} votes

Answer accepted by question author
  1. Castorix31 91,511 Reputation points
    2023-03-19T18:21:21.28+00:00

    But all of my trial end up with one of these problems: High CPU usage

    A way is by adding Sleep/SleepEx (with 1 for example) in the loop

    The client area doesn't update when the window is being dragged

    You must use Direct2D (like in one of your threads : https://learn.microsoft.com/en-us/answers/questions/1020183/how-to-keep-real-time-wm-paint-in-win32-applicatio)

    (Sleep not needed)

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.