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

Windows Forms

332

PART III

In this chapter, we’ll look at the Graphical Device Interface (GDI) used by Windows Forms to create graphics. Notice the name is GDI+ not GDI.NET. This is because GDI+ is not solely a

.NET Framework API. It can also be used by unmanaged code. For the purposes of this chapter however, we’ll use it exclusively from Windows Forms.

The Basic Principles of GDI+

Like its predecessor GDI, GDI+ is an immediate mode graphics system. This means that as you send commands to the graphic interface, effects are seen on the device surface or in the display memory immediately. The other kind of graphics system, retained mode graphics, usually maintain hierarchies of objects that know how to paint themselves.

GDI+ uses brushes and pens to paint on the graphics surface, just like GDI did. Unlike GDI, though, you can use any graphical object on any surface at any time. GDI required you to create a graphics object, select it for use in a Device Context (DC), use the object, deselect it from the DC, and then destroy the object. If you didn’t do it in that order, you could get system resource leaks that would eventually cause all the memory in your system to be allocated away and the system would need a reboot. GDI+ is altogether friendlier to use because you don’t have to worry about selecting and deselecting objects in the right order.

As you might expect, the evolution of GDI+ reflects many of the recent changes in graphics card capabilities. Additions to your graphics arsenal include Alpha Blending or image transparency, antialiasing, transformations like rotation and scaling, plus many new innovations in the areas of color correction and region manipulation.

The Graphics Object

The root of all GDI+ graphics capabilities for .NET is the Graphics object. This is analogous to the Win32 DC and can be obtained explicitly from a window handle or is passed to your application from, say, the OnPaint event. To obtain a Graphics object in Managed C++, for example, you would write the following code:

HDC dc;

PAINTSTRUCT ps;

Graphics *pGraphics;

Dc=BeginPaint(hWnd,&ps) pGraphics=new Graphics(dc); // use the Graphics...

EndPaint(hWnd,&ps);

GDI+: The .NET Graphics Interface

333

CHAPTER 3.5

For the purposes of this chapter, we’ll assume that GDI+ operations will take place in the context of a Windows Forms application and that the Graphics object is handed to you in an event delegate. For example, we see the Graphics object that’s supplied in the PaintEventArgs in the following:

public void OnPaint(object sender, PaintEventArgs e)

{

// use e.Graphics.SomeMethod(...) here

Graphics Coordinates

Objects are painted onto the screen using coordinates that are mapped to no less than three systems. The World Coordinate system, which is an abstract concept of space within the graphics system, the Page Coordinate system, which is another abstract concept of physical dimension on a hypothetical page, and the Device Coordinate system, which is tied to the physical properties of the screen or printer upon which the graphics are rendered. To display anything onscreen, the graphical data that you write to the GDI+ graphics object has to be transformed several times. The reason for this is to allow you to deal with graphics in a device-independent way. For example, if you place a shape or some text in World Coordinates, you might want to ensure that the resulting graphic is displayed as though it were on a standard A4 sheet of paper. The image must look as if it’s on A4 both on the monitor and on any printer of any resolution. The World Coordinate is, therefore, mapped to a Page Coordinate that represents an 8 1/2” by 11” physical measurement. When the system comes to display the A4 page, the monitor might have a resolution of 72 dots per inch (DPI)—printer A has a resolution of 300 DPI and printer B has a resolution of 1200 by 400 DPI. Page space, a physical measurement, then needs to be mapped to Device Space so that, in reality, the monitor maps 8.5 inches across the page to 612 pixels on the monitor—2550 pixels on printer A and 10200 pixels on printer B.

GDI+ allows you to set the way that objects are transformed from the world to the page using the PageUnit, PageUnit, PageScale, and PageScale properties. You have no control over the transformation to device space. That all happens in the device drivers themselves. You can, however, read the device’s DPI with the DpiX and DpiY properties.

We’ll examine coordinate transformations in detail later in this chapter.

Drawing Lines and Simple Shapes

Drawing lines or the outline of a shape requires the use of a pen. Filling an area, particularly the interior of a shape, is accomplished with a brush. The simple Windows Forms example in Listing 3.5.1 shows these operations. This is a self-contained, hand-edited example, so Visual Studio.Net is not needed.

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET

Windows Forms

334

PART III

NOTE

A word about graphics object management under GDI+ for Windows Forms. The garbage collection heap, as you know by now, does memory management under

.NET for you. Technically, there is no need to worry about reclaiming your objects by deleting them because the garbage collector will do it for you eventually.

This is also true for graphical operations that create pens and brushes. However, an intense graphics routing could create many thousands of pens or brushes during each draw cycle and, in circumstances such as this, the garbage collector might not be quick enough to reclaim all the objects, causing a large number of dead items to be left on the heap for a considerable period of time.

To minimize the amount of work the garbage collector does, you should, wherever possible, explicitly invoke the Dispose() method on pens, brushes, and other such objects. This reclaims the memory in the object and tells the garbage collector not to bother with them.

In certain examples, you will see the declaration of the object inline, for example,

DrawRectangle(new Pen(Color.Red),.... This will not cause a memory leak of the pen, it simply defers reclamation of the object when it’s no longer in scope. In other examples, you will see explicit use of, for example, myPen.Dispose(). This is the recommended method for highest memory performance.

LISTING 3.5.1 DrawLines.cs: Drawing Lines and Filling Rectangles

1:using System;

2:using System.Drawing;

3:using System.Windows.Forms;

5:class drawlines : System.Windows.Forms.Form

6:{

7:Timer t;

8:bool BackgroundDirty;

10:public void TickEventHandler(object sender, EventArgs e)

11:{

12:Invalidate();

13:}

14:

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

16:{

17:// the current graphics object for

18:// this window is in the PaintEventArgs

19:

GDI+: The .NET Graphics Interface

CHAPTER 3.5

LISTING 3.5.1 Continued

20: Random r=new Random(); 21:

22:Color c=Color.FromArgb(r.Next(255),r.Next(255),r.Next(255));

23:Pen p=new Pen(c,(float)r.NextDouble()*10);

24:e.Graphics.DrawLine(p,r.Next(this.ClientSize.Width),

25:

r.Next(this.ClientSize.Height),

26:

r.Next(this.ClientSize.Width),

27:

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

28:p.Dispose();

29:}

30:

31:protected override void OnPaintBackground(PaintEventArgs e)

32:{

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

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

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

36:if(BackgroundDirty)

37:{

38:BackgroundDirty = false;

39:// We could call base.OnPaintBackground(e);

40:// but that doesn’t show off rectangle filling

41:e.Graphics.FillRectangle(new SolidBrush(this.BackColor),

42:

this.ClientRectangle);

43:

}

44:

 

45:

}

46:

 

47:public void OnSized(object sender, EventArgs e)

48:{

49:BackgroundDirty=true;

50:Invalidate();

51:}

52:

53:public drawlines()

54:{

55:t=new Timer();

56:t.Interval=300;

57:t.Tick+=new System.EventHandler(TickEventHandler);

58:t.Enabled=true;

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

60:this.SizeChanged+=new EventHandler(OnSized);

61:this.Text=”Lines and lines and lines”;

62:BackgroundDirty = true;

63:}

335

3.5

T GDI+:RAPHICSGNTERFACEI . HE NET