[ Team LiB ] |
13.1 Creating a Simple Windows FormA Windows Form is a tool for building a Windows application. The .NET Framework offers extensive support for Windows application development, the centerpiece of which is the Windows Forms framework. Not surprisingly, Windows Forms use the metaphor of a form. This idea was borrowed from the wildly successful Visual Basic (VB) environment and supports Rapid Application Development (RAD). Arguably, C# is the first development environment to marry the RAD tools of Visual Basic with the object-oriented and high-performance characteristics of a C-family language. 13.1.1 Using NotepadVisual Studio .NET provides a rich set of drag-and-drop tools for working with Windows Forms. It is possible to build a Windows application without using the Visual Studio Integrated Development Environment (IDE), but it is far more painful and takes a lot longer. However, just to prove the point, you'll use Notepad to create a simple Windows Form application that displays text in a window and implements a Cancel button. The application display is shown in Figure 13-1. Figure 13-1. The hand-drawn Windows FormYou start by adding a using statement for the Windows Forms namespace: using System.Windows.Forms; The key to creating a Windows Form application is to derive your form from System.Windows.Forms.Form: . public class HandDrawnClass : Form The Form object represents any window displayed in your application. You can use the Form class to create standard windows, as well as floating windows, tools, dialog boxes, and so forth. Microsoft apparently chose to call this a form rather than a window to emphasize that most windows now have an interactive component that includes controls for interacting with users. All the Windows widgets you'll need (labels, buttons, listboxes, etc.) are found within the Windows.Forms namespace. In the IDE, you'll be able to drag and drop these objects onto a designer, but for now you'll declare them right in your program code. To get started, declare the two widgets you need, a label to hold the Hello World text, and a button to exit the application: private System.Windows.Forms.Label lblOutput; private System.Windows.Forms.Button btnCancel; You're now ready to instantiate these objects, which takes place in the Form's constructor: this.lblOutput = new System.Windows.Forms.Label( ); this.btnCancel = new System.Windows.Forms.Button( ); Next you can set the Form's title text to Hello World: this.Text = "Hello World";
Set the label's location, text, and size: lblOutput.Location = new System.Drawing.Point (16, 24); lblOutput.Text = "Hello World!"; lblOutput.Size = new System.Drawing.Size (216, 24); The location is expressed as a System.Drawing.Point object, whose constructor takes a horizontal and vertical position. The size is set with a Size object, whose constructor takes a pair of integers that represent the width and height of the object.
Next, do the same for the button object, setting its location, size, and text: btnCancel.Location = new System.Drawing.Point (150,200); btnCancel.Size = new System.Drawing.Size (112, 32); btnCancel.Text = "&Cancel"; The button also needs an event handler. As described in Chapter 12, events (in this case the cancel button-click event) are implemented using delegates. The publishing class (Button) defines a delegate (System.EventHandler) that the subscribing class (your form) must implement. The delegated method can have any name but must return void and take two parameters, an object (sender) and a SystemEventArgs object (typically named e): protected void btnCancel_Click ( object sender, System.EventArgs e) { //... } Register your event-handler method in two steps. First, create a new System.EventHandler delegate, passing in the name of your method as a parameter: new System.EventHandler (this.btnCancel_Click); Then add that delegate to the button's click event-handler list with the += operator. The following line combines these steps into one: btnCancel.Click += new System.EventHandler (this.btnCancel_Click); Now you must set up the form's dimensions. The form property AutoScaleBaseSize sets the base size used at display time to compute the scaling factor for the form. The ClientSize property sets the size of the form's client area, which is the size of the form excluding borders and titlebar. (When you use the designer, these values are provided for you interactively.) this.AutoScaleBaseSize = new System.Drawing.Size (5, 13); this.ClientSize = new System.Drawing.Size (300, 300); Finally, remember to add the widgets to the form: this.Controls.Add (this.btnCancel); this.Controls.Add (this.lblOutput); Having registered the event handler, you must supply the implementation. For this example, clicking Cancel will exit the application, using the static method Exit( ) of the Application class: protected void btnCancel_Click ( object sender, System.EventArgs e) { Application.Exit ( ); } That's it; you just need an entry point to invoke the constructor on the form: public static void Main( ) { Application.Run(new HandDrawnClass( )); } The complete source is shown in Example 13-1. When you run this application, the window is opened and the text is displayed. Pressing Cancel closes the application. Example 13-1. Creating a hand-drawn Windows Formusing System; using System.Windows.Forms; namespace ProgCSharp { public class HandDrawnClass : Form { // a label to display Hello World private System.Windows.Forms.Label lblOutput; // a cancel button private System.Windows.Forms.Button btnCancel; public HandDrawnClass( ) { // create the objects this.lblOutput = new System.Windows.Forms.Label ( ); this.btnCancel = new System.Windows.Forms.Button ( ); // set the form's title this.Text = "Hello World"; // set up the output label lblOutput.Location = new System.Drawing.Point (16, 24); lblOutput.Text = "Hello World!"; lblOutput.Size = new System.Drawing.Size (216, 24); // set up the cancel button btnCancel.Location = new System.Drawing.Point (150,200); btnCancel.Size = new System.Drawing.Size (112, 32); btnCancel.Text = "&Cancel"; // set up the event handler btnCancel.Click += new System.EventHandler (this.btnCancel_Click); // Add the controls and set the client area this.AutoScaleBaseSize = new System.Drawing.Size (5, 13); this.ClientSize = new System.Drawing.Size (300, 300); this.Controls.Add (this.btnCancel); this.Controls.Add (this.lblOutput); } // handle the cancel event protected void btnCancel_Click ( object sender, System.EventArgs e) { Application.Exit( ); } // Run the app public static void Main( ) { Application.Run(new HandDrawnClass( )); } } } 13.1.2 Using the Visual Studio .NET DesignerAlthough hand coding is always great fun, it is also a lot of work, and the result in the previous example is not as elegant as most programmers would expect. The Visual Studio IDE provides a design tool for Windows Forms that is much easier to use. To begin work on a new Windows application, first open Visual Studio and choose New Project. In the New Project window, create a new C# Windows application, and name it ProgCSharpWindowsForm, as shown in Figure 13-2. Figure 13-2. Creating a Windows Form applicationVisual Studio responds by creating a Windows Form application and, best of all, putting you into a design environment, as shown in Figure 13-3. Figure 13-3. The design environmentThe Design window displays a blank Windows Form (Form1). A Toolbox window is also available, with a selection of Windows widgets and controls. If the Toolbox is not displayed, try clicking the word "Toolbox," or selecting View Toolbox on the Visual Studio menu. You can also use the keyboard shortcut Ctrl-Alt-X to display the Toolbox. With the Toolbox displayed, you can drag a label and a button directly onto the form, as shown in Figure 13-3. Figure 13-4. The Windows Form development environmentBefore proceeding, take a look around. The Toolbox is filled with controls that you can add to your Windows Form application. In the upper-right corner, you should see the Solution Explorer, a window that displays all the files in your projects. In the lower-right corner is the Properties window, which displays all the properties of the currently selected item. In Figure 13-4, the label (label1) is selected, and the Properties window displays its properties. You can use the Properties window to set the static properties of the various controls. For example, to add text to label1, you can type the words "Hello World" into the box to the right of its Text property. If you want to change the font for the lettering in the HelloWorld label, click the Font property shown in the lower-right corner of Figure 13-5. (You can provide text in the same way for your button—button1—by selecting it in the Property window and typing the word "Cancel" into its Text property.) Figure 13-5. Modifying the fontAny one of these steps is much easier than modifying these properties in code (though that is certainly still possible). Once you have the form laid out the way you want, all that remains is to create an event handler for the Cancel button. Double-clicking the Cancel button will create the event handler, register it, and put you on the code-behind page (the page that holds the source code for this form), in which you can enter the event-handling logic, as shown in Figure 13-6. Figure 13-6. After double-clicking the Cancel buttonThe cursor is already in place; you have only to enter the one line of code: Application.Exit( );
Visual Studio .NET generates all the code necessary to create and initialize the components. The complete source code is shown in Example 13-2, including the one line of code you provided (shown in bold in this example) to handle the Cancel button-click event. Example 13-2. Source code generated by the IDEusing System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; namespace ProgCSharpWindowsForm { /// <summary> /// Summary description for Form1. /// </summary> public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.Label lblOutput; private System.Windows.Forms.Button btnCancel; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public Form1( ) { // // Required for Windows Form Designer support // InitializeComponent( ); // // TODO: Add any constructor code // after InitializeComponent call // } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose( ); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent( ) { this.lblOutput = new System.Windows.Forms.Label( ); this.btnCancel = new System.Windows.Forms.Button( ); this.SuspendLayout( ); // // lblOutput // this.lblOutput.Font = new System.Drawing.Font("Arial", 15.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0))); this.lblOutput.Location = new System.Drawing.Point(24, 16); this.lblOutput.Name = "lblOutput"; this.lblOutput.Size = new System.Drawing.Size(136, 48); this.lblOutput.TabIndex = 0; this.lblOutput.Text = "Hello World"; // // btnCancel // this.btnCancel.Location = new System.Drawing.Point(192, 208); this.btnCancel.Name = "btnCancel"; this.btnCancel.TabIndex = 1; this.btnCancel.Text = "Cancel"; this.btnCancel.Click += new System.EventHandler( this.btnCancel_Click); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(292, 273); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.btnCancel, this.lblOutput}); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main( ) { Application.Run(new Form1( )); } private void btnCancel_Click(object sender, System.EventArgs e) { Application.Exit( ); } } }
There is quite a bit of code in this listing that didn't appear in Example 13-1, though most of it is not terribly important. When Visual Studio creates the application, it must add some boilerplate code that is not essential for this simple application. A careful examination reveals that the essentials are the same, but there are some key differences worth examining. The listing starts with special comment marks: /// <summary> /// Summary description for Form1. /// </summary> These marks are used for creating documentation; they are explained in detail later in this chapter. The form derives from System.Windows.Forms.Form, as did our earlier example. The widgets are defined as in the previous example: public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.Label lblOutput; private System.Windows.Forms.Button btnCancel; The designer creates a private container variable for its own use: private System.ComponentModel.Container components = null; In this and in every Windows Form application generated by Visual Studio .NET, the constructor calls a private method, InitializeComponent( ). This is used to define and set the properties of all the controls. The properties are set based on the values you've chosen (or on the default values you've left alone) in the designer. The InitializeComponent( ) method is marked with a comment that you should not modify the contents of this method: making changes to this method might confuse the designer. This program will behave exactly as your earlier handcrafted application did. |
[ Team LiB ] |