Specializing an Existing Control

You'll create a customized button class that keeps track of how often it has been clicked. To begin, open a new project in Visual Studio .NET. In the Project Type window, choose your language of choice, and in the Templates window, choose Windows Control Library. Be sure to set an appropriate location, and name the library CountedControl.

Tip

This example is similar to a custom control demonstrated in Programming ASP.NET, but there are significant differences in how custom controls are created for use with Windows Forms.

You are placed in the designer for a user control. That isn't quite what you want (you'll be creating a user control in the next example), but it isn't a problem. Right-click on the form and choose View Code. Modify the class name to CountedButton and the base class from UserControl to Button:

image with no caption

public class CountedButton : System.Windows.Forms.Button

image with no caption

Public Class CountedButton
    Inherits System.Windows.Forms.Button

In C#, you must also modify the constructor so it has the same name as the class:

image with no caption

public CountedButton(  )

While you are at it, change the filename from UserControl1 to CountedButton.cs or CountedButton.vb.

Tip

When you change the base type from UserControl to Button, Visual Studio .NET will no longer use the Forms Designer in Design view. You'll add to the new derived button type entirely through code.

Override the OnPaint method to draw the number of times the button was clicked:

image with no caption

protected override void OnPaint (PaintEventArgs e)
{
   if ( numClicks =  = 0 )
      this.Text = "Never been clicked";
    else
       this.Text = "Clicked " + numClicks + " times";
  
   base.OnPaint(e);
}

image with no caption

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    If numClicks = 0 Then
        Me.Text = "Never been clicked"
        Else
            Me.Text = "Clicked " & numClicks & " times"
    End If
    MyBase.OnPaint(e)
End Sub

Finally, override the on-click method to update the number of clicks, and invalidate the button so it will be repainted.

image with no caption

protected override void OnClick( EventArgs e )
{
   numClicks++;
   Invalidate(  );
   base.OnClick(e);
}

image with no caption

Protected Overrides Sub OnClick(ByVal e As EventArgs)
    numClicks = numClicks + 1
    Invalidate(  )
    MyBase.OnClick(e)
End Sub

That's all there is to it! Build your control, and you are ready to test it. The complete source code for the custom control in C# is shown in Example 17-1 and the VB.NET version is shown in Example 17-2.

Example 17-1. Custom derived control (C#)

image with no caption

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
   
namespace CountedButtonCS1
{
   // change the base class to button
   public class CountedButton : System.Windows.Forms.Button
   {
      private System.ComponentModel.Container components = null;
      private int numClicks = 0; // keep track of number of clicks
   
      public CountedButton(  )
      {
         InitializeComponent(  );
      }
   
      // override OnPaint to display the number of clicks
      protected override void OnPaint (PaintEventArgs e)
      {
         if ( numClicks =  = 0 )
            this.Text = "Never been clicked";
         else
            this.Text = "Clicked " + numClicks + " times";
   
         base.OnPaint(e);
      }
   
      // when the button is clicked update the counter
      // and invalidate the control
      protected override void OnClick( EventArgs e )
      {
         numClicks++;
         Invalidate(  );
         base.OnClick(e);
      }
   
   
      /// <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 Component Designer generated code
      #endregion
   }
}

Example 17-2. Custom derived control (VB.NET)

image with no caption

' change the base class to button 
Public Class CountedButton
    Inherits System.Windows.Forms.Button
   
   
    ' keep track of number of clicks
    Private numClicks As Integer = 0
   
    Public Sub New(  )
        MyBase.New(  )
        InitializeComponent(  )
    End Sub
   
    ' override OnPaint to display the number of clicks
    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        If numClicks = 0 Then
            Me.Text = "Never been clicked"
        Else
            Me.Text = "Clicked " & numClicks & " times"
        End If
        MyBase.OnPaint(e)
    End Sub
   
    ' when the button is clicked update the counter
    ' and invalidate the control
    Protected Overrides Sub OnClick(ByVal e As EventArgs)
        numClicks = numClicks + 1
        Invalidate(  )
        MyBase.OnClick(e)
    End Sub
   
#Region " Windows Form Designer generated code "
#End Region
End Class

Testing the Control

Of course, you can't just "run" a control; you need a container, such as a form, within which to test the control. Create a new Windows project in your language of choice and add a reference to the control project. To do so from within Visual Studio .NET, right-click on References and choose Add Reference. Click on the Projects tab, and then click the Browse button. Navigate to the dll you created for your control, and double-click on it. Then click OK to close the Add Reference dialog.

You can add your control to your toolbox by right-clicking on the toolbox and choosing Customize Toolbox. Choose the .NET Framework Components tab, and then click the Browse button. Navigate to and double-click on your dll; the control appears at the bottom of your toolbox.

Tip

You can create your control in one language (e.g., C# or VB.NET) and your test program in another.

Double-click on the control to add it to the form, and size it to display the full message. Run the test program and click on the button. The result, shown in Figure 17-1, is that the button keeps track of how often it is clicked.

The CountedButton control

Figure 17-1. The CountedButton control

Adding Properties

One powerful use for custom controls is to expose custom properties. You might derive from the Button class only to expose new and interesting properties to your clients. In the next example, you'll modify your CountedButton class to add a property that reveals how often the button has been clicked.

The change to the control is almost trivial. Just add a property to the control to provide access to the number of times the button was clicked:

image with no caption

public int NumClicks
{
   get { return numClicks; }
   set { numClicks = value; }
}

image with no caption

Public Property numClicks(  ) As Integer
    Get
        Return _numClicks
    End Get
    Set(ByVal Value As Integer)
        _numClicks = Value
    End Set
End Property

Tip

Because I wanted the property to be named numClicks, I had to change the private field to _numClicks (note the underscore). VB.NET is case insensitive, so you can't use the idiom common in C# of naming the field with a lowercase letter and the property with an uppercase letter.

You can use this property in your test program. Add a label (named lblOut) and a button (named btnUpdate) to your form. Add an event handler for the button to update the label based on the numClicks property:

image with no caption

private void btnUpdate_Click(object sender, System.EventArgs e)
{
   lblOut.Text = 
      "The button was clicked " + 
      countedButton1.NumClicks.ToString(  ) + 
      " times.";
}

image with no caption

Private Sub btnUpdate_Click( _
   ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles btnUpdate.Click
    lblOut.Text = _
     "The button was clicked " & _
     CountedButton1.numClicks.ToString(  ) & _
     " times."
End Sub

The key line of code is shown in bold. Determine how many times the button was pressed by accessing its numClicks property.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset