Now that you can load bitmaps into memory, you need to display them for the user. You need to copy the bitmap from the CBitmapobject to a BITMAPstructure, using the GetBitmapfunction, which will get the width and height of the bitmap image. Next,
you’ll create a new device context that is compatible with the screen device context. You’ll select the bitmap into the new device context and then copy it from this second device context to the original device context, resizing it as it’s copied, using the
StretchBltfunction.
To add this functionality to your application, add a new member function to the second dialog class. Specify the function type as void, the function declaration as
Notice that you have declared the window pointer being passed in as a pointer to a C W n dobject, instead of the class type of your main dialog. To declare it as a pointer to the class type of the first dialog, you’d need to declare the class for the first dialog before the class declaration for the sec- ond dialog. Meanwhile, the first dialog requires that the second dialog class be declared first. This affects the order in which the include files are added to the source code at the top of each file. You cannot have both classes
8
declared before the other; one has to be first. Although there are ways to get around this problem, by declaring a place holder for the second class before the declaration of the first class, it’s easier to cast the pointer as a pointer to the first dialog class in the function in this instance. To learn how to declare a place holder for the second class, see Appendix A, “C++ Review.”
ShowBitmap(CPaintDC *pdc, CWnd *pWnd), and the function access as private. Edit
the function, adding the code in Listing 8.10.
LISTING8.10.THEShowBitmapFUNCTION.
1: void CPaintDlg::ShowBitmap(CPaintDC *pdc, CWnd *pWnd) 2: {
3: // Convert the pointer to a pointer to the main dialog class 4: CGraphicsDlg *lpWnd = (CGraphicsDlg*)pWnd;
5: BITMAP bm;
6: // Get the loaded bitmap
7: lpWnd->m_bmpBitmap.GetBitmap(&bm); 8: CDC dcMem;
9: // Create a device context to load the bitmap into 10: dcMem.CreateCompatibleDC(pdc);
11: // Select the bitmap into the compatible device context 12: CBitmap* pOldBitmap = (CBitmap*)dcMem.SelectObject
➥(lpWnd->m_bmpBitmap); 13: CRect lRect;
14: // Get the display area available 15: GetClientRect(lRect);
16: lRect.NormalizeRect();
17: // Copy and resize the bitmap to the dialog window 18: pdc->StretchBlt(10, 10, (lRect.Width() - 20), 19: (lRect.Height() - 20), &dcMem, 0, 0, 20: bm.bmWidth, bm.bmHeight, SRCCOPY); 21: }
Now that you have the ability to display the currently selected bitmap on the dialog, you’ll need to add the functionality to call this function to the OnPaintfunction in the
second dialog. You can determine whether a bitmap has been specified by checking the value of the m_sBitmapvariable on the first dialog. If this string is empty, there is no
To add this last bit of functionality to this application, edit the OnPaintfunction, adding
lines 15 through 18 from Listing 8.11.
LISTING8.11.THE MODIFIEDOnPaintFUNCTION. 1: void CPaintDlg::OnPaint()
2: {
3: CPaintDC dc(this); // device context for painting 4:
5: // TODO: Add your message handler code here 6:
7: // Get a pointer to the parent window
8: CGraphicsDlg *pWnd = (CGraphicsDlg*)GetParent(); 9: // Do we have a valid pointer?
10: if (pWnd) 11: {
12: // Is the tool a bitmap? 13: if (pWnd->m_iTool == 2) 14: {
15: // Is there a bitmap selected and loaded? 16: if (pWnd->m_sBitmap != “”)
17: // Display it
18: ShowBitmap(&dc, pWnd); 19: }
20: else // No, we’re drawing a shape 21: {
22: // Are we drawing a line? 23: if (m_iShape == 0)
24: DrawLine(&dc, pWnd->m_iColor);
25: else // We’re drawing a ellipse or rectangle
26: DrawRegion(&dc, pWnd->m_iColor, pWnd->m_iTool, 27: pWnd->m_iShape);
28: } 29: }
30: // Do not call CDialog::OnPaint() for painting messages 31:}
At this point, you should be able to select a bitmap from your system and display it in the second dialog, as shown in Figure 8.6.
FIGURE8.6.
Showing a bitmap in the second dialog.
8
Summary
What a way to start the week! You learned a lot today. You learned how Windows uses device context objects to allow you to draw graphics in the same way every time, without having to worry about what hardware users might have in their computers. You learned about some of the basic GDI objects, such as pens and brushes, and how they are used to draw figures on windows and dialogs. You also learned how you can load bitmaps from the system disk and display them onscreen for the user to see. You learned about the dif- ferent pen and brush styles and how you can use these to draw the type of figure you want to draw. You also learned how you can specify colors for use with pens and brushes so that you can control how images appear to the user.
Q&A
Q Why do I need to specify both a pen and a brush if I just want to display one or the other?
A You are always drawing with both when you draw any object that is filled in. The
pen draws the outline, and the brush fills in the interior. You cannot choose to use one or the other; you have to use both. If you only want to display one or the other, you need to take special steps.
Q Why do all of the pen styles become solid when I increase the pen width above 1?
A When you increase the pen width, you are increasing the size of the dot that is used
to draw with. If you remember Day 3, “Allowing User Interaction—Integrating the Mouse and Keyboard in Your Application,” when you first tried to draw by captur-
ing each spot the mouse covered, all you drew were a bunch of dots. Well, when you increase the size of the dots that you are drawing the line with, the gaps between the dots are filled in from both sides, providing an unbroken line.
Workshop
The Workshop provides quiz questions to help you solidify your understanding of the material covered and exercises to provide you with experience in using what you’ve learned. The answers to the quiz questions and exercises are provided in Appendix B, “Answers.”
Quiz
1. What are the three values that are combined to specify a color?
2. What do you use to draw on windows without needing to know what graphics card the user has?
3. What size bitmap can you use to make a brush from it?
4. What event message is sent to a window to tell it to redraw itself? 5. How can you cause a window to repaint itself?
Exercises
1. Make the second dialog window resizable, and make it adjust the figures drawn on it whenever it’s resized.