📄 ch12.htm
字号:
<TD ALIGN="LEFT">Using the current pen, draws a line on the canvas from an array of points. The points are not automatically closed.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Rectangle</TD> <TD ALIGN="LEFT">Draws a rectangle on the canvas outlined by the current pen and filled with the current brush.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">RoundRect</TD> <TD ALIGN="LEFT">Draws a filled rectangle with rounded corners.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"><I>Method</I></TD> <TD ALIGN="LEFT"><I>Description</I></TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">StretchDraw</TD> <TD ALIGN="LEFT">Copies a bitmap from memory to the canvas. The bitmap is stretched or reduced according to the size of the destination rectangle.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">TextExtent</TD> <TD ALIGN="LEFT">Returns the width and height in pixels of the string passed in the Text parameter. The width is calculated using the current font of the canvas.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">TextHeight</TD> <TD ALIGN="LEFT">Returns the height in pixels of the string passed in the Text parameter. The width is calculated using the current font of the canvas.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">TextOut</TD> <TD ALIGN="LEFT">Using the current font, draws text on the canvas at a specified</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">location.</TD> <TD ALIGN="LEFT"></TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">TextRect</TD> <TD ALIGN="LEFT">Draws text within a clipping rectangle.</TD> </TR></TABLE></P><P>Believe it or not, these properties and methods represent just a small part ofthe functionality of a Windows device context. The good news is that these propertiesand methods cover 80 percent of the tasks you will need to perform when working withgraphics. However, before I can talk more about the TCanvas class in detail, I needto talk about graphics objects used in Windows programming.</P><P><H2><A NAME="Heading3"></A>GDI Objects</H2><P>The Windows Graphics Device Interface (GDI) has many types of objects that definehow a device context functions. The most commonly used GDI objects are pens, brushes,and fonts. Other GDI objects include palettes, bitmaps, and regions. Let's take alook at pens, brushes, and fonts first and then move on to more complex objects.</P><P><H3><A NAME="Heading4"></A>Pens, Brushes, and Fonts</H3><P>Pens, brushes, and fonts are straightforward. Let's take a brief look at eachof these GDI objects and how the TCanvas class uses them.</P><PRE></PRE><H4>Pens</H4><P>A pen defines the object that is being used to draw lines. A line might be a singleline from one point to the next, or it might be the border drawn around rectangles,ellipses, and polygons. The pen is accessed through the Pen property of the TCanvasclass and is an instance of the TPen class. Table 12.3 lists the properties of TPen.There are no methods or events of TPen that are worthy of note.</P><P><H4>TABLE 12.3. TPen PROPERTIES.</H4><P><TABLE BORDER="1"> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"><I>Property</I></TD> <TD ALIGN="LEFT"><I>Description</I></TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Color</TD> <TD ALIGN="LEFT">Sets the color of the line.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Handle</TD> <TD ALIGN="LEFT">The handle to the pen (HPEN). Used when calling the GDI directly.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Mode</TD> <TD ALIGN="LEFT">Determines how lines will be drawn (normal, inverse, xor, and so on).</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Style</TD> <TD ALIGN="LEFT">The pen's style. Styles can be solid, dotted, dashed, dash-dot, clear, and more.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Width</TD> <TD ALIGN="LEFT">The width of the pen in pixels.</TD> </TR></TABLE></P><P>For the most part, these properties are used exactly as you would expect. Thefollowing example draws a red, dashed line:</P><P><PRE>Canvas.Pen.Color := clRed;Canvas.Pen.Style := psDash;Canvas.MoveTo(20, 20);Canvas.LineTo(120, 20);</PRE><P>To test this code, drop a button on a form and type the code in the OnClick handlerfor the button. When you click the button, the line will be drawn on the form.</P><BLOCKQUOTE> <P><HR><strong>NOTE:</strong> The simple examples in this chapter can all be tested in this manner. However, if you cover the application and bring it to the top, the drawing will be gone. This is because the drawing is temporary. If you want the drawing to be persistent, place the drawing code in the OnPaint event handler for the form. Any time a window needs to be repainted, its OnPaint event is generated and your drawing code will be executed. <HR></BLOCKQUOTE><P>The dashed and dotted pen styles can be used only with a pen width of 1. The psClearpen style can be used to eliminate the line that the Windows GDI draws around theoutside of objects such as rectangles, ellipses, and filled polygons.</P><BLOCKQUOTE> <P><HR><strong>TIP:</strong> You can experiment with the various properties of TPen by dropping a Shape component on a form and modifying the shape's Pen property. This is especially useful for seeing the effects of the Mode property of the TPen class. <HR></BLOCKQUOTE><H4>Brushes</H4><P>A brush represents the filled area of a graphical shape. When you draw an ellipse,rectangle, or polygon, the shape will be filled with the current brush. When youthink of a brush you probably think of a solid color. Many times this is the case,but a brush is more than just a color. A brush can also include a pattern or a bitmap.The TCanvas class has a property called Brush, which you can use to control the appearanceof the brush. The Brush property is an instance of the TBrush class. As with TPen,the TBrush class doesn't have any methods or events of note. The TBrush propertiesare listed in Table 12.4.</P><P><H4>TABLE 12.4. TBrush PROPERTIES.</H4><P><TABLE BORDER="1"> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"><I>Property</I></TD> <TD ALIGN="LEFT"><I>Description</I></TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Bitmap</TD> <TD ALIGN="LEFT">The bitmap to be used as the brush's background. For Windows 95 the bitmap must be no larger than 8¥8.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Color</TD> <TD ALIGN="LEFT">Sets the color of the brush.</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Handle</TD> <TD ALIGN="LEFT">The handle to the brush (HBRUSH). Used when calling the GDI</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">directly.</TD> <TD ALIGN="LEFT"></TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Style</TD> <TD ALIGN="LEFT">The brush's style. Styles include solid, clear, or one of several patterns.</TD> </TR></TABLE></P><P>By default, the Style property is set to bsSolid. If you want a pattern fill,you should set the Style property to one of the pattern styles (bsHorizontal, bsVertical,bsFDiagonal, bsBDiagonal, bsCross, or bsDiagCross). The following example draws acircle on the form using a 45 degree hatched pattern. Figure 12.1 shows the formwhen this code executes.</P><P><PRE>Canvas.Brush.Color := clBlue;Canvas.Brush.Style := bsDiagCross;Canvas.Ellipse(20, 20, 220, 220);</PRE><P><A HREF="javascript:popUp('28671201.gif')"><B>FIGURE 12.1.</B></A><B> </B><I>Acircle filled with a hatched brush.</I></P><P>When using a pattern brush, the brush's Color property defines the color of thelines that make up the pattern. For some reason, VCL automatically forces the backgroundmode to transparent when using a pattern fill. This means that the background colorof the brush will be the same as the background color of the window on which theshape is drawn.</P><P>Take another look at Figure 12.1 and you will see that the background color ofthe circle is the same color as the form (I know it's not easy to see in grayscale).If you want to specify a background color, you need to circumvent VCL and go to theAPI. Here's how the code would look if you want to use a blue hatch on a white background:</P><P><PRE>Canvas.Brush.Color := clBlue;</PRE><PRE>Canvas.Brush.Style := bsDiagCross;SetBkMode(Canvas.Handle, OPAQUE);SetBkColor(Canvas.Handle, clWhite);Canvas.Ellipse(20, 20, 220, 220);</PRE><P>Now the background color of the brush will be white. Figure 12.2 shows the circlewith the new code applied.</P><P><A HREF="javascript:popUp('28671202.gif')"><B>FIGURE 12.2.</B></A><B> </B><I>Thehatched brush with a white background.</I></P><P>Another interesting feature of brushes is the bitmap background option. Firstlook at the code and then I'll tell you more about bitmap brushes. Here it is:</P><P><PRE>Canvas.Brush.Bitmap := TBitmap.Create;</PRE><PRE>Canvas.Brush.Bitmap.LoadFromFile(`bkgnd.bmp');Canvas.Ellipse(20, 20, 220, 220);Canvas.Brush.Bitmap.Free;</PRE><P>The first line in this code snippet creates a TBitmap object and assigns it tothe Bitmap property of the brush. The Bitmap property is not assigned by default,so you have to specifically create a TBitmap object and assign it to the Bitmap property.The second line loads a bitmap from a file. The bitmap must be no larger than 8 pixelsby 8 pixels. You can use a larger bitmap, but it will be cropped to 8¥8. Thethird line in this example draws the ellipse. After the ellipse has been drawn, theBrush property is deleted. It is necessary to delete the Brush property because VCLwon't do it for you in this case. If you fail to delete the Brush property, yourprogram will leak memory. Figure 12.3 shows the ellipse drawn with a bitmap brush.</P><P><A HREF="javascript:popUp('28671203.gif')"><B>FIGURE 12.3.</B></A><B> </B><I>Anellipse with a bitmap brush.</I></P><P>Sometimes you need a hollow brush. A hollow (or clear) brush enables the backgroundto show through. To create a hollow brush, just set the brush's Style property tobsClear. Let's take the previous example and add a second circle inside the firstusing a hollow brush. Figure 12.4 shows the results. Here's the code:</P><P><PRE>Canvas.Pen.Width := 1;</PRE><PRE>Canvas.Brush.Bitmap := TBitmap.Create;Canvas.Brush.Bitmap.LoadFromFile(`bkgnd.bmp');Canvas.Ellipse(20, 20, 220, 220);Canvas.Brush.Style := bsClear;Canvas.Pen.Width := 5;Canvas.Ellipse(70, 70, 170, 170);Canvas.Brush.Bitmap.Free;</PRE><P><A HREF="javascript:popUp('28671204.gif')"><B>FIGURE 12.4.</B></A><B> </B><I>Acircle with a hollow brush.</I></P><P>You can do other things with brushes if you go directly to the API. Most of thetime, though, the VCL TBrush class does the job.</P><P><H4>Fonts</H4><PRE>Fonts aren't anything new to you; you have been using them throughout the book. Fonts used with the TCanvas class are no different than those used with forms or other components. The Font property of TCanvas is the same as the Font property of any other component. To change the font for the canvas, just do this:</PRE><PRE>Canvas.Font.Name := `Courier New';Canvas.Font.Size := 14;Canvas.Font.Style := Canvas.Font.Style + [fsBold];Canvas.TextOut(20, 20, `Testing');</PRE><P>That's all there is to it. I'll talk more about what to do with fonts a littlelater in the section "Drawing Text."</P><P><H3><A NAME="Heading5"></A>Bitmaps and Palettes</H3><P>Bitmaps and palettes go together most of the time. The TBitmap class encapsulatesa bitmap object in Delphi. Loading and displaying bitmaps is easy when using thisclass. You already saw TBitmap in action in the Jumping Jack program on Day 8, "CreatingApplications in Delphi." The TBitmap class is used in a wide variety of situations.I'll look at some of those situations later today when talking about drawing bitmapsand about memory bitmaps. The TBitmap class is complex, so I won't go over everyproperty and method here.</P><P>Palettes are one of the most confusing aspects of Windows programming. Most ofthe time the palette is maintained by the TBitmap object, so you really don't haveto worry about it. Rather than trying to explain the importance of palettes, letme show you an example.</P><P>Start a new application and type the following code in the OnPaint event handler,or use a button click event. Be sure to enter the correct path to the HANDSHAK.BMPfile. (You should find it in the Borland Shared Files/Images/Splash/256Color directory.)Here's the code:</P><P><PRE>var Bitmap : TBitmap;begin Bitmap := TBitmap.Create; { Bitmap.IgnorePalette := True; } Bitmap.LoadFromFile(`handshak.bmp'); Canvas.Draw(0, 0, Bitmap); Bitmap.Free;end;</PRE><PRE>Notice that one line is commented out with curly braces. Run the program and you will see a nice bitmap on the form. Now uncomment the line that is commented out. This line tells the VCL to ignore the palette information when displaying the bitmap. Run the program again. This time you should notice that the bitmap's colors are all wrong (you might not notice this effect if your video adapter is set to display more than 256 colors). This is because the palette is not being applied. The palette makes sure that the correct colors for the bitmap are mapped to the system palette.</PRE><P>Bitmap and palette objects play an important role in graphics operations. It takessome time to understand everything that they entail, so don't feel bad if you don'tcatch onto it right away.</P><P><H3><A NAME="Heading6"></A>Clipping Regions</H3><P><I>Regions</I> are areas of the screen that can be used to control the parts ofthe canvas that can be drawn on. The TCanvas class has a ClipRect property, but itis read-only. To change the clipping region, you have to use the Windows API. Let'stake the previous example and modify it slightly to illustrate how clipping regionswork. Here's the code:</P><P><PRE>var Bitmap : TBitmap; Rgn : HRGN;begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -