Search code examples
c++windowswinformsbitmapgdi

GDI - Can I save the bitmap in memory between WM_PAINT calls?


I want to optimize my window painting. Want to have the static content and the dynamic content in window. Static content was calculated once and is painting from the created bitmap.

I'm using next algorithm:

  /* !global object! HBITMAP hStaticBitmap */ 
  PAINTSTRUCT ps = {};

  HDC  hdc = BeginPaint (hWnd, &ps);
  //-------------------------------------------
  HDC   hStaticDC = CreateCompatibleDC (hdc);

  if ( hStaticBitmapChanged )
  {
    /* Create once */
    if (hStaticBitmap)
      DeleteObject (hStaticBitmap);

    hStaticBitmap = CreateCompatibleBitmap (hdc, myRect.right  - myRect.left,
                                                 myRect.bottom - myRect.top);
    HBITMAP hBmp_old = (HBITMAP) SelectObject (hStaticDC, wd.hStaticBitmap);
    //-------------------------------------
    OnPaintStaticFigures (hStaticDC);
    hStaticBitmapChanged = false;
    //-------------------------------------
    SetStretchBltMode (hdc, COLORONCOLOR);
    BitBlt (hdc, 0, 0,
            myRect.right - myRect.left,
            myRect.bottom - myRect.top,
            hStaticDC, 0, 0,
            SRCCOPY);
    //-------------------------------------
    SelectObject (hStaticDC, hBmp_old);
  }
  else
  {
    /* Paint every time */
    HBITMAP  hBmp_old = (HBITMAP) SelectObject (hStaticDC, wd.hStaticBitmap);
    //-------------------------------------
    SetStretchBltMode (hdc, COLORONCOLOR);
    BitBlt (hdc, 0, 0,
            myRect.right - myRect.left,
            myRect.bottom - myRect.top,
            hStaticDC, 0, 0,
            SRCCOPY);
    //-------------------------------------
    SelectObject (hStaticDC, hBmp_old);
  }

  HDC   hCmpDC = CreateCompatibleDC (hdc);
  HBITMAP  hBmp = CreateCompatibleBitmap (hdc, myRect.right  - myRect.left,
                                               myRect.bottom - myRect.top);
  SelectObject (hCmpDC, hBmp);
  //-------------------------------------
  OnPainDynamicFigures (hCmpDC, wd);
  //-------------------------------------
  SetStretchBltMode (hdc, COLORONCOLOR);
  BitBlt (hdc, 0, 0,
          myRect.right  - myRect.left,
          myRect.bottom - myRect.top,
          hCmpDC, 0, 0,
          SRCCOPY);

  DeleteDC (hStaticDC);
  DeleteDC (hCmpDC);
  DeleteObject (hBmp);
  //---------------------------------------------
  EndPaint (hWnd, &ps);

The problem is: hStaticBitmap is cleared after the Delete hStaticDC. How to handle this?

Thank you


EDIT:

Now I'm not sure, that it happens, because of the hStaticDC. I have made the hStaticDC global. But I can see the black background, the second bitmap erase the first one. I try another overlap mode, and with global hdc the both of bitmaps are shown.

I want to change my question: How to make a bitmap has no backgraoud?


Solution

  • Working variant: using lower layer as background to upper!

     /* !global object! HBITMAP hStaticBitmap */ 
     /* !global object! HBITMAP hStaticDC    */ // !!!global 
    
      PAINTSTRUCT ps = {};
      HDC  hdc = BeginPaint (hWnd, &ps);
      //-------------------------------------------
      if ( hStaticBitmapChanged )
      {
        /* Create once */
        if ( !hStaticDC )                       // !!!global 
          hStaticDC = CreateCompatibleDC (hdc);
        if (hStaticBitmap)
          DeleteObject (hStaticBitmap);
    
        hStaticBitmap = CreateCompatibleBitmap (hdc, myRect.right  - myRect.left,
                                                     myRect.bottom - myRect.top);
        SelectObject (hStaticDC, hStaticBitmap);
        //-------------------------------------
        OnPaintStaticFigures (hStaticDC);
        hStaticBitmapChanged = false;
        //-------------------------------------
      }
    
      HDC   hCmpDC = CreateCompatibleDC (hdc);
      HBITMAP  hBmp = CreateCompatibleBitmap (hdc, myRect.right  - myRect.left,
                                                   myRect.bottom - myRect.top);
      SelectObject (hCmpDC, hBmp);
      //-------------------------------------
      /* Paint every time */
      SetStretchBltMode (hCmpDC, COLORONCOLOR);   // !!! hCmpDC
      BitBlt ( hCmpDC , 0, 0,                     // !!! hCmpDC
               myRect.right - myRect.left,
               myRect.bottom - myRect.top,
               hStaticDC, 0, 0,
               SRCCOPY);
      //-------------------------------------
      OnPainDynamicFigures (hCmpDC, wd);
      //-------------------------------------
      SetStretchBltMode (hdc, COLORONCOLOR);
      BitBlt (hdc, 0, 0,
              myRect.right  - myRect.left,
              myRect.bottom - myRect.top,
              hCmpDC, 0, 0,
              SRCCOPY);
    
      // DeleteDC (hStaticDC); /* later */
      // DeleteObject (hStaticBitmap); /* later */
      DeleteDC (hCmpDC);
      DeleteObject (hBmp);
      //---------------------------------------------
      EndPaint (hWnd, &ps);