2

When handling the WM_PAINT message, I omitted the BeginPaint and EndPaint calls, and the CPU usage shot up to 100%. Why is this?

I'm also using worker threads... but they do something different and seem to have no influence on this matter.

Also, can I use the device context from GetDC() rather than BeginPaint? They seem to have different values so I thought they had different jobs.

Sorry if I sound like an idiot - I'm new to WinAPI, C++ and just the world of logic in general...

Thanks

  • If you're new to C++, is there any particular reason you use the WinAPI at all? There's relatively little reason to directly use it nowadays, other than to maintain existing programs built on top of it. – Cubic Jan 25 '14 at 18:23
  • 1
    I expect that Begin/Endpaint are used to indicate to the OS that the WM_PAINT message has actually been dealt with. So if you don't use those calls, the OS keeps telling your app that it needs to draw something... – Mats Petersson Jan 25 '14 at 18:24
  • The DC returned by GetDC() is unbounded and has no clipping boundaries. The DC returned by BeginPaint returns a DC that represents the part of the window needing an update. If you paint outside this region, it gets clipped. From my observations, GDI operations on the DC returned by GetDC() have better performance than the same code on the DC returned by BeginPaint - especially if your code just redraws the entire window on each WM_PAINT. You can use the DC returned by GetDC in WM_PAINT, but you still need to call BeginPaint/EndPaint to indicate the region has been updated. – selbie Jan 25 '14 at 18:39

3 Answers3

8

This is entirely normal. Windows generates the WM_PAINT message when your window's update region in not empty. What you are supposed to do is mark it empty again. You do so, for example, by calling Begin/EndPaint().

If you don't then Windows immediately generates yet another WM_PAINT message, still trying to get the update region emptied. Your thread will burn 100% core, idly processing WM_PAINT messages and not actually getting the job done. Maybe you are actually painting, Windows just doesn't know what you painted and doesn't try to guess at it.

Using Begin/EndPaint() is very much the sane way to get that job done. It isn't the only way, you could also call ValidateRect() or ValidateRgn(). As long as you are "new to winapi", I'd very strongly recommend you do this the normal way.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I see, but what if I used, say OpenGL instead of the usual GDI way? Would I still need to call the glWhatEver functions between BeginPaint()/EndPaint()? (I've some foundation in OpenGL so porting this to C++ is at least somewhat achievable) –  Jan 31 '14 at 17:59
  • Lots of opengl tutorials around, no point in re-inventing this for yourself. – Hans Passant Jan 31 '14 at 18:03
3

Not sure if this is the case, but beginpaint and endpaint also validates drawn region of window, if you dont use them then windows is not aware that you have redrawn this region.You can call ValidateRect function to inform of the fact that window was redrawn.

Not sure if this will help in your case, you can read more on tjis in following so

Difference between GetDC() and BeginPaint()

Community
  • 1
  • 1
marcinj
  • 48,511
  • 9
  • 79
  • 100
1

GDI issues the WM_PAINT message to update a part of the window. BeginPaint/EndPaint() informs gdi that the handler is doing that job. In absence of a BeginPaint() for the specified region, until the window is updated (by someone) WM_PAINT messages will be generated. This is the reason you need BeginPaint/EndPaint() in a WM_PAINT handler and in absence of which you see a high CPU utilization.

GetDC() is not a substitute for Begin+EndPaint() because of the reason mentioned in my previous paragraph.

Abhijit
  • 62,056
  • 18
  • 131
  • 204