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

GDI+: The .NET Graphics Interface

341

CHAPTER 3.5

LISTING 3.5.3 Continued

55:button1 = new Button();

56:button1.Location=new Point(5,5);

57:button1.Size=new Size(50,20);

58:button1.Text = “Caps”;

59:button1.Click+=new EventHandler(OnClickedButton1);

60:this.Controls.Add(button1);

61:

62: } 63:

64:static void Main()

65:{

66:Application.Run(new drawstar());

67:}

68:};

Compile this program with the following command line:

csc /t:winexe drawstar.cs

When you run the program, you will see a button in the top-left corner of the window, click it to change to rounded end caps. There are 11 different line cap styles altogether, including a custom style.

Already you can see that GDI+ is a great improvement over good old trusty GDI, and we’ve only really looked at lines and rectangles. Let’s now look at curves, paths, and splines.

Curves and Paths

GDI has had Bezier curves and temporary paths for some time. GDI+ expands these capabilities by providing a rich set of functionality for curves and a persistent path object.

The simplest form is the curve drawn from an array of points. The curve is drawn so that it passes through each point on the array. The tension of the curve for any particular point is controlled by the positions of the points on either side of it in the array. The true Bezier curve has two points associated with each node—a position and a control point. Tension of the curve is determined by the relationship of the control point to the direction of the line.

Listing 3.5.4 illustrates the use of the Graphics.DrawCurve method by creating a set of positions that bounce around in a rectangular area onscreen. A curve, or Cardinal Spline, is drawn along this array of points, and you can select the tension of the curve with a slider.

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

Windows Forms

342

PART III

LISTING 3.5.4 DrawCurve.cs: Using the DrawCurve Method

1:using System;

2:using System.Drawing;

3:using System.Drawing.Drawing2D;

4:using System.Collections;

5:using System.ComponentModel;

6:using System.Windows.Forms;

7:using System.Data;

8:

9:namespace Curves

10:{

11:/// <summary>

12:/// This simple object bounces points

13:/// around a rectangular area.

14:/// </summary>

15:class Bouncer

16:{

17:int dirx;

18:int diry;

19:int X;

20:int Y;

21:

22: Size size; 23:

24:public Bouncer()

25:{

26:dirx=diry=1;

27:}

28:

29:public void Move()

30:{

31:X+=dirx;

32:Y+=diry;

33:

34:if(X<=0 || X>=size.Width)

35:dirx*=-1;

36:

37:if(Y<=0 || Y>=size.Height)

38:diry*=-1;

39:}

40:

41:public Point Position

42:{

43:get{return new Point(X,Y);}

44:set{X=value.X; Y=value.Y;}

45:}

GDI+: The .NET Graphics Interface

343

CHAPTER 3.5

LISTING 3.5.4 Continued

46:

 

47:

public Size Size

48:

{

49:

get{ return size;}

50:

set{size = value;}

51:

}

52:

}

53:

 

54:

/// <summary>

55:

/// Summary description for Form1.

56:

/// </summary>

57:

public class Curves : System.Windows.Forms.Form

58:

{

59:

 

60:

Timer bounce,paint;

61:

TrackBar trk;

62:

 

63:

Bouncer[] bouncers;

64:

 

65:

void OnTickBounce(object sender, EventArgs e)

66:

{

67:

foreach(Bouncer b in bouncers)

68:

b.Move();

69:

}

70:

 

71:

void OnTickPaint(object sender, EventArgs e)

72:

{

73:

Invalidate();

74:

}

75:

 

76:

public void OnPaint(object sender, PaintEventArgs e)

77:

{

78:

Pen p=new Pen(Color.Red,10);

79:

SolidBrush br=new SolidBrush(Color.Blue);

80:

Point[] points = new Point[bouncers.Length];

81:

int i=0;

82:

// need to translate our bouncers to an array of points

83:

foreach(Bouncer b in bouncers)

84:

points[i++]=b.Position;

85:

//Draw the curve

86:

e.Graphics.DrawCurve(p,points,0,points.Length-

1,(float)trk.Value);

87://now draw the nodes in the curve.

88:foreach(Point pn in points)

89:e.Graphics.FillEllipse(br,pn.X-5,pn.Y-5,10,10);

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

Windows Forms

344

PART III

LISTING 3.5.4 Continued

90:p.Dispose();

91:br.Dispose();

92:}

93:

94:public Curves()

95:{

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

97:// A timer to manage the bouncing

98:bounce=new Timer();

99:bounce.Interval=5;

100:bounce.Tick+=new EventHandler(OnTickBounce);

101:// A timer to manage the painting refresh

102:paint=new Timer();

103:paint.Interval=100;

104:paint.Tick+=new EventHandler(OnTickPaint);

105:// Random number generator for initial positions

106:Random r=new Random();

107:// the form initial size

108:this.Size=new Size(800,600);

109://iniialize an array of bouncing points

110:bouncers = new Bouncer[6];

111:for(int i=0;i<6;i++)

112:{

113:bouncers[i]=new Bouncer();

114:bouncers[i].Position=new Point(r.Next(800),r.Next(600));

115:bouncers[i].Size=new Size(800,600);

116:}

117:// turn on the timers

118:bounce.Enabled=true;

119:paint.Enabled=true;

120://create a trackbar for the line tension

121:trk = new TrackBar();

122:trk.Location=new Point(5,25);

123:trk.Size=new Size(100,20);

124:trk.Minimum=1;

125:trk.Maximum=10;

126:trk.Value=2;

127:this.Controls.Add(trk);

128://and label it nicely for the user

129:Label lb=new Label();

130:lb.Location=new Point(5,5);

131:lb.Size=new Size(100,20);

132:lb.Text=”Curve tension”;

133:this.Controls.Add(lb);

134:}

GDI+: The .NET Graphics Interface

345

CHAPTER 3.5

LISTING 3.5.4 Continued

135:

136:static void Main()

137:{

138:Application.Run(new Curves());

139:}

140:}

141:}

Compile Listing 3.5.4 with the following command line:

Csc /t:winexe drawcurve.cs

The work is done by two timers and a paint handler. Timer #1 (lines 98 and 65–69) makes the positions of the curve nodes bounce around the screen. Timer #2 (lines 102 and 71–74) invalidates the screen so that the painting is not done too frequently. The paint handler (lines 76–90) creates an array of points from the bounce object; sadly, Point is a sealed class so you cannot inherit from it, which would have been useful. Then line 86 draws the curve, the tension of which depends on the position of the TrackBar control. To illustrate where the individual points are, lines 88 and 89 draw them in blue. This demonstration clearly shows how line tension works for the simple curve.

Figure 3.5.3 shows the DrawCurves application running.

FIGURE 3.5.3

Drawing a curve with tension.

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

A Bezier Spline is somewhat different. For each line segment, two points define the start and end of the line, and another two determine the control points that add the line tension and curvature. Listing 3.5.5 shows how a Bezier curve is used.

Windows Forms

346

PART III

LISTING 3.5.5 Beziercurves.cs: Using the Bezier Curve

1:using System;

2:using System.Drawing;

3:using System.Drawing.Drawing2D;

4:using System.Collections;

5:using System.ComponentModel;

6:using System.Windows.Forms;

7:using System.Data;

8:

9:namespace Curves

10:{

11:/// <summary>

12:/// This simple object bounces points

13:/// around a rectangular area.

14:/// </summary>

15:class Bouncer

16:{

17:int dirx;

18:int diry;

19:public int X;

20:public int Y;

21:

22: Size size; 23:

24:public Bouncer()

25:{

26:dirx=diry=1;

27:}

28:

29:public void Move()

30:{

31:X+=dirx;

32:Y+=diry;

33:

34:if(X<=0 || X>=size.Width)

35:dirx*=-1;

36:

37:if(Y<=0 || Y>=size.Height)

38:diry*=-1;

39:}

40:

41:public Point Position

42:{

43:get{return new Point(X,Y);}

44:set{X=value.X; Y=value.Y;}

45:}

GDI+: The .NET Graphics Interface

CHAPTER 3.5

LISTING 3.5.5 Continued

46:

47:public Size Size

48:{

49:get{ return size;}

50:set{size = value;}

51:}

52:}

53:

54:/// <summary>

55:/// Summary description for Form1.

56:/// </summary>

57:public class BezierCurves : System.Windows.Forms.Form

58:{

59:

60:Timer bounce,paint;

61:63: Bouncer[] bouncers;

63:void OnTickBounce(object sender, EventArgs e)

64:{

65:foreach(Bouncer b in bouncers)

66:b.Move();

67:}

68:

69:void OnTickPaint(object sender, EventArgs e)

70:{

71:Invalidate();

72:}

73:

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

75:{

76:Pen p=new Pen(Color.Red,10);

77:p.StartCap=LineCap.DiamondAnchor;

78:p.EndCap=LineCap.ArrowAnchor;

79:SolidBrush br=new SolidBrush(Color.Blue);

80://Draw the curve

81:e.Graphics.DrawBezier(p,new Point(550,300),

82:

bouncers[0].Position,

83:

bouncers[1].Position,

84:

new Point(50,300));

85://now draw the nodes in the curve.

86:foreach(Bouncer b in bouncers)

87:e.Graphics.FillEllipse(br,b.X-5,b.Y-5,10,10);

88://and show the relation between the bouncing node

89://and the bezier end point

347

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

Windows Forms

348

PART III

LISTING 3.5.5 Continued

90:p=new Pen(Color.Black,1);

91:p.DashStyle=DashStyle.DashDotDot;

92:e.Graphics.DrawLine(p,bouncers[0].Position,new Point(550,300));

93:e.Graphics.DrawLine(p,bouncers[1].Position,new Point(50,300));

94:p.Dispose();

95:}

96:

97:public BezierCurves()

98:{

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

100:// A timer to manage the bouncing

101:bounce=new Timer();

102:bounce.Interval=5;

103:bounce.Tick+=new EventHandler(OnTickBounce);

104:// A timer to manage the painting refresh

105:paint=new Timer();

106:paint.Interval=100;

107:paint.Tick+=new EventHandler(OnTickPaint);

108:// Random number generator for initial positions

109:Random r=new Random();

110:// the form initial size

111:this.Size=new Size(800,600);

112://iniialize an array of bouncing points

113:bouncers = new Bouncer[2];

114:for(int i=0;i<2;i++)

115:{

116:bouncers[i]=new Bouncer();

117:bouncers[i].Position=new Point(r.Next(800),r.Next(600));

118:bouncers[i].Size=new Size(800,600);

119:}

120:// turn on the timers

121:bounce.Enabled=true;

122:paint.Enabled=true;

123:}

124:

125:static void Main()

126:{

127:Application.Run(new BezierCurves());

128:}

129:}

130: }