Quantcast
Channel: codexpert blog
Viewing all articles
Browse latest Browse all 85

Painting the Dialog Backround

$
0
0

Generally, it’s not necessary to change the dialog’s default background. Besides, if have to display an image in a dialog, it is preferable to do it in a child control (e.g. static picture or custom control). However, let’s say that’s a requirement or we want to do it as an exercise or just for fun.

Painting the Dialog Background

Painting the Dialog Background

The image shows a dialog that has its background painted with a fancy brush. It also has a nice Earth image, transparently painted directly in the dialog’s client area.
Let’s see how to make it!.

Handling WM_ERASEBKGND message

This example handles the WM_ERASEBKGND message and fills the background by using a custom brush.  Finally, it returns TRUE to prevent further erasing.

BOOL CDemoDialog::OnEraseBkgnd(CDC* pDC)
{
   // get clipping rectangle
   CRect rcClip;
   pDC->GetClipBox(rcClip);
   // fill rectangle using a given brush
   pDC->FillRect(rcClip, &m_brushBack);
   return TRUE; // returns non-zero to prevent further erasing
}

Next’ we would notice that’s necessary to handle WM_CTLCOLOR in order to change also the beackground of some child controls (static, radio buttons, etc.). As long as, WM_CTLCOLOR allows also changing the dialog’s background, we can get rid of previous method and do all the work in the WM_CTLCOLOR message handler.

Handling WM_CTLCOLOR message

To change the default background as well as other attributes, WM_CTLCOLOR message handler (OnCtlColor) must return a not-NULL brush handle.

HBRUSH CDemoDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
   HBRUSH hBrush = NULL;
   switch(nCtlColor)
   {
   case CTLCOLOR_DLG:
      // just return a not NULL brush handle
      hBrush = (HBRUSH)m_brushBack;
      break;
   case CTLCOLOR_STATIC:
      {
         // set text color, transparent back node then 
         pDC->SetTextColor(m_crStaticText);
         pDC->SetBkMode(TRANSPARENT);
         // return a not NULL brush handle
         hBrush = (HBRUSH)m_brushBack;
      }
      break;
   default:
      // do the default processing
      hBrush = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
      break;
   }      
   return hBrush;
}

Note: In Win32, WM_CTLCOLOR notification message was replaced by WM_CTLCOLORDLG, WM_CTLCOLORSTATIC, and so on. However, MFC still keeps WM_CTLCOLOR for 16-bit legacy code compatibility. The third argument (nCtlColor) of OnCtlColor handler function, helps us to decide if in fact has been received one of the following notifications: WM_CTLCOLORDLG, WM_CTLCOLORSTATIC, etc.

Handling WM_PAINT message

Finally, lets’s “paint the Earth”! As in any other kind of window, the right place to perform paining is the WM_PAINT message handler.

void CDemoDialog::OnPaint()
{
   CPaintDC dc(this); // device context for painting

   CDC dcMem;
   // create memory DC
   dcMem.CreateCompatibleDC(&dc);
   // select the source bitmao into the memory DC
   CBitmap* pOldBitmap = (CBitmap*)dcMem.SelectObject(&m_bmpEarth);
   // get the bitmap data
   BITMAP bmp = {0};
   m_bmpEarth.GetBitmap(&bmp);
   // transfer the bitmap into paint DC using a transparent color  
   dc.TransparentBlt(
      10, 10, bmp.bmWidth, bmp.bmHeight, // destination coordinates and sizes
      &dcMem,                            // source DC
      0, 0, bmp.bmWidth, bmp.bmHeight,   // source coordinates and sizes
      RGB(255, 0, 0));                   // transparent color
   // restore DC / free GDI objects 
   dcMem.SelectObject(pOldBitmap);
}

Demo project

Download the demo project and you can find more implementation details.

Resources

See also


Viewing all articles
Browse latest Browse all 85

Latest Images

Trending Articles



Latest Images