📄 ch12.htm
字号:
<UL> <LI><TT>Ellipse</TT>: Used to draw an ellipse. This function is also used to draw circles, because a circle is just a special type of ellipse.<BR> <BR> <LI><TT>Arc</TT>: Used to draw a portion of an ellipse.<BR> <BR> <LI><TT>LineTo</TT> and <TT>MoveTo</TT>: Used to draw lines. Together they are often used to draw highlighting, squares, rectangles, and other types of figures.</UL><P>As an example using pens, you can modify the DCTest program you created in Hour11. The changes use three pens to draw three figures in the view window in a varietyof styles and colors. Modifying the existing project also gives you a chance to seehow different mapping modes affect the figures drawn using pens. Although some ofthe listings might look long, most of them require only a few changes in the sourcecode that is already present.<H3><FONT COLOR="#000077"><B>Modifying the Mapping Mode Dialog Box</B></FONT></H3><P>As the first step in the sample program, modify the Mapping Mode dialog box andthe <TT>CMapModeDlg</TT> class to support extra options used when drawing with pens.The new version of the <TT>IDD_MAP_MODE</TT> dialog box is shown in Figure 12.2.</P><P><A NAME="02"></A><A HREF="02.htm"><B>Figure 12.2.</B> </A><I><BR>The new version of the Mapping Mode dialog box.</I></P><P>Use the values from Table 12.1 for the new controls you add to the Mapping Modedialog box, using ClassWizard to add member variables to the <TT>CMapModeDlg</TT>class. All existing controls should remain as they are.<H4><FONT COLOR="#000077">Table 12.1. Values for new edit controls you add to theMapping Mode dialog box.</FONT></H4><P><TABLE BORDER="1"> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP"><B>Edit Control</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Resource ID</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Variable Name</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Type</B></TD> </TR> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP">Pen Width</TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>IDC_WIDTH</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>m_nPenWidth</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>int</TT></TD> </TR> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP">Ellipse Width</TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>IDC_CXELLIPSE</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>m_cxEllipse</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>int</TT></TD> </TR> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP">Ellipse Height</TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>IDC_CYELLIPSE</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>m_cyEllipse</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>int</TT></TD> </TR></TABLE><H3><FONT COLOR="#000077"><B>Modifying the <TT>CDCTestView</TT> Class</B></FONT></H3><P>You must modify the <TT>CDCTestView</TT> class slightly to add three new membervariables that store the pen height and the ellipse variables you just added to thedialog box class. Add three new member variables to the attributes section of the<TT>CDCTestView</TT> class declaration, as shown in Listing 12.2.<H4><FONT COLOR="#000077">TYPE: Listing 12.2. New member variables added to the CDCTestViewclass.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>// Attributes</TT><TT>private:</TT><TT> // Variables added for Hour 11</TT><TT> CMap< int, int, CString, CString > m_map;</TT><TT> int m_nMapMode;</TT><TT> // Variables added for Hour 12 - pens</TT><TT> int m_cxEllipse;</TT><TT> int m_cyEllipse;</TT><TT> int m_nPenWidth;</TT></FONT></PRE><P>Do not modify the declarations for existing member variables.<H3><FONT COLOR="#000077"><B>Modifying the <TT>CDCTestView</TT> Member Functions</B></FONT></H3><P>You must modify three <TT>CDCTestView</TT> member functions:<UL> <LI>The <TT>CDCTestView</TT> constructor <LI>The <TT>CDCTestView::OnViewMapMode</TT> menu handler <LI>The <TT>CDCTestView::OnDraw</TT> member function</UL><P>Each of these views is modified in the following sections. None of these memberfunctions are new; all are used in the current DCTest project.</P><P>Add three new lines to the <TT>CDCTestView</TT> constructor to initialize thenew variables added to the <TT>CDCTestView</TT> class. Listing 12.3 is the new versionof the <TT>CDCTestView</TT> constructor. Most of the function should already be entered;you must add only the last three lines before the closing parenthesis.<H4><FONT COLOR="#000077">TYPE: Listing 12.3. The new version of the CDCTestViewconstructor.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>CDCTestView::CDCTestView()</TT><TT>{</TT><TT> m_nMapMode = MM_TEXT;</TT><TT> m_map.SetAt( MM_ANISOTROPIC, "MM_ANISOTROPIC" );</TT><TT> m_map.SetAt( MM_HIENGLISH, "MM_HIENGLISH" );</TT><TT> m_map.SetAt( MM_HIMETRIC, "MM_HIMETRIC" );</TT><TT> m_map.SetAt( MM_ISOTROPIC, "MM_ISOTROPIC" );</TT><TT> m_map.SetAt( MM_LOENGLISH, "MM_LOENGLISH" );</TT><TT> m_map.SetAt( MM_LOMETRIC, "MM_LOMETRIC" );</TT><TT> m_map.SetAt( MM_TEXT, "MM_TEXT" );</TT><TT> m_map.SetAt( MM_TWIPS, "MM_TWIPS" );</TT><TT> m_nPenWidth = 1;</TT><TT> m_cxEllipse = 100;</TT><TT> m_cyEllipse = 200;</TT><TT>}</TT></FONT></PRE><P>Modify the <TT>CDCTestView::OnViewMapMode</TT> function to handle the changesin the Mapping Mode dialog box. Listing 12.4 provides the source code for the newversion of <TT>OnViewMapMode</TT>. There are a total of six new source code lines,each marked with a comment. You should need to add only these six lines; the restof the function should have been created already.<H4><FONT COLOR="#000077">Listing 12.4. The new version of the CDCTestView::OnViewMapModefunction.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>void CDCTestView::OnViewMapMode()</TT><TT>{</TT><TT> CMapModeDlg dlg;</TT><TT> // The next three lines are added for Hour 12 - pens</TT><TT> dlg.m_nPenWidth = m_nPenWidth; // 1</TT><TT> dlg.m_cxEllipse = m_cxEllipse; // 2</TT><TT> dlg.m_cyEllipse = m_cyEllipse; // 3</TT><TT> if( dlg.DoModal() == IDOK )</TT><TT> {</TT><TT> // The next three lines are added for Hour 12 - pens</TT><TT> m_nPenWidth = dlg.m_nPenWidth; // 4</TT><TT> m_cxEllipse = dlg.m_cxEllipse; // 5</TT><TT> m_cyEllipse = dlg.m_cyEllipse; // 6</TT><TT> POSITION pos;</TT><TT> pos = m_map.GetStartPosition();</TT><TT> while( pos != NULL )</TT><TT> {</TT><TT> CString szMapMode;</TT><TT> int nMapMode;</TT><TT> m_map.GetNextAssoc( pos, nMapMode, szMapMode );</TT><TT> if( szMapMode == dlg.m_szCombo )</TT><TT> {</TT><TT> m_nMapMode = nMapMode;</TT><TT> break;</TT><TT> }</TT><TT> }</TT><TT> InvalidateRect( NULL );</TT><TT> }</TT><TT>}</TT></FONT></PRE><P>Last but not least, you must create a new version of the <TT>OnDraw</TT> function.Most of this version of <TT>OnDraw</TT> is new because you are now drawing with pensinstead of listing device attributes. Use the source code provided in Listing 12.5for the new version of <TT>CDCTestView::OnDraw</TT>.<H4><FONT COLOR="#000077">Listing 12.5. The new version of CDCTestView::OnDraw.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>void CDCTestView::OnDraw(CDC* pDC)</TT><TT>{</TT><TT> pDC->SetMapMode( m_nMapMode );</TT><TT> // Draw an ellipse based on the current map-mode and values</TT><TT> // supplied by the user.</TT><TT> CRect rcClient;</TT><TT> GetClientRect( rcClient );</TT><TT> pDC->DPtoLP( rcClient ); // Covert device units to logical</TT><TT> CPoint ptCenter( rcClient.Width()/2, rcClient.Height()/2 );</TT><TT> CRect rcEllipse( ptCenter.x - ( m_cxEllipse/2 ),</TT><TT> ptCenter.y - ( m_cyEllipse/2 ),</TT><TT> ptCenter.x + ( m_cxEllipse/2 ),</TT><TT> ptCenter.y + ( m_cyEllipse/2 ) );</TT><TT> CPen penRed( PS_SOLID, m_nPenWidth, RGB(255,0,0) );</TT><TT> CPen* pOldPen = pDC->SelectObject( &penRed );</TT><TT> pDC->Ellipse( rcEllipse );</TT><TT> // Draw a black box around the ellipse, using one of the stock</TT><TT> // pens.</TT><TT> pDC->SelectStockObject( BLACK_PEN );</TT><TT> pDC->MoveTo( rcEllipse.TopLeft() );</TT><TT> pDC->LineTo( rcEllipse.right, rcEllipse.top );</TT><TT> pDC->LineTo( rcEllipse.BottomRight() );</TT><TT> pDC->LineTo( rcEllipse.left, rcEllipse.bottom );</TT><TT> pDC->LineTo( rcEllipse.left, rcEllipse.top );</TT><TT> // Draw an arc using the client area as a bounding rectangle.</TT><TT> // Clip the arc so that only the lower-left half is displayed.</TT><TT> CPen penDottedAndGreen( PS_DOT, 1, RGB(0,255,0) );</TT><TT> pDC->SelectObject( &penDottedAndGreen );</TT><TT> pDC->Arc(rcClient, rcClient.TopLeft(),rcClient.BottomRight());</TT><TT> pDC->SelectObject( &pOldPen );</TT><TT>}</TT></FONT></PRE><P>Compile and run the DCTest project, and experiment by changing the values in theMapping Mode dialog box. Figure 12.3 shows the DCTest project running with the mappingmode set to <TT>MM_TEXT</TT>.</P><P><A NAME="03"></A><A HREF="03.htm"><B>Figure 12.3.</B> </A><I><BR>The DCTest example after adding pen GDI objects.</I><H2><FONT COLOR="#000077"><B>What Are Brushes?</B></FONT></H2><P>A brush is a GDI object used to fill a control, window, or other area when programmingfor Windows. A brush is much like a pen; both are selected the same way, some ofthe attributes are similar, and you can use a series of stock objects without muchoverhead. However, you use a brush to fill an area rather than draw a line or a figure.A common use for brushes is to color windows, controls, or dialog boxes.</P><P>Every brush has several attributes:<UL> <LI><I>Color:</I> Specifies the brush color. You use a <TT>COLORREF</TT> value, just as when you specify a pen color.<BR> <BR> <LI><I>Pattern:</I> Defines the pattern used by the brush.<BR> <BR> <LI><I>Hatching Style:</I> Specifies a hatch pattern.</UL><P>By choosing different values for attributes given to a brush, you can achievea wide variety of effects.<H3><FONT COLOR="#000077"><B>MFC Support for Brushes</B></FONT></H3><P>In a program you write with Visual C++, you normally create and use <TT>CBrush</TT>objects the way you create and use <TT>CPen</TT> objects. Every brush has a set ofattributes that define how it appears and behaves. Just as with pens, Windows hasseveral stock brushes that are available by calling the <TT>SelectStockObject</TT>function.</P><P>Your Windows program can create four basic types of brushes:<UL> <LI>Solid brushes: Similar to solid pens, except they are used to fill areas instead of drawing lines. You normally give these brushes a color when you use a <TT>COLORREF</TT> to create them.<BR> <BR> <LI>Stock brushes: Predefined brushes stored and maintained by Windows.<BR> <BR> <LI>Hatch brushes: Fill an area with a predefined hatch pattern, as shown in Figure 12.4. These brushes can also be colored when they are created.<BR> <BR> <LI>Pattern brushes: Fill an area with a pattern supplied in an 8x8 bitmap, as shown in Figure 12.4.</UL><P><A NAME="04"></A><A HREF="04.htm"><B>Figure 12.4.</B> </A><I><BR>Examples of styles available for brushes.</I></P><P>You create each of these brush types using a different function call. For example,a solid brush is created using <TT>CreateSolidBrush</TT>, whereas a hatched brushis created using <TT>CreateHatchBrush</TT>. When using the <TT>CBrush</TT> class,it's also possible to call a specialized <TT>CBrush</TT> constructor to constructthe <TT>CBrush</TT> object in the desired style. You will use the <TT>CBrush</TT>class later in this hour.</P><P>You can create solid and hatch brushes with a color attribute that specifies thecolor used when the brush fills an area. In the case of a hatched brush, the colorspecifies the color of the hatching lines.<H3><FONT COLOR="#000077"><B>Hatch Styles for Brushes</B></FONT></H3><P>Six hatch styles are available for hatch brushes. You create a hatch style bypassing one of the following styles as a parameter when you create the brush:<UL>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -