User-Defined Controls
The .NET Framework allows you to create custom controls. These custom controls appear in the user's Toolbox and can be added to Forms, Panels or GroupBoxes in the same way that we add Buttons, Labels and other predefined controls. The simplest way to create a custom control is to derive a class from an existing control, such as a Label. This is useful if you want to add functionality to an existing control, rather than having to reimplement the existing control to include the desired functionality. For example, you can create a new type of Label that behaves like a normal Label but has a different appearance. You accomplish this by inheriting from class Label and overriding method OnPaint.
All controls contain method OnPaint, which the system calls when a component must be redrawn (such as when the component is resized). Method OnPaint is passed a PaintEventArgs object, which contains graphics informationproperty Graphics is the graphics object used to draw, and property ClipRectangle defines the rectangular boundary of the control. Whenever the system raises the Paint event, our control's base class catches the event. Through polymorphism, our control's OnPaint method is called. Our base class's OnPaint implementation is not called, so we must call it explicitly from our OnPaint implementation before we execute our custom-paint code. In most cases, you want to do this to ensure that the original painting code executes in addition to the code you define in the custom control's class. Alternately, if we do not wish to let the base class OnPaint method execute, we do not call it.
To create a new control composed of existing controls, use class UserControl. Controls added to a custom control are called constituent controls. For example, a programmer could create a UserControl composed of a Button, a Label and a TextBox, each associated with some functionality (for example, the Button setting the Label's text to that contained in the TextBox). The UserControl acts as a container for the controls added to it. The UserControl contains constituent controls, so it does not determine how these constituent controls are displayed. Method OnPaint of the UserControl cannot be overridden. To control the appearance of each constituent control, you must handle each control's Paint event. The Paint event handler is passed a PaintEventArgs object, which can be used to draw graphics (lines, rectangles, etc.) on the constituent controls.
Using another technique, a programmer can create a brand new control by inheriting from class Control. This class does not define any specific behavior; that task is left to you. Instead, class Control handles the items associated with all controls, such as events and sizing handles. Method OnPaint should contain a call to the base class's OnPaint method, which calls the Paint event handlers. You must then add code that draws custom graphics inside the overridden OnPaint method when drawing the control. This technique allows for the greatest flexibility, but also requires the most planning. All three approaches are summarized in Fig. 14.48.
Custom control techniques and PaintEventArgs properties |
Description |
---|---|
Custom Control Techniques |
|
Inherit from Windows Forms control |
You can do this to add functionality to a pre-existing control. If you override method OnPaint, call the base class's OnPaint method. Note that you only can add to the original control's appearance, not redesign it. |
Create a UserControl |
You can create a UserControl composed of multiple pre-existing controls (e.g., to combine their functionality). Note that you cannot override the OnPaint methods of custom controls. Instead, you must place drawing code in a Paint event handler. Again, note that you only can add to the original control's appearance, not redesign it |
Inherit from class Control |
Define a brand new control. Override method OnPaint, then call base class method OnPaint and include methods to draw the control. With this method you can customize control appearance and functionality. |
PaintEventArgs Properties |
|
Graphics |
The graphics object of the control. It is used to draw on the control. |
ClipRectangle |
Specifies the rectangle indicating the boundary of the control. |
We create a "clock" control in Fig. 14.49. This is a UserControl composed of a Label and a Timerwhenever the Timer raises an event, the Label is updated to reflect the current time.
Figure 14.49. UserControl-defined clock.
(This item is displayed on page 708 in the print version)
1 // Fig. 14.49: ClockUserControl.cs 2 // User-defined control with a timer and a Label. 3 using System; 4 using System.Windows.Forms; 5 6 // UserControl that displays the time on a Label 7 public partial class ClockUserControl : UserControl 8 { 9 // default constructor 10 public ClockUserControl() 11 { 12 InitializeComponent(); 13 } // end constructor 14 15 // update Label at every tick 16 private void clockTimer_Tick(object sender, EventArgs e) 17 { 18 // get current time (Now), convert to string 19 displayLabel.Text = DateTime.Now.ToLongTimeString(); 20 } // end method clockTimer_Tick 21 } // end class ClockUserControl |
Timers (System.Windows.Forms namespace) are invisible components that reside on a Form, generating Tick events at a set interval. This interval is set by the Timer's Interval property, which defines the number of milliseconds (thousandths of a second) between events. By default, timers are disabled and do not generate events.
This application contains a user control (ClockUserControl) and a Form that displays the user control. We begin by creating a Windows application. Next, we create a UserControl class for the project by selecting Project > Add User Control.... This displays a dialog from which we can select the type of control to adduser controls are already selected. We then name the file (and the class) ClockUserControl. Our empty ClockUserControl is displayed as a grey rectangle.
You can treat this control like a Windows Form, meaning that you can add controls using the ToolBox and set properties using the Properties window. However, instead of creating an application, you are simply creating a new control composed of other controls. Add a Label (displayLabel) and a Timer (clockTimer) to the UserControl. Set the Timer interval to 1000 milliseconds and set displayLabel's text with each event (lines 1620). To generate events, clockTimer must be enabled by setting property Enabled to true in the Properties window.
Structure DateTime (namespace System) contains property Now, which is the current time. Method ToLongTimeString converts Now to a string containing the current hour, minute and second (along with AM or PM). We use this to set the time in displayLabel in line 19.
Once created, our clock control appears as an item on the ToolBox. You may need to switch to the application's Form before the item appears in the ToolBox. To use the control, simply drag it to the Form and run the Windows application. We gave the ClockUserControl object a white background to make it stand out in the Form. Figure 14.49 shows the output of ClockForm, which contains our ClockUserControl. There are no event handlers in ClockForm, so we show only the code for ClockUserControl.
Visual Studio allows you to share custom controls with other developers. To create a UserControl that can be exported to other solutions, do the following:
1. |
Create a new Class Library project.
|
2. |
Delete Class1.cs, initially provided with the application.
|
3. |
Right click the project in the Solution Explorer and select Add > User Control.... In the dialog that appears, name the user control file and click Add.
|
4. |
Inside the project, add controls and functionality to the UserControl (Fig. 14.50).
Figure 14.50. Custom-control creation. |
5. |
Build the project. Visual Studio creates a .dll file for the UserControl in the output directory (bin/Release). The file is not executable; class libraries are used to define classes that are reused in other executable applications.
|
6. |
Create a new Windows application.
|
7. |
In the new Windows application, right click the ToolBox and select Choose Items.... In the Choose Toolbox Items dialog that appears, click Browse.... Browse for the .dll file from the class library created in Steps 15. The item will then appear in the Choose Toolbox Items dialog (Fig. 14.51). If it is not already checked, check this item. Click OK to add the item to the Toolbox. This control can now be added to the Form as if it were any other control (Fig. 14.52).
Figure 14.51. Custom control added to the ToolBox. (This item is displayed on page 710 in the print version) Figure 14.52. Custom control added to a Form. (This item is displayed on page 710 in the print version) |