Скачиваний:
64
Добавлен:
15.03.2015
Размер:
4.31 Mб
Скачать

Windows Forms

336

PART III

LISTING 3.5.1 Continued

64:

65:static void Main()

66:{

67:Application.Run(new drawlines());

68:}

69:};

Compile Listing 3.5.1 by using the following command line:

csc /t:winexe drawlines.cs

Lines 53–62 set up the application by creating a timer and by adding the OnPaint handler to the Paint event list. It also adds an event handler for the SizeChanged event, so that we can detect when a new background needs painting.

Lines 10–13 are a simple Tick event handler that just invalidates the window. And lines 15–29 are the paint handler that creates a pen and draws a line between two random coordinates onscreen.

Lines 31–43 paint the background for us. The reason that it’s done this way is so that the invalidation of the screen doesn’t paint over the lines already drawn. You can take this out if you like to see what happens. It illustrates how a brush fills a rectangle.

Using Gradient Pens and Brushes

Pens and brushes have come a long way in a short time. GDI+ allows you to have lines and filled areas that show a gradient or sweep of colors. Modifying the code in Listing 3.5.1 will allow us to use the gradient pens or gradient fills instead of solid lines or colors.

To fill the background of the window is simple enough, we just need to specify a gradient fill brush. The LinearGradientBrush object is a member of the System.Drawing.Drawing2d namespace. Drawing a gradient fill on a line is very simple, because one of the overloads allows you to specify two Point objects, each at opposite corners of a rectangle.

Listing 3.5.2 is a selective listing of the two sections you need to change in the example from Listing 3.5.1. It contains only the modified routines OnPaint and OnPaintBackground. Remember, though, to add the declaration

Using System.Drawing.Drwing2D;

to your source also.

GDI+: The .NET Graphics Interface

CHAPTER 3.5

LISTING 3.5.2 DrawLines2.cs: The Modified Line and Fill Code for DrawLines.cs

1:

2:public void OnPaint(object sender, PaintEventArgs e)

3:{

4:// the current graphics object for

5:// this window is in the PaintEventArgs

6:

7: Random r=new Random(); 8:

9:Color cA=Color.FromArgb(r.Next(255),r.Next(255),r.Next(255));

10:Color cB=Color.FromArgb(r.Next(255),r.Next(255),r.Next(255));

11:Point pA=new Point(r.Next(this.ClientSize.Width),

12: r.Next(this.ClientSize.Height));

13:Point pB=new Point(r.Next(this.ClientSize.Width),

14: r.Next(this.ClientSize.Height));

15:LinearGradientBrush brush = new LinearGradientBrush(pA,pB,cA,cB);

16:Pen p=new Pen(brush,(float)r.NextDouble()*10);

17:e.Graphics.DrawLine(p,pA,pB);

18:p.Dispose();

19: } 20:

21:protected override void OnPaintBackground(PaintEventArgs e)

22:{

23:// When we resize or on the first time run

24:// we’ll paint the background, otherwise

25:// it will be left so the lines build up

26:if(BackgroundDirty)

27:{

28:BackgroundDirty = false;

29:LinearGradientBrush gb=

30:new LinearGradientBrush(this.ClientRectangle,

31:

Color.Navy,

32:

Color.Aquamarine,

33:

90);

34:e.Graphics.FillRectangle(gb,this.ClientRectangle);

35:gb.Dispose();

36:}

37: 38: }

337

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

Figure 3.5.1 shows the application running in all it’s garish glory.

Windows Forms

338

PART III

FIGURE 3.5.1

The modified DrawLines program.

NOTE

You might notice that the pen itself uses a brush for filling its internal color. You can also use a hatch brush or a pattern brush to draw a line. This is very powerful indeed.

Textured Pens and Brushes

You saw in the previous example that a pen can be given a brush with which to paint the line. Brushes can be solid, gradients, textures, or hatch patterns. A textured brush can be used to draw lines that are painted with a bitmap image. To accomplish this, you can load in a bitmap from a file or a resource, create a brush with it, pass the brush to a pen, and finally draw your lines with the pen. The following snippet of code shows this process:

Image i=Image.FromFile(“stone.bmp”); TextureBrush b= new TextureBrush(i); Pen p=new Pen(b,10); e.Graphics.DrawLine(p,0,0,100,100); p.Dispose();

As you can see, a ridiculously simple thing to do.

GDI+: The .NET Graphics Interface

339

CHAPTER 3.5

Tidying up Your Lines with Endcaps

The line segments shown in Figure 3.5.1 have ends that are cut squarely and might not be good for drawing polygons. Figure 3.5.2 shows how wide lines with square ends look when used to draw a simple star.

FIGURE 3.5.2

Flat end caps used in a polygon.

As you can see, the flat end caps make a mess of the shape where the lines join. To tidy this up, we can specify a rounded end cap for the lines. Pens have two properties, StartCap and EndCap, that can be set to draw specialized ends on your lines. In Listing 3.5.3, we show the program that draws the star and allows you to turn end caps on or off with a button on the form.

LISTING 3.5.3 DrawStar.cs: The Line Cap Example

1:using System;

2:using System.Drawing;

3:using System.Drawing.Drawing2D;

4:using System.Windows.Forms;

5:

6:class drawstar : System.Windows.Forms.Form

7:{

8:Button button1;

9:

10: bool EndCap;

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

Windows Forms

340

PART III

LISTING 3.5.3 Continued

11:

12:public void OnPaint(object sender, PaintEventArgs e)

13:{

14:Pen pen=new Pen(Color.Black,(float)20.0);

15:if(EndCap)

16:{

17:pen.StartCap=LineCap.Round;

18:pen.EndCap=LineCap.Round;

19:}

20:

21:float r36 = (float)(36.0 * 3.1415926 / 180);

22:Point Center=new Point(this.ClientRectangle.Width/2,

23:

this.ClientRectangle.Height/2);

24:float Pointsize = (float)0.8*Math.Min(Center.X,Center.Y);

25:for(int i=0; i<10; i++)

26:{

27:float d1=(i & 1)==1 ? Pointsize / 2 : Pointsize;

28:float d2=(i & 1)==0 ? Pointsize / 2 : Pointsize;

29:e.Graphics.DrawLine(pen,

30:new Point((int)(d1*Math.Cos(r36*i))+Center.X,

31: (int)(d1*Math.Sin(r36*i))+Center.Y),

32:new Point((int)(d2*Math.Cos(r36*(i+1)))+Center.X,

33: (int)(d2*Math.Sin(r36*(i+1))+Center.Y)));

34:}

35:pen.Dispose();

36:}

37:

38:public void OnSizeChanged(object sender, EventArgs e)

39:{

40:Invalidate();

41:}

42:

43:public void OnClickedButton1(object sender, EventArgs e)

44:{

45:EndCap = !EndCap;

46:Invalidate();

47:}

48:

49:public drawstar()

50:{

51:this.Paint+=new PaintEventHandler(OnPaint);

52:this.Text=”Star”;

53:this.SizeChanged+=new EventHandler(OnSizeChanged);