Bitmap Backgrounds For Dialog Boxes
An article on setting a Bitmap as the Dialog Background. NO API

Introduction
This article is intended to give a solution for placing a bitmap as the Dialog's background. Setting a bitmap as the background allows you to place controls over the bitmap and not have them obscured. Placing a bitmap into a dialog using the resource editor forces the bitmap to the foreground and hinders the placement of additional controls.
Background
While I was busy with my final year Industrial Engineering project of designing and building a USB Control interface, the final step was to write an application to communicate with the board. I chose an easy-to-use graphic interface. After many hours of drawing the PCB on CAD, I took a screen dump and thought that was it finalised. When I inserted the screen dump into the application using the Resource Editor, I discovered that not a single GUI drawing command had been displayed. Upon removing the bitmap to ensure that the OnPaint
instructions were being drawn, I realised that the bitmap was drawn as the foreground with no options in the Resource Editor to force the bitmap into the background. I searched the Internet for a solution. I found a few possible solutions, but they all involved downloading an API written by another author. I challenged myself as to whether it would be possible for me to derive my own solution to this problem. I succeeded and I herewith describe my solution.
Using the code
Step 1: Load the bitmap image into the resource editor under Bitmaps. Change the Depth from 16 Colours to 24Bit True Colour.
Step 2: Assign a Resource ID to the bitmap and resize the dialog to the size of the bitmap. This ensures that Windows does not fill the empty area with a screen dump. Disable the maximize box, failing which the OnSize
message will have to be handled to adjust the size of the bitmap to fill the remaining areas. It's preferable to use SW_SHOWNORMAL
instead of SW_MAXIMIZE
in OnInitDialog();
Step 3: Add a Cbitmap
class under Protected in the bitmaps header file, a CSize
handle and a CBrush
handle, as per the example set out below:
// Dialog Data
enum { IDD = IDD_BITMAPBACKGROUND_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
Cbitmap Background; // For Holding The bitmap
CBrush BrushHol; //For Handling Background of Text in Static Text
CSize bitmapSize; // For Holding The bitmap Size
Step 4: Load the bitmap in OnInitDialog()
and get bitmap dimensions as per the example set out below:
BOOL CbitmapBackgroundDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
ShowWindow(SW_SHOWNORMAL);
//Load bitmap From Resource, Get bitmap Size
Background.LoadbitmapW(IDB_BACKGROUND); //Load bitmap
BITMAP bm; //Create bitmap Handle to get dimensions
Background.Getbitmap(&bm); //Load bitmap into handle
bitmapSize = CSize(bm.bmWidth, bm.bmHeight); // Get bitmap Sizes;
Invalidate(1);
//Force the dialog to repaint itself;
//End bitmap Information
return TRUE; // return TRUE unless you set the focus to a control
}
Step 5: Add a WM_ERASEBKGND
Message (OnEraseBkgnd
)
Step 6: Edit OnEraseBkgnd
and add the following:
BOOL CbitmapBackgroundDlg::OnEraseBkgnd(CDC* pDC)
{
CDC dcMemory;
dcMemory.CreateCompatibleDC(pDC);
Cbitmap* pOldbitmap = dcMemory.SelectObject(&Background);
CRect rcClient;
GetClientRect(&rcClient);
const CSize& sbitmap = bitmapSize;
pDC->BitBlt(0,0,sbitmap.cx,sbitmap.cy,&dcMemory,0,0,SRCCOPY);
dcMemory.SelectObject(pOldbitmap);
return TRUE;
//return CDialog::OnEraseBkgnd(pDC); Remove and return TRUE
}
Step 7: Add OnDestroy()
and free the resources created for the bitmap, as per the example set out below:
void CbitmapBackgroundDlg::OnDestroy()
{
CDialog::OnDestroy();
Background.DeleteObject(); // Delete Background bitmap
BrushHol.DeleteObject();
// Delete Brush
}
Step 8: Handle background colour for controls like Static Text. This will ensure that the text is drawn with a background the same as the bitmap. Add the following to the Dialogs Create function:
CbitmapBackgroundDlg::CbitmapBackgroundDlg(CWnd* pParent /*=NULL*/)
: CDialog(CbitmapBackgroundDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
BrushHol.CreateStockObject(HOLLOW_BRUSH);
//Used for background painting of text. Add This Line
}
Step 9: Add OnCtlColor
. This instructs Windows to make your background mode TRANSPARENT. This can later be used to change the colour of text and controls, as per the example set out below:
HBRUSH CbitmapBackgroundDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
// HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
pDC->SetBkMode(TRANSPARENT);
if( pWnd->GetDlgCtrlID() == IDC_STATIC)
//Example of changing Text colour specific to a certain
//Static Text Contol in this case IDC_STATIC.
{
pDC->SetTextColor(RGB(255, 0, 0));
}
// TODO: Return a different brush if the default is not desired
return BrushHol;
}
Points of interest
I hope you found this experiment in Windows manipulation as interesting as I did. You may wish to eliminate the OnCtlColor
by doing your text drawing in the OnPaint()
function. This was the method I used.
History
- 28 May, 2007 - Original version posted