The aim of this chapter is to provide a brief introduction to Windows Forms and GDI+ graphics through a high-level overview of the relevant .NET libraries and a comparison with the Java classes that provide equivalent functionality. Anything more than an introduction is beyond the scope of this book; both the Windows Forms library and the GDI+ toolkit are sufficiently complex that full coverage would require a dedicated book.
The coverage presented in this chapter provides enough information to allow a Java developer experienced in the Swing/JFC, Java AWT, and Java 2D APIs to quickly use the comparable .NET libraries; the .NET documentation should be consulted for the details of the individual topics discussed.
The Windows Forms library is a toolkit for building UI applications for the Microsoft Windows operating system, equivalent in purpose to the Java AWT and Swing/JFC libraries.
While Swing and the AWT are intended for cross-platform development, Windows Forms are clearly rooted in the Windows operating system; there is no support for different platform appearances or behaviors.
The experienced Java programmer will have little problem adjusting to Windows Forms but will find the toolkit to be less flexible than Swing and the AWT. Forms provide fewer components, and it can be difficult to implement custom behavior using the provided classes.
The central class in the Forms library is System.Windows.Forms.Form. This class represents top-level application windows and is the starting point for a UI application.
Controls are added to a Form by creating the control instance and calling the Add method on the Form.Controls property. This property returns an instance of System.Windows.Forms.Control.ControlsCollection.
When a Form is no longer required, the Dispose method must be called; it’s important to ensure that the Dispose method is also called on any controls that the Form contains.
The System.ComponentModel.Container class can be used to track a group of controls, and calling the Dispose method on the Container class ensures that Dispose is also called on all of the controls that have been added to the container.
The following example demonstrates how to add a Button to a Form and how to ensure that controls are correctly disposed of; for more information on disposing of objects, see the Destructors section in Chapter 5. For an overview of controls included in the .NET Framework, see the Control Overview section later in this chapter.
using System.Drawing; using System.Windows.Forms; public class SimpleForm : Form { private System.ComponentModel.Container o_components = null; public SimpleForm() { o_components = new System.ComponentModel.Container(); Button x_button = new Button(); x_button.Text = "My Button"; Controls.Add(x_button); o_components.Add(x_button); } protected override void Dispose(bool p_disposing) { if(p_disposing) { if (o_components != null) { o_components.Dispose(); } } base.Dispose(p_disposing); } }
Windows Forms applications are started by calling the static Run method of the System.Windows.Forms.Application class, normally from the application Main method. The following fragment demonstrates how to run an instance of the SimpleForm class created earlier:
static void Main() { Application.Run(new SimpleForm()); }
A Forms application can be terminated either by calling the Application.Exit method or when the user clicks on the Close icon at the top of a form window.
Compiling a Forms application using the command-line compiler is similar to compiling any other C# application. However, you should use the /target:winexe flag to specify that the output is a UI application. Applications built with the /target:exe flag will still work but will cause a command prompt to be displayed to the user alongside the main window. The following statement demonstrates how to compile the SimpleForm.cs file:
csc /target:winexe /out:MyApp.exe SimpleForm.cs
For more information about compiling C# classes, see Chapter 3.
Table 18-1 describes the Windows Forms controls that are included in the .NET Framework. These classes are found in the System.Windows.Forms namespace. Consult the .NET documentation for more information about the controls. This table demonstrates the lack of explicit implementation classes in Java when directly compared with the Windows Forms library.
Table 18-1. A Comparison Between Windows Forms and Swing Controls
Swing | Description | |
---|---|---|
Containers | ||
TabControl | JTabbedPane | A tabbed pane, used to group controls on separate pages. |
GroupBox | JPanel | A labeled panel, typically used for a related group of controls, such as radio buttons; the equivalent can be achieved in Java using a JPanel and the TitledBorder class. |
Panel | JPanel | An unlabeled panel used to group controls. |
Button Controls | ||
Button | JButton | A standard button control, which can display an image and/or a text string. |
LinkLabel | JButton | A button that can display a URL. |
NotifyIcon | N/A | Displays an icon in the Windows Task Tray, typically used to represent an application running in the background. |
Toolbar | JToolBar | A collection of buttons grouped together, typically used to present the user with commonly used commands. |
Menu Controls | ||
MainMenu | JMenuBar | The menu for a Windows Form. |
MenuItem | JMenuItem | An individual element of a MainMenu. |
ContextMenu | JPopupMenu | A menu that appears when the user clicks on a control with the right mouse button. |
Value Controls | ||
CheckBox | JCheckBox | Displays a text label and a check box to allow the user to select a property. |
CheckedListBox | N/A | Displays a scrollable list of items, each with a check box. |
RadioButton | JRadioButton | Displays a button that can be turned on or off; typically used in groups to allow mutually exclusive options to be selected. |
Trackbar | JSlider | Allows a value to be selected by dragging a thumb along a scale. |
List Controls | ||
ComboBox | JComboBox | Displays a drop-down list of items. |
DomainUpDown | JSpinner | Displays a list of text items that the user can scroll through using an up and a down button. |
JList | Displays a list of text or image items. | |
ListView | JTable | Displays items in one of four different views; the report view can be used as a table. |
NumericUpDown | JSpinner | Displays a list of numeric values that the user can scroll though using an up and a down button. |
TreeView | JTree | Displays a hierarchical set of nodes, displayed in a tree format. |
Text Editing Controls | ||
TextBox | JTextArea | Displays text, which can be edited either by the user or programmatically. |
RichTextBox | JTextPane JEditorPane | Displays formatted text, using the Rich Text Format (RTF). |
Text Display Controls | ||
Label | JLabel | Displays a line of text that cannot be edited by the user. |
StatusBar | JProgressBar | Displays status information about the application to the user; typically docked at the bottom of a form. |
Dialog Box Controls | ||
ColorDialog | JColorChooser | Displays a color picker. |
FontDialog | N/A | Displays a font picker. |
OpenFileDialog | JFileChooser | Displays a dialog that allows a user to specify a file to be opened. |
SaveFileDialog | JFileChooser | Displays a dialog that allows a user to specify a location to save a file. |
PrintDialog | N/A | Displays a dialog that allows a user to select and configure a printer. |
Date Controls | ||
DateTimePicker | N/A | Displays a calendar that allows a user to select a date or a time. |
MonthCalendar | N/A | Displays a calendar that allows a user to select a range of dates. |
Other Controls | ||
VScrollBar HScrollBar | JScrollBar | Vertical and horizontal scroll bars. |
PictureBox | ImageIcon | Displays bitmaps and icons in a frame. |
The Windows Form library doesn’t provide the same layout flexibility as Swing or the AWT; the location of controls must be specified relative to their containers, as shown in the following example:
using System.Drawing; using System.Windows.Forms; public class LayoutDemo : Form { public LayoutDemo() { Button x_button = new Button(); x_button.Text = "My Button"; x_button.Location = new Point(20, 20); Controls.Add(x_button); } // Other methods, such as Dispose, would go here. static void Main() { Application.Run(new LayoutDemo()); } }
The position of the button in the form is specified using the Location property; this value defaults to the upper left corner of the container. No equivalent of the Java layout manager system exists in the Windows Forms library. This means that controls will overlap unless their locations are explicitly specified.
When a control is anchored to the edge of a container, the distance between the edge of the control and the edge of the container remains constant when the container is resized. A control can be anchored to any combination of edges, which causes the control to be resized as needed to maintain the distance between edges.
The following code demonstrates anchoring a button to the left and right edges of the form; the button will be resized as the form is resized to ensure that the distance from the edge of the button to the edge of the form remains constant:
using System.Drawing;
using System.Windows.Forms;
public class LayoutDemo : Form {
public LayoutDemo() {
Button x_button = new Button();
x_button.Text = "My Button";
x_button.Location = new Point(20, 20);
x_button.Anchor = AnchorStyles.Left | AnchorStyles.Right;
Controls.Add(x_button);
}
// Other methods, such as Dispose, would go here.
static void Main() {
Application.Run(new LayoutDemo());
}
}
The Anchor property is used to specify a value from the AnchorStyles enumeration; values can be combined using a bit mask, as shown in the statement marked in boldface. Table 18-2 shows the values in the AnchorStyle enumeration.
Table 18-2. The AnchorStyle Enumeration
Value | Description |
---|---|
Top | The control is anchored to the top edge of its container. |
Bottom | The control is anchored to the bottom edge of its container. |
Left | The control is anchored to the left edge of its container. |
Right | The control is anchored to the right edge of its container. |
None | The control is not anchored to any edge of its container. |
When a control is docked to an edge of its container, it remains in contact with that edge when the container is resized; the control will be resized to ensure that it is the same size as the docked edge. Docking is specified using the Dock property, as shown in the following example, which docks a button to the left edge of a form; the button will be resized to be completely in contact with the left edge of the form at all times, so it will be resized horizontally to follow the size of the form:
using System.Drawing; using System.Windows.Forms; public class LayoutDemo : Form { public LayoutDemo() { Button x_button = new Button(); x_button.Text = "My Button"; x_button.Location = new Point(20, 20); x_button.Dock = DockStyle.Left; Controls.Add(x_button); } // Other methods, such as Dispose, would go here. static void Main() { Application.Run(new LayoutDemo()); } }
The Dock property accepts a value from the DockStyle enumeration; Table 18-3 describes the values in this enumeration.
Table 18-3. The DockStyle Enumeration
Value | Description |
---|---|
Top | The top edge of the control is docked to the top of the container. |
Bottom | The bottom edge of the control is docked to the bottom of the container. |
Left | The left edge of the control is docked to the left edge of the container. |
Right | The right edge of the control is docked to the right edge of the container. |
Fill | All of the control edges are docked to all of the container edges. |
None | No control edges are docked. |
Windows Forms controls define events that can be used to monitor instances for state changes and interaction with users. For general information on events, see Chapter 5.
The following example demonstrates how to handle an event from a Button; for details of the events supported by each control, consult the .NET documentation.
using System.Drawing; using System.Windows.Forms; public class EventDemo : Form { Button o_button; public EventDemo() { o_button = new Button(); o_button.Text = "Press Me"; o_button.Click += new System.EventHandler(processButtonEvent); Controls.Add(o_button); } private void processButtonEvent(object p_source, System.EventArgs p_event) { o_button.Text = "Press Again"; } // Other methods, such as Dispose, would go here. static void Main() { Application.Run(new EventDemo()); } }
When the button is pressed, the processButtonEvent method is called, and the button’s text is changed appropriately.