|
Custom Controls - I
The C# Column - Yashawant Kanetkar
Prior
to .NET the controls that were popularly used as language-independent reusable
user-defined controls were ActiveX controls. These included controls like multimedia
controls, spreadsheet controls, mailing controls, etc. But they had their own
disadvantages. ActiveX controls were COM–based controls and COM had a steep
learning curve. In addition to this, there were overheads of maintaining the
registry, maintaining CLSIDs, handling interfaces and working through complex
threading models. .NET has solved all these problems by facilitating creation
of user-defined controls in a simple manner. In this article we will see how
to create such user-defined controls.
Custom controls v/s User controls
Normally when we develop a .NET Windows
application, we use controls from the System.Windows.Forms namespace.
We have a wide variety of controls available, from simple controls such as Label
and TextBox, to controls that are richer and more complex, such as MonthCalendar
and ColorDialog. While these controls are good enough for most Windows
applications we need to build, sometimes we need to create a different control
that we cannot find in the Framework class library.
We can create two types of controls—Custom
controls and User or Composite controls.
Custom controls display UI by making
calls to a Graphics object. Custom controls are typically derived from
the Control class. The Control class implements basic functionality
required by classes that display information to the user. It handles user inputs
through the keyboard. It handles message routing and security. There is limited
design-time support for creating custom controls.
User or Composite controls are composed
of other existing controls. User controls are derived from the UserControl
class. The UserControl class is also derived from the Control
class There is full design-time support for creating user controls with the
Visual Studio .NET Windows Forms Designer.
Creating a custom control
Let us create a Custom Control and use
it in a Windows Form project. The idea is to make an analog clock. Here we plan
to display time in a dial using the hour, minute and second hands. The control
(after dragging and dropping it in a form) is shown in the following figure.
To
create a custom control, select ‘Windows Control Library’ template. Name the
project as ClockCtrl.
By default a class called UserControl1
gets created, derived from the UserControl class. Change the base class
of the control class from UserControl to Control. Also change
the name of the control class from UserControl1 to Clock. Next,
set the Size property of the control to 120, 120 and BackColor
property to Light Blue.
To keep track of the time we must add
a Timer control. Do so and name it mytimer. Set the interval time
of the timer to 1000 milliseconds (equivalent to one second) and add a handler
mytimer_Tick( ) to handle the Tick event that would get generated
every second.
We will draw the hands and background
of the control in the mytimer_Tick( ) event handler because we need to
redraw the control every second. This is the reason why we did not do the painting
in the Paint event handler.
Let us now see what we have done for
drawing the control.
On occurrence of every tick we have
drawn the clock UI on a bitmap and displayed the bitmap on the control. To draw
on the bitmap we first need to obtain the graphics context of the bitmap. We
have done this in the constructor of the Clock class. To collect the
graphics context we have added a reference g of type Graphics
as a data member of the control. We have also added a reference mybmp
of type Bitmap to this class. Let us now take a look at the constructor.
public Clock( )
{
InitializeComponent( ) ;
Size sz = this.Size ;
mybmp = new Bitmap ( sz.Width, sz.Height ) ;
g = Graphics.FromImage ( mybmp ) ;
Color bkclr = this.BackColor ;
g.Clear ( bkclr ) ;
p = new Pen ( Color.Black ) ;
b = new SolidBrush ( Color.Purple ) ;
}
In the constructor, after a call to
InitializeComponent( ), we have created a Bitmap object having
the same size as that of the control and collected its reference in mybmp.
Then we obtained a graphics context of the bitmap using the FromImage( )
shared method of the Graphics class and collected the reference of the
context in g. Next using the Clear( ) method we have painted the
background of the bitmap with the background of the control. We have then initialised
a black pen and purple brush. As you guessed, b and p are added
as data members of type SolidBrush and Pen respectively.
Let us now see how the painting is done
in the Tick event handler.
Private Sub mytimer_Tick ( ByVal sender As
Object,
ByVal e As System.EventArgs )
Handles mytimer.Tick
g.TranslateTransform ( 60, 60 ) ;
for ( int i = 0 ; i<=12; i++ )
{
g.FillRectangle ( b, -2, -45, 4, 5 ) ;
g.RotateTransform ( 30 ) ;
}
g.ResetTransform( ) ;
//seconds
p.Width = 1 ;
p.EndCap = LineCap.Flat ;
p.Color = Color.Red ;
g.TranslateTransform ( 60, 60 ) ;
g.RotateTransform ( s ) ;
g.DrawLine ( p, 0, 0, 0, -40 ) ;
g.ResetTransform( ) ;
//minutes
p.Width = 3 ;
p.EndCap = LineCap.Triangle ;
p.Color = Color.Blue ;
g.TranslateTransform ( 60, 60 ) ;
g.RotateTransform ( m ) ;
g.DrawLine ( p, 0, 0, 0, -30 ) ;
g.ResetTransform( ) ;
//hours
p.Width = 4 ;
g.TranslateTransform ( 60, 60 ) ;
g.RotateTransform ( h ) ;
g.DrawLine ( p, 0, 0, 0, -20 ) ;
g.ResetTransform( ) ;
s += 6 ;
if ( s == 360 )
s = 0 ;
sec = sec + 1 ;
if ( sec == 60 )
{
sec = 0 ;
m += 6 ;
if ( m == 360 )
m = 0 ;
min = min + 1 ;
h += 0.5f ;
if ( h == 360 )
h = 0 ;
if ( min == 60 )
{
min = 0 ;
hr += 1 ;
}
}
Size sz = this.Size ;
Rectangle rect = new Rectangle ( 0, 0, sz.Width,
sz.Height ) ;
Bitmap bm = mybmp.Clone ( rect,
mybmp.PixelFormat ) ;
this.BackgroundImage = bm ;
Color bkclr = this.BackColor ;
g.Clear ( bkclr ) ;
}
We will discuss this handler next time.
In the next article we will also create a client for this custom control.
 |
Yashavant Kanetkar, one of the first Express Computer
columnists, is an established software expert, speaker and author with several
best-sellers to his credit, including titles like “Let Us C” and the “Fundas”
series. Contact him at kanet@nagpur.dot.net.in |
|