The MFC library makes it easy to display a bitmap (instead of text) on a pushbutton. If you were to program this from scratch, you would set the Owner Draw property for your button and then write a message handler in your dialog class that would paint a bitmap on the button control's window. If you use the MFC CBitmapButton class instead, you end up doing a lot less work, but you have to follow a kind of "cookbook" procedure. Don't worry too much about how it all works (but be glad that you don't have to write much code!).
There's also another way to put bitmaps on buttons. See Chapter 36, for a description of the CButton::SetBitmap function, which associates a single bitmap with a button.
To make a long story short, you lay out your dialog resource as usual with unique text captions for the buttons you designate for bitmaps. Next you add some bitmap resources to your project, and you identify those resources by name rather than by numeric ID. Finally you add some CBitmapButton data members to your dialog class, and you call the AutoLoad member function for each one, which matches a bitmap name to a button caption. If the button caption is "Copy", you add two bitmaps: "COPYU" for the up state and "COPYD" for the down state. By the way, you must still set the button's Owner Draw property. (This will all make more sense when you write a program).
If you look at the MFC source code for the CBitmapButton class, you'll see that the bitmap is an ordinary GDI bitmap painted with a BitBlt call. Thus, you can't expect any palette support. That's not often a problem because bitmaps for buttons are usually 16-color bitmaps that depend on standard VGA colors.
Here are the steps for building EX11D:
The Context-Sensitive Help option was selected for one reason only: it causes AppWizard to copy some bitmap files into your project's \hlp subdirectory. These bitmaps are supposed to be bound into your project's help file, but we won't study help files until Chapter 21.
Select the Owner Draw property for all three buttons.
Assign the name "COPYU" as shown.
Be sure to use quotes around the name in order to identify the resource by name rather than by ID. This is now the bitmap for the button's up state. Close the bitmap window and, from the ResourceView window, use the clipboard (or drag and drop) to make a copy of the bitmap. Rename the copy "COPYD" (down state), and then edit this bitmap. Choose Invert Colors from the Image menu. There are other ways of making a variation of the up image, but inversion is the quickest.
Repeat the steps listed above for the EditCut and EditPast bitmaps. When you're finished, you should have the following bitmap resources in your project.
Resource Name | Original File | Invert Colors |
"COPYU" | EditCopy.bmp | no |
"COPYD" | EditCopy.bmp | yes |
"CUTU" | EditCut.bmp | no |
"CUTD" | EditCut.bmp | yes |
"PASTEU" | EditPast.bmp | no |
"PASTED" | EditPast.bmp | yes |
CBitmapButton m_editCopy; CBitmapButton m_editCut; CBitmapButton m_editPaste;
Then you use ClassWizard to map the WM_INITDIALOG message in the dialog class. (Be sure that the CAboutDlg class is selected.) The message handler (actually a virtual function) is coded as follows:
BOOL CAboutDlg::OnInitDialog() { CDialog::OnInitDialog(); VERIFY(m_editCopy.AutoLoad(IDC_BUTTON1, this)); VERIFY(m_editCut.AutoLoad(IDC_BUTTON2, this)); VERIFY(m_editPaste.AutoLoad(IDC_BUTTON3, this)); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
The AutoLoad function connects each button with the two matching resources. The VERIFY macro is an MFC diagnostic aid that displays a message box if you didn't code the bitmap names correctly.
pDC->TextOut(0, 0, "Choose About from the Help menu.");
Note that bitmap buttons send BN_CLICKED notification messages just as ordinary buttons do. ClassWizard can, of course, map those messages in your dialog class.
You've seen bitmaps for the buttons' up and down states. The CBitmapButton class also supports bitmaps for the focused and disabled states. For the Copy button, the focused bitmap name would be "COPYF", and the disabled bitmap name would be "COPYX". If you want to test the disabled option, make a "COPYX" bitmap, possibly with a red line through it, and then add the following line to your program:
m_editCopy.EnableWindow(FALSE);