WM_PAINT返回值异常引发CPU占用及OpenGL绘制问题求助
1. Why CPU sits at ~1% even when minimized (returning 0/1 from WM_PAINT)
Here’s the core issue: Win32’s WM_PAINT message runs on a "pending request" system. When the system thinks your window needs redrawing, it queues a WM_PAINT message—but it won’t stop sending it until you explicitly confirm the redraw is handled.
If you’re just returning 0 or 1 without calling BeginPaint() and EndPaint(), the system never gets the signal that the redraw is done. So it keeps spamming your message loop with WM_PAINT, even when the window is minimized. That constant, low-effort message processing is why you’re seeing a steady 1% CPU usage—your app is stuck looping through the same unacknowledged redraw request over and over.
2. Skipping WM_PAINT causes resize glitches with OpenGL
OpenGL rendering is tightly tied to your window’s size and device context. When you resize the window, two critical things need to happen:
- You have to update the OpenGL viewport (
glViewport()) to match the new window dimensions - You probably need to adjust your projection matrix to avoid stretching or skewing your scene
If you skip the WM_PAINT flow, you’re missing the trigger to re-render the scene with the updated viewport/matrix. The system will keep drawing using the old window size, leading to those weird resize artifacts—think black bars, stretched graphics, or partial draws.
Pro tip: Handle the WM_SIZE message to update your OpenGL state, then call InvalidateRect() to trigger a WM_PAINT. This ensures the scene gets re-rendered with the new dimensions every time the window resizes.
3. Why CPU spikes to 15% when removing WM_PAINT function calls
This is an amplified version of the first problem. If you strip out all code from your WM_PAINT handler—no rendering, no BeginPaint()/EndPaint()—the system keeps sending WM_PAINT messages, and your app processes them extremely fast, like thousands of times per second. Since there’s no heavy OpenGL rendering to slow things down, your CPU gets pegged handling these constant, unacknowledged messages, hence the 15% spike.
Fixes to Get Everything Working Smoothly
Let’s turn these explanations into actionable fixes:
Always pair
BeginPaint()andEndPaint()in WM_PAINT: Even if you don’t need to render anything (like when the window is minimized), these functions tell the system you’ve handled the redraw request, stopping the spam. Here’s a quick example:case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // Only render if the window is visible (skip when minimized) if (IsWindowVisible(hwnd)) { // Bind your OpenGL context, update viewport to the redraw area glViewport(0, 0, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top); // Draw your scene here SwapBuffers(hdc); } EndPaint(hwnd, &ps); return 0; }Handle WM_SIZE properly for OpenGL: Catch the resize event, update your OpenGL state, then trigger a redraw:
case WM_SIZE: { int newWidth = LOWORD(lParam); int newHeight = HIWORD(lParam); // Update OpenGL viewport to match new window size glViewport(0, 0, newWidth, newHeight); // Adjust projection matrix (example for perspective rendering) glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (float)newWidth / newHeight, 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); // Tell the window it needs to redraw with the new state InvalidateRect(hwnd, NULL, FALSE); return 0; }Skip rendering when minimized: As shown in the WM_PAINT example, using
IsWindowVisible()lets you skip heavy OpenGL calls when the window isn’t visible, keeping CPU usage low while still acknowledging the WM_PAINT request.
内容的提问来源于stack exchange,提问作者ciyaso

