Search code examples
windowswinapioptimizationgdi

Why should I call `GetDC` and `ReleaseDC` again and again?


Every example code I have seen are GetDC and ReleaseDC being called again and again. Or BeginPaint and EndPaint.

But I think drawing on the screen happens very frequently (especially in a game), so storing the drawing in memory is better than getting and releasing device contexts all time.

So I went the route of getting a DC and "keeping it", only releasing it when the program ends. But why don't people do it like this? Is it because GetDC and ReleaseDC cost very little?

case WM_CREATE:
    hdc = GetDC(hWnd); //hdc is declared as global HDC
    MyBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));
    return 0;
case WM_PAINT:
    MemDC = CreateCompatibleDC(hdc);
    OldBitmap = (HBITMAP)SelectObject(MemDC, MyBitmap);
    BitBlt(hdc, 0, 0, 300, 300, MemDC, 0, 0, SRCCOPY);
    SelectObject(MemDC, OldBitmap);
    DeleteDC(MemDC);
    return 0;

Solution

  • The code you presented here is wrong. First off, you need to read a little more of the documentation. Here is a useful link: Painting and Drawing. Basically there are two ways to update a window:

    • In response to the WM_PAINT message. Use the BeginPaint and EndPaint functions to paint the client area properly. This message is sent by the system when a part of the client area is "invalidated" (as a result of resizing, restoring from minimized state, moving a window previously obscured, or programmatically invalidating it.) WM_PAINT is a low-priority message, received just before the message-queue gets empty.
    • Specifically drawing a part or the whole client area without having an invalidated region on it. Use GetDC and ReleaseDC for this. Useful if you want to make changes immediately visible, when the application (CPU) is busy.

    Writing some code to process the WM_PAINT message is normally almost mandatory, while specifically drawing as well is optional, depending on the requirements of your application.

    Never send or post a WM_PAINT message yourself, instead invalidate a part or the client area - the application will receive a WM_PAINT message before becoming idle. If you want the painting to occur immediately call UpdateWindow - this bypasses the message queue.