You can compile and run your application at this point, and the second dialog redraws itself whenever you choose a different radio button on the main dialog, but you wouldn’t notice anything happening. At this point, you are triggering the redraws, but you haven’t told the second dialog what to draw, which is the next step in building this application. The easiest graphics to draw on the second dialog will be different styles of lines because you already have some experience drawing them. What you’ll want to do is create one pen for each of the different pen styles, using the currently selected color. After you have created all of the pens, you’ll loop through the different pens, selecting each one in turn and drawing a line across the dialog with each one. Before you start this loop, you need to perform a few calculations to determine where each of the lines should be on the dia- log, with their starting and stopping points.
To begin adding this functionality to your application, you first add a color table, with one entry for each of the colors in the group of available colors on the first dialog. To create this color table, add a new member variable to the second dialog class,CPaintDlg,
and specify the variable type as static const COLORREF, the name as m_crColors[8], and
the access as public. Open the source code file for the second dialog class, and add the color table in Listing 8.4 near the top of the file before the class constructor and destruc- tor.
LISTING8.4.THE COLOR TABLE.
1: const COLORREF CPaintDlg::m_crColors[8] = { 2: RGB( 0, 0, 0), // Black 3: RGB( 0, 0, 255), // Blue 4: RGB( 0, 255, 0), // Green 5: RGB( 0, 255, 255), // Cyan 6: RGB( 255, 0, 0), // Red 7: RGB( 255, 0, 255), // Magenta
8
8: RGB( 255, 255, 0), // Yellow 9: RGB( 255, 255, 255) // White 10: }; 11: /////////////////////////////////////////////////////////////////// 12: // CPaintDlg dialog . . .With the color table in place, you can add a new function for drawing the lines. To keep the OnPaintfunction from getting too cluttered and difficult to understand, it makes more
sense to place a limited amount of code in it to determine what should be drawn on the second dialog and then call other more specialized functions to draw the various shapes. With this in mind, you need to create a new member function for the second dia- log class for drawing the lines. Declare this as a void function, and specify its declaration as DrawLine(CPaintDC *pdc, int iColor)and its access as private. You can edit this function,
adding the code in Listing 8.5.
LISTING8.5.THEDrawLineFUNCTION.
1: void CPaintDlg::DrawLine(CPaintDC *pdc, int iColor) 2: {
3: // Declare and create the pens
4: CPen lSolidPen (PS_SOLID, 1, m_crColors[iColor]); 5: CPen lDotPen (PS_DOT, 1, m_crColors[iColor]); 6: CPen lDashPen (PS_DASH, 1, m_crColors[iColor]); 7: CPen lDashDotPen (PS_DASHDOT, 1, m_crColors[iColor]); 8: CPen lDashDotDotPen (PS_DASHDOTDOT, 1, m_crColors[iColor]); 9: CPen lNullPen (PS_NULL, 1, m_crColors[iColor]);
10: CPen lInsidePen (PS_INSIDEFRAME, 1, m_crColors[iColor]); 11:
12: // Get the drawing area 13: CRect lRect;
14: GetClientRect(lRect); 15: lRect.NormalizeRect(); 16:
17: // Calculate the distance between each of the lines 18: CPoint pStart;
19: CPoint pEnd;
20: int liDist = lRect.Height() / 8; 21: CPen *lOldPen;
22: // Specify the starting points 23: pStart.y = lRect.top;
24: pStart.x = lRect.left;
LISTING8.5.CONTINUED
25: pEnd.y = pStart.y; 26: pEnd.x = lRect.right; 27: int i;
28: // Loop through the different pens 29: for (i = 0; i < 7; i++)
30: {
31: // Which pen are we on? 32: switch (i) 33: { 34: case 0: // Solid 35: lOldPen = pdc->SelectObject(&lSolidPen); 36: break; 37: case 1: // Dot 38: pdc->SelectObject(&lDotPen); 39: break; 40: case 2: // Dash 41: pdc->SelectObject(&lDashPen); 42: break;
43: case 3: // Dash Dot
44: pdc->SelectObject(&lDashDotPen); 45: break;
46: case 4: // Dash Dot Dot
47: pdc->SelectObject(&lDashDotDotPen); 48: break; 49: case 5: // Null 50: pdc->SelectObject(&lNullPen); 51: break; 52: case 6: // Inside 53: pdc->SelectObject(&lInsidePen); 54: break; 55: }
56: // Move down to the next position 57: pStart.y = pStart.y + liDist; 58: pEnd.y = pStart.y;
59: // Draw the line 60: pdc->MoveTo(pStart); 61: pdc->LineTo(pEnd); 62: }
63: // Select the original pen 64: pdc->SelectObject(lOldPen); 65: }
Now you need to edit the OnPaintfunction so that the OnLinefunction is called when it
needs to be called. Add this function through the Class Wizard as an event-handler func- tion for the WM_PAINTmessage. You’ll notice that the generated code for this function
8
descendent of the CDC device context class. It automatically calls the BeginPaintand EndPaintAPI functions that all Windows applications must call before drawing any
graphics during the WM_PAINTevent message processing. It can be treated just like a reg-
ular device context object, calling all of the same functions.
When you are in the OnPaintfunction, you need to get a pointer to the parent window so
that you can check the values of the variables tied to the groups of radio buttons to deter- mine the color, tools, and shape to be drawn on the second dialog. This information tells you whether to call the DrawLinefunction or another function that you haven’t written
yet.
To add this functionality to your application, add an event handler for the WM_PAINT
message on the second dialog class, adding the code in Listing 8.6 to the function creat- ed in your class.
LISTING8.6.THEOnPaintFUNCTION. 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: }
16: else // No, we’re drawing a shape 17: {
18: // Are we drawing a line? 19: if (pWnd->m_iShape == 0)
20: DrawLine(&dc, pWnd->m_iColor); 21: }
22: }
23: // Do not call CDialog::OnPaint() for painting messages 24:}
At this point, if you compile and run your application, you should be able to draw lines across the second dialog, as shown in Figure 8.4.