The .NET Framework allows you to create custom controls. These custom controls appear in the user’s Toolbox and can be added to Form
s, Panel
s or GroupBox
es in the same way that we add Button
s, Label
s 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 replacing it with one that provides 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
.
OnPaint
All controls have an OnPaint
method, which the system calls when a component must be redrawn (such as when the component is resized). The method receives a PaintEventArgs
object, which contains graphics information—property Graphics
is the graphics object used to draw, and property ClipRectangle
defines the rectangular boundary of the control. Whenever the system raises a Paint
event to draw the control on the screen, the control catches the event and calls its OnPaint
method. The base class’s OnPaint
should be called explicitly from an overridden OnPaint
implementation before executing 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.
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, but it does not determine how these constituent controls are displayed. To control the appearance of each constituent control, you can handle each control’s Paint
event or override OnPaint
. Both the Paint
event handler and OnPaint
are passed a PaintEventArgs
object, which can be used to draw graphics (lines, rectangles, and so on) 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’s 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 add code that draws custom graphics inside the overridden OnPaint
method. This technique allows for the greatest flexibility but also requires the most planning. All three approaches are summarized in Fig. 15.49.
Custom-control techniques and PaintEventArgs properties |
Description |
---|---|
Custom-Control Techniques | |
Inherit from a Windows Form s control |
You can do this to add functionality to a preexisting control. If you override method OnPaint , call the base class’s OnPaint method. You only can add to the original control’s appearance, not redesign it. |
Create a UserControl |
You can create a UserControl composed of multiple preexisting controls (e.g., to combine their functionality). You place drawing code in a Paint event handler or overridden OnPaint method. |
Inherit from class Control |
Define a brand new control. Override method OnPaint , then call base-class method OnPaint and add the code to draw the control. With this method you can customize both control appearance and functionality. |
PaintEventArgs Properties |
|
Graphics |
The control’s graphics object, which is used to draw on the control. |
ClipRectangle |
Specifies the rectangle indicating the boundary of the control. |
We create a “clock” control in Fig. 15.50. This is a UserControl
composed of a Label
and a Timer
—whenever the Timer
raises an event (once per second in this example), the Label
is updated to reflect the current time.
Timer
sTimer
s (System.Windows.Forms
namespace) are non-visual components that generate 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 app contains a user control (ClockUserControl
) and a Form
that displays the user control. Create a Windows app, then create a UserControl
class by selecting Project > Add User Control…. This displays a dialog from which we can select the type of item to add— user 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 app, you’re 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 Tick
event (lines 18–22; the default event). 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 returns the current time. Method ToLongTimeString
converts Now
to a string
containing the current hour, minute and second (along with AM or PM, depending on your locale). We use this to set the time in displayLabel
in line 21.
Once created, our clock control appears as an item in the ToolBox in the section titled ProjectName Components, where ProjectName is your project’s name. You may need to switch to the app’s Form
before the item appears in the ToolBox. To use the control, simply drag it to the Form
and run the Windows app. We gave the ClockUserControl
object a white background to make it stand out in the Form
. Figure. 15.50 shows the output of Clock
, which contains our ClockUserControl
. There are no event handlers in Clock
, so we show only the code for ClockUserControl
.
Visual Studio allows you to share custom controls with other developers. To create a User-Control
that can be exported to other solutions, do the following:
Create a new Class Library project.
Delete Class1.cs
, initially provided with the app.
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.
Inside the project, add controls and functionality to the UserControl
(Fig. 15.51).
Build the project. Visual Studio creates a .dll
file for the UserControl
in the output directory (bin/Debug
or bin/Release
). The file is not executable; class libraries are used to define classes that are reused in other executable apps. You can give the .dll
file to other developers and they can follow Steps 6 and 7.
Create a new Windows app.
In the new Windows app, 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 1–5. The item will then appear in the .NET Framework Components tab of the Choose Toolbox Items dialog. If it’s 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.