Painting the Background for a CFormView Derived Class | CodeGuru

Painting the Background for a CFormView Derived Class

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 […]

Written By
CodeGuru Staff
CodeGuru Staff
Aug 5, 1998
1 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

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
   ::DrawTheBackground(this,pDC,&m_palette,&m_bitmap);
}
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
   if(nCtlColor==CTLCOLOR_STATIC){
      //this is only an example – you may have to modify here the
      //code in order to work properly for you
      if(pWnd->GetDlgCtrlID()==IDC_STATIC){
         pDC->SetBkMode(TRANSPARENT);
         //you can change the color of static text here
         //pDC->SetTextColor(RGB(255,255,255));
         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
   DIBSECTION ds;
   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 );
   else{
      // Create the palette
      RGBQUAD *pRGB = new RGBQUAD[nColors];
      CDC memDC;
      memDC.CreateCompatibleDC(&dc);
      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)
{
   if(pDC->IsPrinting())return;
   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 );
      pDC->RealizePalette();
   }
   view->GetClientRect(rect);
   pDC->DPtoLP(rect);
   CMemDC DC(pDC,rect);
   CDC dcImage;
   if (!dcImage.CreateCompatibleDC(pDC))return;
   BITMAP bm;
   mp_bitmap->GetBitmap(&bm);
   // Paint the image.
   CBitmap* pOldBitmap = dcImage.SelectObject(mp_bitmap);
   for(int i=((int)floor((double)rect.left/bm.bmWidth))*bm.bmWidth;
       i<=rect.right/*rect.Width()*/;i+=bm.bmWidth)
        for(int j=((int)floor((double)rect.top/bm.bmHeight))
            *bm.bmHeight;j<=rect.bottom/*rect.Height()
            */;j+=bm.bmHeight)
      DC->BitBlt(i, j, bm.bmWidth, bm.bmHeight, &dcImage,
                    0, 0, SRCCOPY);
   dcImage.SelectObject(pOldBitmap);
   pDC->SelectPalette(old_palette,FALSE);
   pDC->RealizePalette();
}
#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 {
private:
   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.
public:
   CMemDC(CDC* pDC, CRect &rect) : CDC(), m_oldBitmap(NULL),
         m_pDC(pDC)
   {
      ASSERT(m_pDC != NULL);    // If you asserted here, you passed
                                // in a NULL CDC.
      m_bMemDC = !pDC->IsPrinting();
      m_rect=rect;
      if (m_bMemDC){
         // Create a Memory DC
         CreateCompatibleDC(pDC);
         pDC->GetClipBox(&m_rect);
         m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(),
                                         m_rect.Height());
         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;
      }
   }
   ~CMemDC()
   {
      if (m_bMemDC) {
         // Copy the offscreen bitmap onto the screen.
         m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(),
                          m_rect.Height(),
            this, m_rect.left, m_rect.top, SRCCOPY);
         //Swap back the original bitmap.
         SelectObject(m_oldBitmap);
      } 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;}
};
#endif
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.