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

Windows Forms

216

PART III

In this chapter, we will be showing you a good selection of the standard controls available, how to place and use them, how to add handlers for some of the more useful events, and how to create an application with some nice user interface features.

Windows Forms has a lot of standard user interface components that can be used in your applications. As you might expect, many of them are far more advanced through evolution than their Win32 counterparts. There are dialogs, list boxes, tree controls, panels, labels, toolbars, and many more. There is a large selection of common dialog controls including file selection, color picker, font style, and print dialogs. After a menu format, the dialog box is probably the most widely employed user interface item. Let’s examine them more closely now.

Dialogs

Dialogs come in two styles. The modal style requires that the user complete the actions on the dialog before returning to the normal flow of the application. Modeless, which is a simple fixed size window that can be used to perform some action, but leaves the user free to work on the main application too.

NOTE

Dialogs are best when they are simple. The design of a dialog is crucial to the usability of the application. Too many small dialogs can be annoying, especially if there is no choice of seeing them or not. Large dialogs, especially modal ones, are annoying because they require a lot of interaction that can break the flow of the application.

Dialogs under MFC were the usual odd mixture of Win32 API and object-oriented wrapper code, particularly in the Dialog Data eXchange or DDX system. This represented data in the dialog as data members of the dialog class, but used these members as a staging area for the real information that is edited or selected by the Windows controls on the dialog surface. This meant that there was no instant update mechanism for dialogs because data needed to be transferred to and from the dialog’s child windows by the use of Windows messages. Dialogs under Windows Forms are different. They are, like the applications that host them, fully objectoriented components that work in a more logical manner.

Under .NET, dialogs are essentially Windows Forms. Controls are placed on them in the same way that you would build a form application—with a tool or by coding directly.

Using the Common Dialogs

Common dialogs are simple to use and provide a consistent interaction with the underlying operating system. Dialogs are displayed with the ShowDialog function. All common dialogs are

User Interface Components

217

CHAPTER 3.2

derived from the System.Windows.Forms.CommonDialog class. You can use this as a base class for custom dialogs that you might create.

The FileDialog Family

The most used of the common dialogs must be the file dialogs. Windows Forms defines a fileopen and file-save dialog. To use these in your application, you need to put a member of type OpenFileDialog or SaveFileDialog in your application. Incidentally, both these dialogs are derived from System.Windows.Forms.FileDialog.

Listing 3.2.1 shows a simple application with a file-open dialog.

LISTING 3.2.1 fileopen.cs:OpenFileDialog in Action

1:using System;

2:using System.Drawing;

3:using System.ComponentModel;

4:using System.Windows.Forms;

7:namespace Sams

8:{

10:class fileopenapp : System.Windows.Forms.Form

11:{

12:

13:MainMenu m_menu;

14:MenuItem m_filemenu;

16:void OnOpenFile(Object sender, EventArgs e)

17:{

18:OpenFileDialog dlg=new OpenFileDialog();

20:if(dlg.ShowDialog() == DialogResult.OK)

21:{

22:MessageBox.Show(“You selected the file “+dlg.FileName);

23:}

24:}

25:

26:void OnExit(Object sender, EventArgs e)

27:{

28:Application.Exit();

29:}

30:

31:fileopenapp()

32:{

3.2

NTERFACEI SERU

OMPONENTSC

Windows Forms

218

PART III

LISTING 3.2.1 Continued

33:m_menu = new MainMenu();

34:m_filemenu=new MenuItem(“&File”);

35:m_menu.MenuItems.Add(m_filemenu);

36:MenuItem t;

37:

38:t=new MenuItem(“&Open”);

39:t.Click += new EventHandler(OnOpenFile);

40:m_filemenu.MenuItems.Add(t);

41:

42:t=new MenuItem(“-”);

43:m_filemenu.MenuItems.Add(t);

45:t=new MenuItem(“E&xit”);

46:t.Click += new EventHandler(OnExit);

47:m_filemenu.MenuItems.Add(t);

48:

49:this.Menu = m_menu;

50:}

51:

52:public static void Main()

53:{

54:Application.Run(new fileopenapp());

55:}

56:}

57:

58: }// end of Sams namespace

This example is the very simplest use of the dialog. Common dialogs provide much more functionality and are used in more complex ways.

A common dialog control is used differently when the application is constructed by Visual Studio.NET for example. In this instance, the application will instantiate a copy of the dialog when the application is run and attach an event source called FileOK to a button click handler in the form that uses the dialog. The delegate for this event handler is a little different from that of menu events. The signature for the CancelEventHandler is as follows:

void FN(object sender, System.ComponentModel.CancelEventArgs e)

Listing 3.2.2 shows the equivalent to this approach in a hand-built form.

LISTING 3.2.2 fileopenevent.cs: Event-driven Common Dialog Response

1:using System;

2:using System.Drawing;

LISTING 3.2.2 Continued

3:using System.ComponentModel;

4:using System.Windows.Forms;

5:using System.IO;

6:

7:

8:namespace Sams

9:{

10:

11:class fileopenapp : System.Windows.Forms.Form

12:{

13:

14:MainMenu m_menu;

15:MenuItem m_filemenu;

17: OpenFileDialog openfiledlg1; 18:

19:void OnOpenFile(Object sender, EventArgs e)

20:{

21:openfiledlg1.Filter = “C# files (*.cs)|”+

22:“*.cs|Bitmap files (*.bmp)|*.bmp”;

23:openfiledlg1.FilterIndex = 1;

24:openfiledlg1.ShowDialog();

25:}

26:

27:void OnExit(Object sender, EventArgs e)

28:{

29:Dispose();

30:}

31:

32:fileopenapp()

33:{

34:m_menu = new MainMenu();

35:m_filemenu=new MenuItem(“&File”);

36:m_menu.MenuItems.Add(m_filemenu);

37:MenuItem t;

38:

39:t=new MenuItem(“&Open”);

40:t.Click += new EventHandler(OnOpenFile);

41:m_filemenu.MenuItems.Add(t);

42:

43:t=new MenuItem(“-”);

44:m_filemenu.MenuItems.Add(t);

46:t=new MenuItem(“E&xit”);

User Interface Components

219

CHAPTER 3.2

3.2

NTERFACEI SERU

OMPONENTSC

Windows Forms

220

PART III

LISTING 3.2.2 Continued

47:t.Click += new EventHandler(OnExit);

48:m_filemenu.MenuItems.Add(t);

49:

50: this.Menu = m_menu; 51:

52:openfiledlg1 = new OpenFileDialog();

53:openfiledlg1.FileOk += new CancelEventHandler(OnFileOpenOK);

54:}

55:

56:void OnFileOpenOK(Object sender, CancelEventArgs e)

57:{

58://MessageBox.Show(“You selected the file “+openfiledlg1.FileName);

59:// remember to add “using System.IO;” to the top of this file.

60:OpenFileDialog dlg = (OpenFileDialog)sender;

61:

62:Stream FileStream;

63:if((FileStream = dlg.OpenFile())!=null)

64:{

65://perform the read from FileStream here...

66:FileStream.Close(); //and tidy up...

67:}

68:}

69:

70:public static void Main()

71:{

72:Application.Run(new fileopenapp());

73:}

74:}

75:

76: }// end of Sams namespace

The event in Listing 3.2.2 will only fire if the OK button has been clicked. There is also a HelpRequested event that will fire if the Help button in the dialog is chosen.

A file dialog can be made to present only a particular set of files by specifying a filter or even to open a file and return a file-stream for you. Lines 19–25 of the listing show how a filter is set for a particular selection of file types.

Lines 56–68 define the event handler that is triggered when a file is selected and opened using the dialog box.

Figure 3.2.1 shows a screen shot of FileOpenDialog as defined by this code.

User Interface Components

CHAPTER 3.2

FIGURE 3.2.1

The FileOpenDialog showing file filtering.

SaveFileDialog works in a similar manner because it inherits most of its functionality from FileDialog. If you use the OpenFile function, a chosen file will be created or opened for writing.

NOTE

Note that FileDialog, OpenFileDialog, and SaveFileDialogs support properties that allow you to change the way files are displayed, checked, or selected. The .NET SDK help files should be consulted for details

The ColorDialog

Selecting color is a common function. Many people try to write color pickers themselves for reasons of aesthetics, but the Windows ColorDialog is simple to use and effective. What’s more, it’s consistent and familiar to most users.

Invoking ColorDialog is the same as other common dialogs by virtue of its base class. Create an instance of the class and call the ShowDialog method.

Figure 3.2.2 shows the ColorDialog in its various modes.

The ColorDialog class returns color information in the form of a Color object. This contains the alpha, or transparency, and the red, green, and blue values of the color. There are also methods for ascertaining a color’s hue, brightness, and saturation values.

221

3.2

NTERFACEI SERU

OMPONENTSC

Windows Forms

222

PART III

FIGURE 3.2.2

The ColorDialog in all its glory.

There is a property called AllowFullOpen in the ColorDialog that allows you to decide if the Define Custom Colors button is enabled. You can also use the FullOpen property to force the complex color picker to appear. The CustomColors property is an array of color values that can be set or interrogated and that fill the custom color boxes on the control.

Listing 3.2.3 shows the ColorDialog in a selection of modes.

LISTING 3.2.3 colordlgs.cs: Various Incarnations of the ColorDialog

1:using System;

2:using System.Drawing;

3:using System.ComponentModel;

4:using System.Windows.Forms;

7:namespace Sams {

10:class ColorStretcher : System.Windows.Forms.Form

11:{

12:

13:void OnFull(Object sender, EventArgs e)

14:{

15:ColorDialog dlg=new ColorDialog();

16:dlg.FullOpen = true;

17:

18:dlg.ShowDialog();

19:}

20:

21: void OnNoCustom(Object sender, EventArgs e)

User Interface Components

CHAPTER 3.2

LISTING 3.2.3 Continued

22:{

23:ColorDialog dlg=new ColorDialog();

24:dlg.AllowFullOpen = false;

25:

26:dlg.ShowDialog();

27:}

28:

29:void OnNormal(Object sender, EventArgs e)

30:{

31:ColorDialog dlg=new ColorDialog();

32:dlg.Color = Color.PaleGoldenrod;

33:dlg.ShowDialog();

34:}

35:

36:void OnWithColours(Object sender, EventArgs e)

37:{

38:ColorDialog dlg=new ColorDialog();

39:dlg.FullOpen = true;

40:// this statement defines the first five of the

41:// custom color settings as ints the data is

42:// 0xAARRGGBB where AA is alpha, RR is red,

43:// GG is green and BB is blue expressed as the

44:// hexadecimal byte equivalent

45:dlg.CustomColors = new int[5]{0x00ff8040, 0x00c256fe,

46:

0x00aa2005, 0x0004f002, 0x002194b5};

47:

 

48:dlg.ShowDialog();

49:}

50:

51:ColorStretcher()

52:{

53:// first a menu for the choices

55:MainMenu m=new MainMenu();

56:MenuItem top,temp;

57:

58:top=new MenuItem(“ColorDialog”);

59:m.MenuItems.Add(top);

60:

61:temp=new MenuItem(“Full”);

62:temp.Click+=new EventHandler(OnFull);

63:top.MenuItems.Add(temp);

64:

65: temp=new MenuItem(“No custom”);

223

3.2

NTERFACEI SERU

OMPONENTSC

Windows Forms

224

PART III

LISTING 3.2.3 Continued

66:temp.Click+=new EventHandler(OnNoCustom);

67:top.MenuItems.Add(temp);

68:

69:temp=new MenuItem(“With Colours”);

70:temp.Click+=new EventHandler(OnWithColours);

71:top.MenuItems.Add(temp);

72:

73:temp=new MenuItem(“Normal”);

74:temp.Click+=new EventHandler(OnNormal);

75:top.MenuItems.Add(temp);

76:

77: this.Menu = m; 78:

79: } 80:

81:public static void Main()

82:{

83:Application.Run(new ColorStretcher());

84:}

85:

86:}

87:}

Notice how the custom colors are defined as integer values in the OnWithColours event handler (lines 36–49).

To get the chosen color from the ColorDialog, simply read the contents of the Color property. Setting this property before invoking the ShowDialog method will pre-select a color. This is useful for changing colors that are already set in an application. This is shown in the OnNormal handler. To see the color selection, you must click the Define Custom Colors button. The color selected in the palette is the one that is programmed.

FontDialog

The font you choose for text is very important. Times Roman conveys a sense of solidity and reliability. Tahoma shows technical competence, Shotgun proves that you spent too much of your youth before 1975, and nothing says “I love you” better than 72-point Gigi.

The plethora of fonts available to the modern wordsmith is truly phenomenal, so there is nothing more important than a quick, simple method for choosing the face, size, and weight of a font. The standard font dialog is available to .Net programmers through the FontDialog class which, like its FileDialog and ColorDialog cousins, is derived from the CommonDialog class.

The technique for invoking the font dialog is the same as we have seen before. The properties of the dialog and the return data is uniquely dedicated to type face selection.

User Interface Components

225

CHAPTER 3.2

Listing 3.2.4 shows a simple application with a label and a font selection button. The button is wired to an event that invokes the font dialog. The font dialog itself has many options, set through its properties, that allow you to select the operations the dialog can perform. In the following example, we have enabled the Apply button and attached an event that updates the label text each time the Apply button is clicked.

LISTING 3.2.4 fontdlg.cs: Using the Font Selection Dialog

using System;

using System.ComponentModel; using System.Drawing;

using System.Windows.Forms;

namespace Sams {

class FontPicker : System.Windows.Forms.Form

{

Button b;

Label l;

void OnApply(Object sender,System.EventArgs e)

{

FontDialog dlg = (FontDialog)sender; l.Font=dlg.Font;

}

void OnClickedb(Object sender,EventArgs e)

{

// Create a new Font Dialog FontDialog dlg=new FontDialog();

//Initialize it with the existing font in the label dlg.Font = l.Font;

//Set the property to allow an “Apply button on the form” dlg.ShowApply = true;

//attach an OnApply event handler dlg.Apply += new EventHandler(OnApply);

if(dlg.ShowDialog() != DialogResult.Cancel)

{

l.Font = dlg.Font;

}

}

3.2

NTERFACEI SERU

OMPONENTSC

Windows Forms

226

PART III

LISTING 3.2.4 Continued

public FontPicker()

{

this.Size=new Size(416,320);

l=new Label();

l.Location = new Point(8,8); l.Size = new Size(400,200);

l.Text = “0 1 2 3 4 5 6 7 8 9 \nabcdefghijklmnopqrstuvwxyz”+ “\nABCDEFGHIJKLMNOPQRSTUVWXYZ”;

l.Font = new Font(“Microsoft Sans Serif”, 18f); this.Controls.Add(l);

b=new Button();

b.Text = “Choose Font”;

b.Click += new EventHandler(OnClickedb); b.Location = new Point(8,250);

b.Size = new Size(400,32); this.Controls.Add(b);

}

static void Main()

{

Application.Run(new FontPicker());

}

}

}

Build this file with the command line:

csc /t:winexe fontdlg.cs

The Print and Print Preview Dialogs

Rendering a document onscreen or to the printer requires graphics knowledge that we will cover more in depth later in this book, so we wont go into great detail on that subject at this stage. Just to give you a feel for print and print preview. In Listing 3.2.5 we have created a very simple application that enables you to perform print and print preview.

User Interface Components

CHAPTER 3.2

LISTING 3.2.5 printpreview.cs Printing and Print Preview in Action

Totally re-written… 1: namespace Sams

2:{

3:using System;

4:using System.Drawing;

5:using System.Drawing.Printing;

6:using System.Collections;

7:using System.ComponentModel;

8:using System.Windows.Forms;

9:

10:

11:/// <summary>

12:///the ppView is a simple control window that uses a common draw

13:///method for both painting on screen and printing or print preview

14:/// </summary>

15:public class ppView : System.Windows.Forms.Panel

16:{

17:private ArrayList points;

18:

19: Point mousePoint; 20:

21:

22:void OnClick(Object sender, MouseEventArgs e)

23:{

24:if(points == null)

25:{

26:points=new ArrayList();

27:}

28:

29:points.Add(mousePoint);

30:Invalidate();

31:}

32:

33:void OnMouseMove(Object sender,MouseEventArgs e)

34:{

35:mousePoint = new Point(e.X,e.Y);

36:}

37:

38:public ppView()

39:{

40:this.MouseDown+=new MouseEventHandler(OnClick);

41:this.MouseMove+=new MouseEventHandler(OnMouseMove);

227

3.2

NTERFACEI SERU

OMPONENTSC

Windows Forms

228

PART III

LISTING 3.2.5 Continued

42:this.BackColor=Color.White;

43:}

44:

45:private void DrawSmiley(Point pt, Graphics g)

46:{

47:g.FillEllipse(Brushes.Black,pt.X-52,pt.Y-52,104,104);

48:g.FillEllipse(Brushes.Yellow,pt.X-50,pt.Y-50,100,100);

49:g.FillEllipse(Brushes.Black,pt.X-30,pt.Y-10,60,40);

50:g.FillEllipse(Brushes.Yellow,pt.X-35,pt.Y-10,70,35);

51:g.FillEllipse(Brushes.Black,pt.X-25,pt.Y-15,10,10);

52:g.FillEllipse(Brushes.Black,pt.X+10,pt.Y-15,10,10);

53:}

54:

55:private void DoDraw(Graphics g)

56:{

57:if(points == null)

58:{

59:return;

60:}

61:foreach(Point p in points)

62:{

63:DrawSmiley(p,g);

64:}

65:}

66:

67:protected override void OnPaint(PaintEventArgs e)

68:{

69:if(points == null)

70:{

71:return;

72:}

73:DoDraw(e.Graphics);

74:}

75:

76:public void OnPrintPage(Object sender,PrintPageEventArgs e)

77:{

78:if(points == null)

79:{

80:return;

81:}

82:DoDraw(e.Graphics);

83:}

84:}

85:

86:

User Interface Components

CHAPTER 3.2

LISTING 3.2.5 Continued

87:/// <summary>

88:/// This is the application that hosts the MainApps.

89:/// </summary>

90:public class MDIChildForm : System.Windows.Forms.Form

91:{

92:/// <summary>

93:/// Required designer variable.

94:/// </summary>

95:private System.ComponentModel.Container components;

96:private ppView vw;

97:

98:// Accessor for private data

99:public ppView View {

100:get

101:{

102:return vw;

103:}

104:}

105:

106:public MDIChildForm()

107:{

108:

109:

110://

111:// Required for Windows Form Designer support

112://

113:InitializeComponent();

114:

115:vw=new ppView();

116:vw.Location = new Point(3,3);

117:vw.Size = new Size(this.Size.Width-6,this.Size.Height-6);

118:vw.Anchor=AnchorStyles.Left|

119:AnchorStyles.Top|

120:AnchorStyles.Right|

121:AnchorStyles.Bottom;

122:

123: this.Controls.Add(vw); 124:

125://

126:// TODO: Add any constructor code after InitializeComponent call

127://

128:}

129:

130:/// <summary>

131:/// Clean up any resources being used.

229

3.2

NTERFACEI SERU

OMPONENTSC

Windows Forms

230

PART III

LISTING 3.2.5 Continued

132:/// </summary>

133:public override void Dispose()

134:{

135:base.Dispose();

136:components.Dispose();

137:}

138:

139:/// <summary>

140:/// Required method for Designer support - do not modify

141:/// the contents of this method with the code editor.

142:/// </summary>

143:private void InitializeComponent()

144:{

145:this.components = new System.ComponentModel.Container ();

146:this.Text = “MDIChildForm”;

147:this.AutoScaleBaseSize = new System.Drawing.Size (5, 13);

148:this.ClientSize = new System.Drawing.Size (328, 277);

149:}

150:}

151:

152:/// <summary>

153:/// Summary description for MainApp.

154:/// </summary>

155:public class MainApp : System.Windows.Forms.Form

156:{

157:/// <summary>

158:/// Required designer variable.

159:/// </summary>

160:private System.ComponentModel.Container components;

161:private System.Windows.Forms.MenuItem FileExit;

162:private System.Windows.Forms.MenuItem FilePrintPreview;

163:private System.Windows.Forms.MenuItem FilePrint;

164:private System.Windows.Forms.MenuItem FileNew;

165:private System.Windows.Forms.MenuItem menuItem1;

166:private System.Windows.Forms.MainMenu mainMenu1;

167:

168:public MainApp()

169:{

170://

171:// Required for Windows Form Designer support

172://

173:InitializeComponent();

174:

175://

User Interface Components

CHAPTER 3.2

LISTING 3.2.5 Continued

176:// Add any constructor code after InitializeComponent call

177://

178:}

179:

180:/// <summary>

181:/// Clean up any resources being used.

182:/// </summary>

183:public override void Dispose()

184:{

185:base.Dispose();

186:components.Dispose();

187:}

188:

189:/// <summary>

190:/// Required method for Designer support - do not modify

191:/// the contents of this method with the code editor.

192:/// </summary>

193:private void InitializeComponent()

194:{

195:this.components = new System.ComponentModel.Container ();

196:this.mainMenu1 = new System.Windows.Forms.MainMenu ();

197:this.FilePrintPreview = new System.Windows.Forms.MenuItem ();

198:this.FileExit = new System.Windows.Forms.MenuItem ();

199:this.menuItem1 = new System.Windows.Forms.MenuItem ();

200:this.FileNew = new System.Windows.Forms.MenuItem ();

201:this.FilePrint = new System.Windows.Forms.MenuItem ();

202:mainMenu1.MenuItems.AddRange(

203:new System.Windows.Forms.MenuItem[1] {this.menuItem1});

204:FilePrintPreview.Text = “P&review...”;

205:FilePrintPreview.Index = 2;

206:FilePrintPreview.Click +=

207:new System.EventHandler (this.FilePrintPreview_Click);

208:FileExit.Text = “&Exit”;

209:FileExit.Index = 3;

210:FileExit.Click += new System.EventHandler (this.FileExit_Click);

211:menuItem1.Text = “&File”;

212:menuItem1.Index = 0;

213:menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[4]

214: {this.FileNew,

215:this.FilePrint,

216:this.FilePrintPreview,

217:this.FileExit});

218:FileNew.Text = “&New”;

219:FileNew.Index = 0;

231

3.2

NTERFACEI SERU

OMPONENTSC

Windows Forms

232

PART III

LISTING 3.2.5 Continued

220:FileNew.Click += new System.EventHandler (this.FileNew_Click);

221:FilePrint.Text = “&Print...”;

222:FilePrint.Index = 1;

223:FilePrint.Click += new System.EventHandler (this.FilePrint_Click);

224:this.Text = “MainApp”;

225:this.AutoScaleBaseSize = new System.Drawing.Size (5, 13);

226:this.IsMdiContainer = true;

227:this.Menu = this.mainMenu1;

228:this.ClientSize = new System.Drawing.Size (368, 289);

229:}

230:

231:protected void FileExit_Click (object sender, System.EventArgs e)

232:{

233:Application.Exit();

234:}

235:

236:protected void FilePrintPreview_Click(object sender,System.EventArgs e)

237:{

238:PrintPreviewDialog d=new PrintPreviewDialog();

239:PrintDocument doc = new PrintDocument();

240:

241:MDIChildForm f = (MDIChildForm)this.ActiveMdiChild;

242:ppView vw = f.View;

243:doc.PrintPage += new PrintPageEventHandler(vw.OnPrintPage);

245: d.Document=doc; 246:

247: d.ShowDialog(); 248:

249:doc.PrintPage -= new PrintPageEventHandler(vw.OnPrintPage);

250:}

251:

252:protected void FilePrint_Click (object sender, System.EventArgs e)

253:{

254:PrintDialog dlg = new PrintDialog();

255:PrintDocument doc = new PrintDocument();

256:

257:MDIChildForm f = (MDIChildForm)this.ActiveMdiChild;

258:ppView vw = f.View;

259:doc.PrintPage += new PrintPageEventHandler(vw.OnPrintPage);

261:dlg.Document=doc;

262:

User Interface Components

CHAPTER 3.2

LISTING 3.2.5 Continued

263: dlg.ShowDialog(); 264:

265: doc.PrintPage -= new PrintPageEventHandler(vw.OnPrintPage); 266:

267: } 268:

269:protected void FileNew_Click (object sender, System.EventArgs e)

270:{

271:MDIChildForm f = new MDIChildForm();

272:f.MdiParent=this;

273:f.Show();

274:}

275:

276:/// <summary>

277:/// The main entry point for the application.

278:/// </summary>

279:public static void Main(string[] args)

280:{

281:Application.Run(new MainApp());

282:}

283:}

284:}

This application has three components. The form, called MainApp, is a Multiple Document Interface (MDI) application and hosts a number of MDIChildForm objects. These, in turn, host a simple control called ppView.

The ppView does all the work of tracking the mouse, adding simple points to an array list, and drawing smiley faces at every stored point. It also employs the technique of a single, simple draw routine that takes a Graphics object as an argument.

The print and print preview mechanism uses a PrintDocument that fires an event for each printed page. To use the print preview and print facilities, the simple draw routine is used by the OnPaint, line 67, and the OnPrintPage, line 76, events that call the DoDraw method with whatever drawing device context they have been given by the screen or printer drivers. The Graphics context passed to the DoDraw routine when drawing onscreen is different than when printing. The drawing system knows that it needs to change scales and pixel resolution for you, depending on the device.

If you’re interested in the graphics used, lines 47–52 draw the smileys.

233

3.2

NTERFACEI SERU

OMPONENTSC