Painting the Background for a CFormView Derived Class


Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

I wanted to paint bitmaps on forms, like Access does. So I wrote some code for that: First, add in your derived CFormView two members:

CPalette m_palette;
CBitmap m_bitmap;

Add the following functions to your derived class: OnDraw overrides the base class' function, and OnCtlColor is a handler for WM_CTLCOLOR message. Call in OnInitialUpdate the function:

GetBitmapAndPalette( IDB_BACK, m_bitmap, m_palette );

where IDB_BACK is the identifier for the bitmap you want as background.

The code uses Keith Rule's CMemDC class. I added it here, so you don't have to search for it.

Add to your view a handler for WM_ERASEBKGND message:

BOOL CMyView::OnEraseBkgnd(CDC* pDC)
   // TODO: Add your message handler code here and/or call default
   return FALSE;

void CMyFormView::OnDraw(CDC* pDC) 
   // TODO: Add your specialized code here and/or call the base class

HBRUSH CMyFormView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
   //replace with your own base class
   HBRUSH hbr = CDaoRecordView::OnCtlColor(pDC, pWnd, nCtlColor);

   // TODO: Change any attributes of the DC here
      //this is only an example - you may have to modify here the
      //code in order to work properly for you
         //you can change the color of static text here
         return (HBRUSH)::GetStockObject(NULL_BRUSH);
   }else pDC->SetBkMode(OPAQUE);   
   // TODO: Return a different brush if the default is not desired
   return hbr;

BOOL CMyFormView::GetBitmapAndPalette(UINT nIDResource,
                                      CBitmap &bitmap,
                                      CPalette &pal)
   LPCTSTR lpszResourceName = (LPCTSTR)nIDResource;
   HBITMAP hBmp = (HBITMAP)::LoadImage( AfxGetInstanceHandle(),
      lpszResourceName, IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION );
   if( hBmp == NULL )return FALSE;
   bitmap.Attach( hBmp );
   // Create a logical palette for the bitmap
   BITMAPINFOHEADER &bmInfo = ds.dsBmih;
   bitmap.GetObject( sizeof(ds), &ds );
   int nColors = bmInfo.biClrUsed ? bmInfo.biClrUsed : 1
      << bmInfo.biBitCount;
   // Create a halftone palette if colors > 256. 
   CClientDC dc(NULL);         // Desktop DC
   if( nColors > 256 )   pal.CreateHalftonePalette( &dc );
      // Create the palette
      RGBQUAD *pRGB = new RGBQUAD[nColors];
      CDC memDC;
      memDC.SelectObject( &bitmap );
      ::GetDIBColorTable( memDC, 0, nColors, pRGB );
      UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY)
                                                * nColors);
      LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
      pLP->palVersion = 0x300;
      pLP->palNumEntries = nColors;
      for( int i=0; i < nColors; i++){
         pLP->palPalEntry[i].peRed = pRGB[i].rgbRed;
         pLP->palPalEntry[i].peGreen = pRGB[i].rgbGreen;
         pLP->palPalEntry[i].peBlue = pRGB[i].rgbBlue;
         pLP->palPalEntry[i].peFlags = 0;
      pal.CreatePalette( pLP );
      delete[] pLP;
      delete[] pRGB;
   return TRUE;

void DrawTheBackground(CDaoRecordView *view,
                       CDC *pDC,
                       CPalette *mp_palette,
                       CBitmap *mp_bitmap)
   CRect rect;
   CPalette *old_palette=NULL;
   // Select and realize the palette
   if( pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE &&
       mp_palette->m_hObject != NULL ){
      old_palette=pDC->SelectPalette( mp_palette, FALSE );
   CMemDC DC(pDC,rect);
   CDC dcImage;
   if (!dcImage.CreateCompatibleDC(pDC))return;
   BITMAP bm;
   // Paint the image.
   CBitmap* pOldBitmap = dcImage.SelectObject(mp_bitmap);
   for(int i=((int)floor((double)rect.left/bm.bmWidth))*bm.bmWidth;
        for(int j=((int)floor((double)rect.top/bm.bmHeight))
      DC->BitBlt(i, j, bm.bmWidth, bm.bmHeight, &dcImage,
                    0, 0, SRCCOPY);

#ifndef _MEMDC_H_
#define _MEMDC_H_
// CMemDC - memory DC
// Author: Keith Rule
// Email: keithr@europa.com
// Copyright 1996-1997, Keith Rule
// You may freely use or modify this code provided this
// Copyright is included in all derived versions.
// History - 10/3/97 Fixed scrolling bug.
//                   Added print support.
// This class implements a memory Device Context

class CMemDC : public CDC {
   CBitmap m_bitmap;        // Offscreen bitmap
   CBitmap* m_oldBitmap;    // bitmap originally found in CMemDC
   CDC* m_pDC;              // Saves CDC passed in constructor
   CRect m_rect;            // Rectangle of drawing area.
   BOOL m_bMemDC;           // TRUE if CDC really is a Memory DC.
   CMemDC(CDC* pDC, CRect &rect) : CDC(), m_oldBitmap(NULL),
      ASSERT(m_pDC != NULL);    // If you asserted here, you passed
                                // in a NULL CDC.
      m_bMemDC = !pDC->IsPrinting();
      if (m_bMemDC){
         // Create a Memory DC
         m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(),
         m_oldBitmap = SelectObject(&m_bitmap);
         SetWindowOrg(m_rect.left, m_rect.top);
      } else {
         // Make a copy of the relevent parts of the current DC
         // for printing
         m_bPrinting = pDC->m_bPrinting;
         m_hDC = pDC->m_hDC;
         m_hAttribDC = pDC->m_hAttribDC;

      if (m_bMemDC) {
         // Copy the offscreen bitmap onto the screen.
         m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(),
            this, m_rect.left, m_rect.top, SRCCOPY);
         //Swap back the original bitmap.
      } else {
         // All we need to do is replace the DC with an illegal
         // value, this keeps us from accidently deleting the
         // handles associated with the CDC that was passed to
         // the constructor.
         m_hDC = m_hAttribDC = NULL;
   // Allow usage as a pointer
   CMemDC* operator->() {return this;}
   // Allow usage as a pointer
   operator CMemDC*() {return this;}


Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date