Question

MSDN and numerous post have suggested that BeginPaint/EndPaint should used in WM_PAINT. I've also seen numerous places suggesting that if double buffering is employed in painting, it makes more sense to initialize the DC and mem allocation in WM_CREATE and reuse those handles in WM_PAINT.

For example, using BeginPaint, I commonly see:

case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
MemDC = CreateCompatibleDC(hdc);
bmp = CreateCompatibleBitmap(hdc, width, height);
oldbmp = SelectObject(MemDC,bmp);
g = new Graphics(MemDC);

//do paint on bmp
//blt bmp back to hdc

EndPaint(hWnd, &ps);
DeleteObject(bmp);
g->ReleaseHDC(MemDC);
DeleteDC(MemDC);
delete g;

To save the initialization and tearing down, is it possible to do this :

case WM_CREATE:
hdc   = GetDC(hWnd);
//create memDC and graphics object references ...
case WM_DESTROY
//delete memDC and graphics object references...
case WM_PAINT
BeginPaint(hWnd, &ps);
//use previously create mem and graphics object to paint 
EndPaint(hWnd, &ps);

So we only use EndPaint to clear the update region but delegate the drawing to prev created objects.

Was it helpful?

Solution

No, that's a very poor practice. This goes wrong first by the device context having the wrong clipping region, you cannot properly paint the window when the user resizes the window.

Second problem is that the update region clipping won't be in effect, PAINTSTRUCT.rcPaint. Preventing any possible paint optimization that Windows may automatically perform when the update region is just a part of the window.

Third problem is that you are holding on an operating system resource needlessly. All GDI objects are allocated in a single heap that's shared by all processes that run on the same desktop.

Creating a HDC is very cheap, create it when you need it. Not to mention the PAINTSTRUCT.hdc you'll get served on a platter, ready to use.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top