0

I have been experimenting around with the device context and read quite a lot about it from the MSDN documentation. I have created a program which does some painting with double buffering and I ran into a small problem (Not really a problem, but curiosity from my side).

According to MSDN you should use BeginPaint and EndPaint whenever you are drawing on the window and releaseDC and getDC whenever you are performing drawing anywhere else.

I decided to try using GetDC and ReleaseDC anyway and I managed to get it to work Only issue is that the CPU usage during the lifetime of my program is extremely high. I am talking about 25% to 50% CPU usage.

I will post the code which I have in WM_PAINT. Would appreciate any tips for why this happens.

paintWindow is my own function that creates an offscreen DC, renders the frame and copies the content to the hdc. The code is not important since I am 100% positive it is not related to the problem I am experiencing.

The code below works flawlessly. No high CPU usage. Everything is cool.

CASE WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
paintWindow(hdc);
EndPaint(hWnd, &ps);

As soon as I try doing something like this:

hdc = GetDC(hWnd);
paintWindow(hdc);
ReleaseDC(hWnd, hdc);

The code still works flawlessly just as before, except the CPU usage is sky high. This is more or less an optimization problem and out of my own curiosity I would like to know what is the exact difference in the background and what should I do if I wanted to achieve the same thing as BeginPaint and EndPaind.

drescherjm
  • 10,365
  • 5
  • 44
  • 64
Erik9631
  • 87
  • 9
  • I guess without `BeginPaing` / `EndPaint` the invalidated region remain invalid and you get `WM_PAINT` messages infinitely. Put `OutputDebugString()` trace after `case WM_PAINT:` to check this. – i486 Jun 19 '18 at 18:56
  • @i486: Visual Studio has had [trace points](https://blogs.msdn.microsoft.com/devops/2013/10/10/tracepoints/) for as long as I can remember, so that you don't have to edit your code just to see, how many times a function is called. – IInspectable Jun 19 '18 at 20:20
  • @IInspectable Imagine that he is using Borland C++ :) – i486 Jun 19 '18 at 21:55

1 Answers1

3

The WM_PAINT message is autogenerated by the message-retrieval functions, whenever part of a window is invalidated, either through an explicit call to InvalidateRect, or when the window gets resized or uncovered.

Your WM_PAINT handler is required to validate the invalid region, telling the system that no more painting is required. The BeginPaint call does that for you. If you fail to validate the invalid region, the system keeps generating WM_PAINT messages.

If you do want to keep your GetDC-based approach (for whatever reason; I wouldn't know of a single one), you are going to have to explicitly call ValidateRect before returning, so that the system will not continue to generate WM_PAINT messages.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
  • Thanks for the answer. That cleared it up, I am not going to keep doing this, as you said yourself there is no reason to. It is for educational purposes. Thanks a lot for the help – Erik9631 Jun 19 '18 at 20:20