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

GDI+: The .NET Graphics Interface

349

CHAPTER 3.5

The meat of this application is substantially similar to that shown in Listing 3.5.4. The points of interest are lines 83–86, where the Bezier is drawn, and lines 92–96, which show you how to draw dashed lines. The image shown in Figure 3.5.4 is a screenshot of the application and shows how the Bezier control points are used to add direction and tension to a particular node.

FIGURE 3.5.4

The Bezier curve in action.

An array of points can also be used to create a multi-segmented Bezier Spline. The array must have a multiple of four points and is arranged as follows:

Point[0] = Start point of line segment 1

Point[1] = Control point for the start point

Point[2] = Control point for the end point

Point[3] = End point for line segment and start point of line segment 2

Point[4] = Control point for the start point of line segment 2

And so on, giving 4 initial points plus three for each subsequent line segment.

The GraphicsPath Object

GDI+ Graphics Paths are a convenient way of collecting together a number of graphical shapes, or their boundaries at least, into a single unit. A path, once created, can be manipulated in its entirety, filled, stroked, or used to perform other graphical operations, such as being used to create a clipping region.

Any combination of the following graphical primitives can be placed in a Path object:

Arcs

Bezier Splines

Cardinal splines

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

Windows Forms

350

PART III

Ellipses

Lines

Paths

Pie segments

Polygons

Rectangles

Character Glyphs from Strings

The following code snippet produces the result seen in Figure 3.5.5.

void OnPaint(object sender, PaintEventArgs e)

{

GraphicsPath p=new GraphicsPath(); p.AddEllipse(10,10,100,100); p.AddRectangle(new Rectangle(0,0,120,120)); Pen pen=new Pen(Color.Black,1); e.Graphics.DrawPath(pen,p);

pen.Dispose();

}

FIGURE 3.5.5

Two figures in a GraphicsPath.

Filling the path by substituting a suitable brush and fill command produces the following effect (see Figure 3.5.6):

SolidBrush brush = new SolidBrush(Color.Blue); e.Graphics.FillPath(brush,p);

FIGURE 3.5.6

A filled path.

GDI+: The .NET Graphics Interface

351

CHAPTER 3.5

The square part of the path has been filled and the circle has not. This is because the graphics FillMode for the path is set to the default setting, Alternate.

To fill everything inside the outermost boundary of the shape, set the FillMode to Winding.

Adding Text and Other Paths

One path can be added to another quite simply by calling the AddPath method. The following code snippet creates a second path and adds it to the one shown in Figure 3.5.5.

void OnPaint(object sender, PaintEventArgs e)

{

GraphicsPath p=new GraphicsPath(); p.AddEllipse(10,10,100,100); p.AddRectangle(new Rectangle(0,0,120,120)); Pen pen=new Pen(Color.Black,1); GraphicsPath p2=new GraphicsPath();

Point[] tripoint=new Point[3]; tripoint[0]=new Point(80,10); tripoint[1]=new Point(80,110); tripoint[2]=new Point(150,60); p2.AddClosedCurve(tripoint,(float)0); p2.AddPath(p,true);

SolidBrush brush = new SolidBrush(Color.Blue); e.Graphics.FillPath(brush,p2); e.Graphics.DrawPath(pen,p2);

}

Now the image displayed is the sum of the two paths. Figure 3.5.7 shows the output from the modified OnPaint handler.

FIGURE 3.5.7

The combination of two paths

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

Placing text in a path is a great way of creating text effects. A text path only contains the glyph outlines of the letters used. These outlines can be used to create clip paths, filled with patterns or colors, scaled, rotated, or otherwise transformed to make some pretty impressive effects.

Windows Forms

352

PART III

Modifying the code in our phantom OnPaint will illustrate again how this is accomplished.

void OnPaint(object sender, PaintEventArgs e)

{

GraphicsPath p=new GraphicsPath(); p.AddString(“AYBABTU”,FontFamily.GenericSansSerif,

0,(float)72,new Point(0,0), StringFormat.GenericDefault);

SolidBrush brush = new SolidBrush(Color.Blue); e.Graphics.FillPath(brush,p); brush.Dispose();

}

We’ll continue this discussion in the next section because it leads nicely into that topic.

Clipping with Paths and Regions

A region is a description of some enclosed shape that can be used as a mask in which to perform graphical operations. Regions can be regular shapes, like rectangles or ellipses; they can also be irregular, perhaps created from curves or text glyphs. Because regions can be created from paths, it is possible to have very complex, clipped shapes. Going back again to our previous text path example, we can create a clipping region from it and use it for other interesting things.

In the example shown in Listing 3.5.6, we use a path, filled with a text string, as a mask for randomly positioned ellipses of color that splatter the window but are clipped by the glyph outlines of the text.

LISTING 3.5.6 ClipToPath.cs: Using a Path to Clip the Drawing Area

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 Clipping

10:{

11:public class ClipToPath : System.Windows.Forms.Form

12:{

13:

14:Timer timer;

15:GraphicsPath p;

16:bool dirty;

GDI+: The .NET Graphics Interface

CHAPTER 3.5

LISTING 3.5.6 Continued

17:

18:void OnPaint(object sender, PaintEventArgs e)

19:{

20:Random r=new Random();

21:SolidBrush brush = new SolidBrush(

22:

Color.FromArgb(r.Next(255),

23:

r.Next(255),

24:

r.Next(255)));

25:e.Graphics.SetClip(p);

26:e.Graphics.FillEllipse(brush,

27:

r.Next(500),

28:

r.Next(200),

29:

r.Next(20),

30:

r.Next(20));

31:brush.Dispose();

32:}

33:

34:void OnTick(object sender, EventArgs e)

35:{

36:Invalidate();

37:}

38:

39:protected override void OnPaintBackground(PaintEventArgs e)

40:{

41:if(dirty)

42:{

43:

e.Graphics.ResetClip();

44:

SolidBrush b=new SolidBrush(this.BackColor);

45:

e.Graphics.FillRectangle(b, this.ClientRectangle);

46:

dirty = false;

47:

b.Dispose();

48:}

49:}

51:void OnSized(object sender, EventArgs e)

52:{

53:dirty=true;

54:Invalidate();

55:}

56:

57:public ClipToPath()

58:{

59:

60:p=new GraphicsPath();

61:p.AddString(“AYBABTU”,FontFamily.GenericSansSerif,

353

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

354

Windows Forms

PART III

 

 

LISTING 3.5.6

Continued

62:

 

0,(float)72,new Point(0,0),

63:

 

StringFormat.GenericDefault);

64:

 

dirty=true;

65:

 

this.Paint+=new PaintEventHandler(OnPaint);

66:

 

this.SizeChanged+=new EventHandler(OnSized);

67:

 

timer = new Timer();

68:

 

timer.Interval=10;

69:

 

timer.Tick+=new EventHandler(OnTick);

70:

 

timer.Enabled=true;

71:

}

 

72:

 

 

73:static void Main()

74:{

75:Application.Run(new ClipToPath());

76:}

77:}

78:}

The path is created once on lines 59–62 and stored for use later. Then a timer is initialized to enable the periodic refresh of the page.

Lines 39–48 handle the repaint of the background if the window is resized or on the first draw.

Finally, line 25 selects the clip-path into the Graphics object. The following lines place a random blob of color on the page; this might or might not be seen, depending on its coincidence with the clipping path.

After a while, the output from the application looks something like the image in Figure 3.5.8.

FIGURE 3.5.8

Painting clipped to a path.

Operations on regions are different from those on paths. A path specifies a set of boundaries, a region specifies an area or group of areas to be used as a mask. Regions can be combined in several ways. The operation is controlled by the CombineMode enumeration. Listing 3.5.7 illustrates the use of regions in four different modes.

GDI+: The .NET Graphics Interface

CHAPTER 3.5

LISTING 3.5.7 Regions.cs: Combining Regions in Different Ways

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 regions

10:{

11:/// <summary>

12:/// Summary description for Form1.

13:/// </summary>

14:public class RegionsTest : System.Windows.Forms.Form

15:{

16:void PaintRegions(Graphics g,CombineMode m,

Point offset,string text)

17:

{

18:

Region ra,rb;

19:

GraphicsPath p=new GraphicsPath();

20:

p.AddRectangle(new Rectangle(60,60,120,120));

21:

ra=new Region(p);

22:

p=new GraphicsPath();

23:

p.AddEllipse(0,0,120,120);

24:

rb=new Region(p);

25:

ra.Translate(offset.X,offset.Y );

26:

rb.Translate(offset.X,offset.Y);

27:

g.SetClip(ra,CombineMode.Replace);

28:

g.SetClip(rb,m);

29:

SolidBrush brush=new SolidBrush(Color.Black);

30:

g.FillRectangle(brush,this.ClientRectangle);

31:

g.ResetClip();

32:

g.DrawString(text,

33:

new Font(“Ariel”,(float)16),

34:

brush,(float)offset.X+60,(float)offset.Y+220);

35:

}

36:

 

37:

void OnPaint(object sender, PaintEventArgs e)

38:

{

39:

// A union of two regions...

40:

PaintRegions(e.Graphics,CombineMode.Union,

41:

new Point(0,0),”Union”);

42:

// the intersection of two regions

43:

PaintRegions(e.Graphics,CombineMode.Intersect,

44:

new Point(250,0),”Intersect”);

355

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

Windows Forms

356

PART III

LISTING 3.5.7 Continued

45:// Region exclusive or

46:PaintRegions(e.Graphics,CombineMode.Xor,

47: new Point(500,0),”Xor”);

48:// The complement of the two regions

49:PaintRegions(e.Graphics,CombineMode.Complement,

50: new Point(0,250),”Complement”);

51:// Exclusion.

52:PaintRegions(e.Graphics,CombineMode.Exclude,

53:

new Point(250,250),”Exclude”);

54:

}

55:

 

56:public RegionsTest()

57:{

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

59:this.Size = new Size(800,800);

60:}

61:

62:static void Main()

63:{

64:Application.Run(new RegionsTest());

65:}

66:}

67:}

OnPaint (lines 37–54) repeatedly calls the PaintRegions method with a distinct CombineMode setting, some positional information, and an identifying string. The PaintRegions method (lines 16–35) begins by declaring two regions, ra and rb, and filling them with a circle and a rectangle. Lines 25 and 26 ensure that the regions are moved into position ready for display, and then line 27 selects the first clip region, replacing the one that already exists in the Graphics object. The second region is combined with the CombineMode, supplied on line 28, and the whole rectangle of the client area filled with black. Note that only the area inside the clipped region is filled. The program then removes the clipping region on line 31 to draw the information text on lines 32–34.

Output from this program is shown in Figure 3.5.9.