⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch05.htm

📁 Learning language of Visual C++6
💻 HTM
📖 第 1 页 / 共 4 页
字号:
font. After all, if there's not enough space between the lines, the larger fonts
will overlap the smaller ones. When Windows created the new font, it stored the font's
height (most likely the height that you requested, but maybe not) in the LOGFONT
structure's lfHeight member. By adding the value stored in lfHeight, the program
can determine the next position at which to display the line of text. To make the
text appear onscreen, ShowFonts() calls TextOut().</P>
<P>TextOut()'s first two arguments are the X and Y coordinates at which to print
the text. The third argument is the text to print. Having printed the text, you restore
the old font to the DC in case this is the last time through the loop.</P>
<P>Build the application and run it. It should resemble Figure 5.3. If you click
the window, it will go blank because the ShowPens() routine doesn't draw anything.
Click again and it's still blank, this time because the ShowBrushes() routine doesn't
draw anything. Click a third time and you are back to the fonts screen.</P>
<P><A HREF="javascript:popUp('05uvc03.gif')"><B>FIG. 5.3</B></A><B> </B><I>The font
display shows different types of text output.</I></P>
<P>
<H3><A NAME="Heading7"></A>Sizing and Positioning the Window</H3>
<P>As you can see in Figure 5.3, Paint1 doesn't display eight different fonts at
800*600 screen settings--only seven can fit in the window. To correct this, you need
to set the size of the window a little larger than the Windows default. In an MFC
program, you do this in the mainframe class PreCreateWindow() function. This is called
for you just before the mainframe window is created. The mainframe window surrounds
the entire application and governs the size of the view.</P>
<P>PreCreateWindow() takes one parameter, a reference to a CREATESTRUCT structure.
The CREATESTRUCT structure contains essential information about the window that's
about to be created, as shown in Listing 5.5.</P>
<P>
<H4>Listing 5.5&#160;&#160;The CREATESTRUCT Structure</H4>
<PRE>typedef struct tagCREATESTRUCT {
   LPVOID    lpCreateParams;
   HANDLE    hInstance;
   HMENU     hMenu;
   HWND      hwndParent;
   int       cy;
   int       cx;
   int       y;
   int       x;
   LONG      style;
   LPCSTR    lpszName;
   LPCSTR    lpszClass;
   DWORD     dwExStyle;
</PRE>
<PRE>} CREATESTRUCT;
</PRE>
<P>If you've programmed Windows without application frameworks such as MFC, you'll
recognize the information stored in the CREATESTRUCT structure. You used to supply
much of this information when calling the Windows API function CreateWindow() to
create your application's window. Of special interest to MFC programmers are the
cx, cy, x, and y members of this structure. By changing cx and cy, you can set the
window width and height, respectively. Similarly, modifying x and y changes the window's
position. By overriding PreCreateWindow(), you have a chance to fiddle with the CREATESTRUCT
structure before Windows uses it to create the window.</P>
<P>AppWizard created a CMainFrame::PreCreateWindow() function. Expand CMainFrame
in ClassView, double-click PreCreateWindow() to edit it, and add lines to obtain
the code shown in Listing 5.6. This sets the application's height and width. It also
prevents users from resizing the application by using the bitwise and operator (&amp;)
to turn off the WS_SIZEBOX style bit.</P>
<P>
<H4>Listing 5.6&#160;&#160;CMainFrame::PreCreateWindow()</H4>
<PRE>BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&amp; cs)
{
     cs.cx = 440;
     cs.cy = 480;
     cs.style &amp;= ~WS_SIZEBOX;
      if( !CFrameWnd::PreCreateWindow(cs) )
            return FALSE;
      return TRUE;
</PRE>
<PRE>}
</PRE>
<P>It's important that after your own code in PreCreateWindow(), you call the base
class's PreCreateWindow(). Failure to do this will leave you without a valid window
because MFC never gets a chance to pass the CREATESTRUCT structure on to Windows,
so Windows never creates your window. When overriding class member functions, you
usually need to call the base class's version.</P>
<P>Build and run Paint1 to confirm that all eight fonts fit in the application's
window. Now you're ready to demonstrate pens.</P>
<P>
<H3><A NAME="Heading8"></A>Using Pens</H3>
<P>You'll be pleased to know that pens are much easier to deal with than fonts, mostly
because you don't have to fool around with complicated data structures like LOGFONT.
In fact, to create a pen, you need to supply only the pen's line style, thickness,
and color. The Paint1 application's ShowPens() function displays in its window the
lines drawn by using different pens created within a for loop. Listing 5.7 shows
the code.</P>
<P>
<H4>Listing 5.7&#160;&#160;CPaint1View::ShowPens()</H4>
<PRE>void CPaint1View::ShowPens(CDC * pDC)
{
     // Initialize the line position.
     UINT position = 10;
     // Draw sixteen lines in the window.
     for (UINT x=0; x&lt;16; ++x)
     {
          // Create a new pen and select it into the DC.
CPen pen(PS_SOLID, x*2+1, RGB(0, 0, 255));
          CPen* oldPen = pDC-&gt;SelectObject(&amp;pen);
          // Draw a line with the new pen.
          position +=  x * 2 + 10;
          pDC-&gt;MoveTo(20, position);
          pDC-&gt;LineTo(400, position);
          // Restore the old pen to the DC.
          pDC-&gt;SelectObject(oldPen);
     }
</PRE>
<PRE>}
</PRE>
<P>Within the loop, ShowPens() first creates a custom pen. The constructor takes
three parameters. The first is the line's style, one of the styles listed in Table
5.3. (You can draw only solid lines with different thicknesses. If you specify a
pattern and a thickness greater than 1 pixel, the pattern is ignored and a solid
line is drawn.) The second argument is the line thickness, which increases each time
through the loop. The third argument is the line's color. The RGB macro takes three
values for the red, green, and blue color components and converts them to a valid
Windows color reference. The values for the red, green, and blue color components
can be anything from 0 to 255--the higher the value, the brighter that color component.
This code creates a bright blue pen. If all the color values were 0, the pen would
be black; if the color values were all 255, the pen would be white.</P>
<P>
<H4>Table 5.3&#160;&#160;Pen Styles</H4>
<P>
<TABLE BORDER="1">
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT"><B>Style</B></TD>
		<TD ALIGN="LEFT"><B>Description</B></TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">PS_DASH</TD>
		<TD ALIGN="LEFT">A pen that draws dashed lines</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">PS_DASHDOT</TD>
		<TD ALIGN="LEFT">A pen that draws dash-dot patterned lines</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">PS_DASHDOTDOT</TD>
		<TD ALIGN="LEFT">A pen that draws dash-dot-dot patterned lines</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">PS_DOT</TD>
		<TD ALIGN="LEFT">A pen that draws dotted lines</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">PS_INSIDEFRAME</TD>
		<TD ALIGN="LEFT">A pen that's used with shapes, in which the line's thickness must not extend outside
			the shape's frame</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">PS_NULL</TD>
		<TD ALIGN="LEFT">A pen that draws invisible lines</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">PS_SOLID</TD>
		<TD ALIGN="LEFT">A pen that draws solid lines</TD>
	</TR>
</TABLE>



<BLOCKQUOTE>
	<P>
<HR>
<strong>NOTE:</strong> If you want to control the style of a line's end points or create
	your own custom patterns for pens, you can use the alternative CPen constructor,
	which requires a few more arguments than the CPen constructor described in this section.
	To learn how to use this alternative constructor, look up CPen in your Visual C++
	online documentation. 
<HR>


</BLOCKQUOTE>

<P>After creating the new pen, ShowPens() selects it into the DC, saving the pointer
to the old pen. The MoveTo() function moves the pen to an X,Y coordinate without
drawing as it moves; the LineTo() function moves the pen while drawing. The style,
thickness, and color of the pen are used. Finally, you select the old pen into the
DC.</P>


<BLOCKQUOTE>
	<P>
<HR>
<strong>TIP:[</strong> There are a number of line drawing functions other than LineTo(),
	including Arc(), ArcTo(), AngleArc(), and PolyDraw(). 
<HR>


</BLOCKQUOTE>

<P>Build and run Paint1 again. When the font display appears, click the window. You
will see a pen display similar to the one in Figure 5.4.</P>
<P>
<H3><A NAME="Heading9"></A>Using Brushes</H3>
<P>A pen draws a line of a specified thickness onscreen. A brush fills a shape onscreen.
You can create solid and patterned brushes and even brushes from bitmaps that contain
your own custom fill patterns. Paint1 will display both patterned and solid rectangles
in the ShowBrushes() function, shown in Listing 5.8.</P>
<P><A HREF="javascript:popUp('05uvc04.gif')"><B>FIG. 5.4</B></A><B> </B><I>The pen
display shows the effect of setting line thickness.</I></P>
<P>
<H4>Listing 5.8&#160;&#160;CPaint1View::ShowBrushes()</H4>
<PRE>void CPaint1View::ShowBrushes(CDC * pDC)
     // Initialize the rectangle position.
     UINT position = 0;
     // Select pen to use for rectangle borders
     CPen pen(PS_SOLID, 5, RGB(255, 0, 0));
     CPen* oldPen = pDC-&gt;SelectObject(&amp;pen);
     // Draw seven rectangles.
     for (UINT x=0; x&lt;7; ++x)
     {
          CBrush* brush;
          // Create a solid or hatched brush.
          if (x == 6)
               brush = new CBrush(RGB(0,255,0));
          else
              brush = new CBrush(x, RGB(0,160,0));
          // Select the new brush into the DC.
          CBrush* oldBrush = pDC-&gt;SelectObject(brush);
          // Draw the rectangle.
          position += 50;
          pDC-&gt;Rectangle(20, position, 400, position + 40);
          // Restore the DC and delete the brush.
          pDC-&gt;SelectObject(oldBrush);
          delete brush;
     }
     // Restore the old pen to the DC.
     pDC-&gt;SelectObject(oldPen);
</PRE>
<PRE>}
</PRE>
<P>The rectangles painted with the various brushes in this routine will all be drawn
with a border. To arrange this, create a pen (this one is solid, 5 pixels thick,
and bright red) and select it into the DC. It will be used to border the rectangles
without any further work on your part. Like ShowFonts() and ShowPens(), this routine
creates its graphical objects within a for loop. Unlike those two functions, ShowBrushes()
creates a graphical object (in this routine, a brush) with a call to new. This enables
you to call the one-argument constructor, which creates a solid brush, or the two-argument
constructor, which creates a hatched brush.</P>
<P>In Listing 5.8, the first argument to the two-argument constructor is just the
loop variable, x. Usually, you don't want to show all the hatch patterns but want
to select a specific one. Use one of these constants for the hatch style:</P>

<UL>
	<LI>HS_HORIZONTAL--Horizontal
	<P>
	<LI>HS_VERTICAL--Vertical
	<P>
	<LI>HS_CROSS--Horizontal and vertical
	<P>
	<LI>HS_FDIAGONAL--Forward diagonal
	<P>
	<LI>HS_BDIAGONAL--Backward diagonal
	<P>
	<LI>HS_DIAGCROSS--Diagonal in both directions
</UL>

<P>In a pattern that should be familiar by now, ShowBrushes() selects the brush into
the DC, determines the position at which to work, uses the brush by calling Rectangle(),
and then restores the old brush. When the loop is complete, the old pen is restored
as well.</P>
<P>Rectangle()is just one of the shape-drawing functions that you can call. Rectangle()
takes as arguments the coordinates of the rectangle's upper-left and lower-right
corners. Some others of interest are Chord(), DrawFocusRect(), Ellipse(), Pie(),
Polygon(), PolyPolygon(), Polyline(), and RoundRect(), which draws a rectangle with
rounded corners.</P>
<P>Again, build and run Paint1. Click twice, and you will see the demonstration of
brushes, as shown in Figure 5.5.</P>


<BLOCKQUOTE>
	<P>
<HR>
<strong>NOTE:</strong> Remember the call to Invalidate() in CPaint1View::OnLButtonDown()?
	Invalidate() actually takes a Boolean argument with a default value of TRUE. This
	argument tells Windows whether to erase the window's background. If you use FALSE
	for this argument, the background isn't erased. In Figure 5.6, you can see what happens
	to the Paint1 application if Invalidate() is called with an argument of FALSE.&#160;
	
<HR>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -