Creating ActiveX Control



We have so far seen how to create an ActiveX DLL and ActiveX EXE.  Those two are called as ActiveX code components. We will now discuss about how to create ActiveX Control.
ActiveX Controls were previously known as OLE controls. The fundamental difference between those OLE controls and ActiveX controls is the support for Internet.  ActiveX control can be placed on web pages to make web pages more interactive.  Something like how you place a Java Applet in a web page.

In this chapter, first we will create a simple ActiveX control to get an overall idea about how to create ActiveX controls.  In the next chapter we will get into more details of ActiveX control.

Creating a Number control
Number ActiveX control is a modified version of Textbox. Unlike a textbox, Number control can accept only digits and backspace.  You can use this control instead of a textbox whenever you want to accept a number from user. As user cannot enter anything other than digits, there is no scope for making errors.  This control also contains a few user-defined properties, methods and events (see table 27.1)

Properties, Methods and Events of Number control are as follows:

Type
Name
Value
Property
Value
Sets/returns the value in number control.

MaxLength
Sets/ returns the maximum number of digits that can be entered.

MinLength
Sets/returns the minimum number of digits to be entered.
Method
Clear
Clears the content of the control.
Event
InvalidChar
Fired when an invalid character is entered. Passes invalid character as the parameter.

LengthError
Fired when minimum length is not entered by user.
Table 27.1 : Members of ActiveX controls.

The following are the major steps in creating an ActiveX control:

¨         Creating ActiveX control project
¨         Placing intrinsic controls (standard controls) on UserControl and changing their properties
¨         Writing code for events
¨         Changing properties of the project and creating .OCX file.

Let us follow the steps mentioned above to create Number control.

Creating an ActiveX control Project
Create a new project of type ActiveX control to create Number control as follows:

1.      Select File->New Project and choose ActiveX Control as the project type.
A new project is created with a single UserControl.  A UserControl object is similar to a form. It can contain intrinsic controls such as textbox, command button etc.
Placing control and changing properties
1.      Now invoke UserControl designer by double clicking on UserControl1 in Project Explorer.
2.      Place a textbox at the upper left corner of the UserControl. (See figure 27.1)
3.      Resize UserControl to the size of textbox.
When control is placed in client application, client application can change the size of the usercontrol according to its requirement.
Whenever user control’s size is changed the size of textbox should also be changed. This is done using Resize event of usercontrol (see listing 27.1).
4.      Change the following properties of Usercontrol and Textbox.
           
Object
Property
Value
UserControl
Name
Number
Text1
Name
Txtnumber

Text
“”(Null)

At the end of this step, UserControl designer should look like the one in figure 27.1.

Writing Code
We will write only a part of the code now.  Now concentrate on important events such as KeyPress event for textbox, Resize event of  UserControl.

Private Sub txtNumber_KeyPress(KeyAscii As Integer)
' ignore nondigits
 If KeyAscii < 48 Or KeyAscii > 57 Then
   ' if key is not tab key
   If KeyAscii <> 8 Then
      KeyAscii = 0  'ignore
   End If
 End If
End Sub

Private Sub UserControl_Resize ()

  txtNumber.Move 0, 0, UserControl.Width, UserControl.Height
 
End Sub
Listing 27.1:Code for user control.

UserControl object contains Width and Height properties that contain the width and height of the UserControl object.  So change the size of textbox to the size of UserControl object using Width and Height properties of UserControl.

Number control needs a few properties. So let us add required properties to ActiveX control.  To create properties we can use ActiveX Control Interface Wizard. But for now let us do it manually. In the next chapter we will see how to use ActiveX Control Interface Wizard.

To create Value property:

1.      Invoke code window and then Select  Tools -> Add Procedure.
2.      Enter Value as the name of the property and select Property radio button in Type group.
3.      Click on Ok.

Two property procedures are automatically created.  One is Property Let and another one is Property Get.  Write the following code. The code is used to map Text property of textbox to value property of number control.

Public Property Get Value() As Variant
      Value = txtNumber.Text
End Property

Public Property Let Value(ByVal vNewValue As Variant)
      txtNumber.Text = vNewValue
End Property
Listing 27.2: Code for Value property procedure

We will add remaining functionality to the control later. For the time being, let us create .OCX file and use it in a client application.

Creating .OCX file

Save project and give the following names.

Project             Numberctrl.vbp

UserControl     Number.ctl

Change required properties of the project using project properties window as follows

Project Name               NumberCtrl
Project Description      Number Control By P.Srikanth.

To create .OCX file:

1.      Select File-> Make Numberctrl.ocx
2.      Specify the directory in which .ocx file is to be created.
3.      Click on Ok.
Visual Basic creates .ocx file and also registers ActiveX control in system registry.

That's all you have to do to create a simple ActiveX control. Remember we still have to add some more features to our ActiveX control. In spite of that, let us use it in a client application to get an idea regarding how it works in client application.

Creating Testing Project
We create a testing project to test ActiveX control.  The project contains nothing but a single form and one instance of Number control.  Follow the steps given below.

1.      Select File->New Project and select  Standard Exe as the project type.
2.      Select  Project -> Components and select  Number Control By P.Srikanth.
Tool box contains a new icon (see figure 27.2) representing Number control.  If you take MousePointer on to it, it displays Number as the tooltip.
3.      Create an instance of Number control just like how you create an instance of standard control (by selecting the icon and then dragging on to form).
4.      Also place a command button to get the number that we have entered into it through value property.
5.      Change the following properties of command button and the form.

Object
Property
Value
Form
Name
txtNumctrl

Caption
Testing Number Control
Command1
Name
Cmddispvalue

Caption
&Display Value

Write the following code.

Private Sub cmddispvalue_Click()

  MsgBox Number1.Value, , "Value"
 
End Sub
Listing 27.3: Code for Display Value button.

Running test project

1.      Run the project by pressing F5.
2.      Enter a few digits into Number control. It will receive them. Now enter a few alphabets. It will ignore alphabets. Try pressing backspace. It will erase previously entered digit.
3.      Click on Display Value command button. A message box will be displayed with the value entered into the Number control. See figure 27.3.
4.      Close testing project and open  NumberCtrl (ActiveX control ) project. Now let us enhance our control by adding remaining properties, methods and events.

Enhancing Number Control
The only user-defined property that we have (Value) is mapped to Text property of txtNumber textbox. Now we want to limit the number of digits entered into text box. Text box control also contains MaxLength property. So let us create MaxLength property for UserControl and map it to MaxLength property of textbox.

To create MaxLength property:

1.      Get into code window and then select Tools -> Add Procedure.
2.      Enter MaxLength as the name and select Property radio button in Type group.
3.      Then change property procedures as shown in listing 27.4.



Public Property Get MaxLength() As Variant
   MaxLength = txtNumber.MaxLength
End Property

Public Property Let MaxLength(ByVal vNewValue As Variant)
    txtNumber.MaxLength = vNewValue
End Property
Listing 27.4: Code for MaxLength property.
Note: There is no MinLength property for text box. So creating MinLength property involves a bit more work. And we will do it later.

To create Clear method:

1.      Select Tools -> Add Procedure
2.      Enter Clear as the name and select Sub as type.
3.      Write the following code.

Public Sub Clear ()
    txtNumber.Text = ""
End Sub

To create InvalidChar event:

1.      Select Tools -> Add Procedure
2.      Enter InvalidChar as the name and select Event as the type.
 Visual Basic places a single statement in general/declaration as follows.

Public Event InvalidChar()

Add an argument to event of integer type as shown below.  This is to pass the Ascii code of the invalid character enter by the user.

Public Event InvalidChar(ch As Integer)

Modifying  KeyPress event procedure of Text box
KeyPress event is to be modified as it has to raise InvalidChar event whenever it encounters invalid character.   So modified code is shown in listing.

Private Sub txtNumber_KeyPress(KeyAscii As Integer)
' ignore nondigits
 If KeyAscii < 48 Or KeyAscii > 57 Then
   ' if key is not tab key
   If KeyAscii <> 8 Then
      KeyAscii = 0  'ignore
      RaiseEvent InvalidChar(KeyAscii)
   End If
 End If
End Sub
Listing 27.6: Code for KeyPress event of the textbox.

3.      Now save the project and recreate  .OCX file.
4.      Close NumberCtrl project and open tstNumctrl project.
At the time of opening Visual Basic detects that Number control was modified and a new version was created. So it displays a message box (see figure27.4) informing that the control will be upgraded to new one.

Click on Ok to use upgraded control.

To test InvalidChar event and clear method, add a label control to display the most recently entered invalid characters and a command button to clear the value from number control. 

 Change properties of all the controls that are added.

Control
Property
Value
Command button
Name
CmdClear

Caption
&Clear
Label
Name
Lblchar

Caption
“ “

BorderStyle
1-fixed Single

BackColor
White (&H8000000E&)
Label
Caption
Recent Invalid Character


Write the following code for click event of clear button and InvalidChar event of Number1.

Private Sub cmdClear_Click()
    Number1.Clear
    Number1.SetFocus
End Sub    

Private Sub Number1_InvalidChar(ch As Integer)
   lblchar.Caption = Chr$(ch)
End Sub
Listing 27.7: Code in testing form.
 
Run the project and enter 1583 followd by J.  As J is not a valid character for Number control, Number control fires InvalidChar event and passes the Ascii code of the character as the parameter. We used InvalidChar event of Number1 control and placed the character form of the Ascii code into label. See figure 27.5.

 Testing MaxLength Property
Now let us test maxlength property of the control by following the steps given below.

1. Invoke properties window of Number1 control and change MaxLength property to 10.
2 .Run the testing project and see whether you can enter more than 10 digits.

Shocked…

Oh, it does not work. You are able to enter as many digits as you want. But if we set MaxLength property to 10, it indirectly set MaxLength property of text box to 10.  Does it mean MaxLength property of text box is not working. I suggest before you come to any conclusion, try the following with Value property.

1.      Invoke properties window of Number1 control and change Value property to 100.
2.      When you dismiss Properties window, you see 100 in the control. That’s OK.
3.      Run the testing project and see what you have in Number control.

Shocked… again.

Don’t worry. We will see later what is happening. For now all that I can say is, it is a very important part of ActiveX controls. We will understand more about it  later in this chapter. For the time being it is a mystery.

Adding MinLength  property and LengthError event
MinLength property specifies the minimum number of digits to be entered by user. It is set to 0 by default.  If user doesn't enter given number of digits then LengthError event is fired and focus remains in the control.

Open NumberCtrl  project. If it is not already open and take the following steps:

To add MinLength property:

1.      Get into code window of UserControl.
2.      Select Tools ->Add Procedure and enter MinLength as name.
3.      Select  Property radio button from Type group.
4.      Click on ok

To add LengthError Event

1.      Select Tools-> Add Procedure option.
2.      Enter LengthError as name and select Event option in Type group.

Visual Basic places a single statement in general/declarations as follows.

Public Event LengthError()

Property Let and Property Get procedures are created for MinLength Property name is part of the interface of the control. But MinLength is not a variable. It can only interact but cannot store the value.  So declare a variable vMinLength and store minimum length in that variable.  When it comes to accessing minimum length, we use MinLength property but the value is actually stored in vMinLenth variable.  Here are the changes to be made to the existing code.

General / Declarations

Private vMinLength As Integer

Public Property Get MinLength() As Variant
    MinLength = vMinLength
End Property

Public Property Let MinLength(ByVal vNewValue As Variant)
        vMinLength = vNewValue

End Property
Listing  27.7: Code for MinLength property

We use LostFocus event of txtNumber text box to check whether user has entered the required number of digits. Here is the code for LostFocus event.


Private Sub txtNumber_LostFocus()
  ' check whether MinLength number of digits are given
  If Len(txtNumber.Text) < MinLength Then
       RaiseEvent LengthError
       txtNumber.SetFocus
  End If
End Sub
Listing 27.8: Checking for Minimum Number of digits.

Property Persistency
Recollect the problem with MaxLength and Value properties of Number control. When we set Value property to 100 in design mode, that value was not available at runtime. The same was the problem with MaxLength.  And, in fact, that will be the problem with all properties of the ActiveX control. Before we try to solve the problem, let us try to understand the reason for the problem.

ActiveX controls always run, when you place an ActiveX control on a form, even in design mode the ActiveX control runs. Actually an instance of ActiveX control is placed on the form and it is in run mode even when Form is in design mode.

When you place an ActiveX control on the form, an instance of ActiveX control is created and placed on the form.  When you are moving from design mode to run mode by running Visual Basic project,  the instance of ActiveX control that was placed in design mode is destroyed and a new instance of the ActiveX control is created at runtime. That means all the property settings that you have in design mode are gone as the instance itself is destroyed. When a new instance is created at runtime, it has all the properties reset to default values.

That means the property settings do not have any persistency. Properties lose their values when they move from design mode to run mode.  And also when you save and reopen the project and so on.

We can achieve property persistence by storing the property setting before the instance is destroyed and retrieve the setting when a new instance is created. This is what is called as property persistence. So we achieved property persistence by writing the values of properties to disk and then reading them back when they are required.

WriteProperties Event
This event of UserControl object occurs whenever a controls property settings are to be saved. For example, when you are moving from design mode to run mode, as the settings of properties are to be saved, WriteProperties event occurs.  

WriteProperties event is used to:

Write setting of properties into Propety Bag (PropBag) object using WriteProperty Method.

WriteProperties event doesn’t occurs in the following cases:

When Visual Basic believes no property values have changed.
When switching from run mode to design mode.

ReadProperties Event
This event occurs whenever the control is created except for the very first time. ReadProperties event is used to read the setting of properties that were written using WriteProperties event.  The following are the steps to be taken in this event:

Read the values of properties from Property Bag (PropBag) object.

InitProperties Event
This event occurs when control is created for the very first time. For example, when you drag and drop a control on the form. 

Use this event to set initial values to properties and perform any other operations that you want to perform only for once in the life time of the control.

PropertyChanged Method
PropetyChanged method is used to mark a property as changed.  Only those properties that are marked as changed will be written by Visual Basic into property bag (PropBag) object during WriteProperties event.

This method takes the name of the property that has been changed as the parameter and notifies Visual Basic that the property has changed.

The following is the syntax of PropertyChanged method.

PropertyChanged  propertyname

This method is used for the following reasons:

¨         To notify Visual Basic which properties need to be written to PropBag when project is saved or when switching from design mode to run mode.
¨         To update the value of the property when the property is changed through property page in design mode.
¨         To update database when a data bound property is changed
 Providing Object Persistency to Number control
Now let us put what we have understood to practice. As you know we have not taken care of property persistence in Number control. Now let us add code for the above mentioned event to provide object persistence. Actually  ActiveX Control Interface Wizard automatically writes code for these events. We will use it in the next chapter, but for the time being let us add the following code for Number control normally.

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
 Value = PropBag.ReadProperty("Value", 0)
 MinLength = PropBag.ReadProperty("MinLength", 0)
 MaxLength = PropBag.ReadProperty("MaxLength", 0)
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
 PropBag.WriteProperty "Value", Value, 0
 PropBag.WriteProperty "MinLength", MinLength, 0
 PropBag.WriteProperty "MaxLength", MaxLength, 0
End Sub
Listing  27.9: Code to write and read properties to and from property bag.

Test run
1.      Open the text project and do the following.
Now invoke properties window and change Value property to 100 and MaxLength property to 10.
2.      Run the project using F5.
You should see value 100 in Number control at runtime.  And you should not be able to enter more than 10 digits. That means whatever settings you have at design mode those settings are available even in run mode.
The following is the sequence of events that made the property persistence possible:

¨         When project is switching from design mode to run mode, WriteProperties event occurs.
¨         WriteProperty method of PropBag object writes the current values of properties into PropBag object.
¨         Then control's instance in design mode is removed.
¨         Project has entered into run mode.
¨         A new instance of control is created and placed on the form.
¨         ReadProperties event occurs.
¨         ReadProperty method of PropBag object is used to read the values of properties from PropBag and assign those values to properties.
Now let us understand what are the events that occur in various scenarios related to property persistence.

Scenario #1, creating a new control

Whenever you create a new instance of an ActiveX control by placing the control on the form,  the following event of ActiveX control occur in the given order.

¨       Initialize
¨       InitProperties
¨       Resize
¨       Paint

Scenario #2, Switching from Design mode to Run mode

The following events of ActiveX control occurs whenever you switch from design mode to run mode in Visual Basic IDE.

¨       WriteProperties
¨       Terminate
¨       Initialize
-       ReadProperties
¨       Resize
¨       Paint

 Scenario #3, Switching from Run mode to design mode

The following events of ActiveX control occurs whenever you switch from run mode to design mode in Visual Basic IDE.

¨       Terminate
¨       Initialize
¨       ReadProperties
¨       Resize
¨       Paint

 Scenario #4, saving the project
The following events occur when you save project in VB IDE.

¨       WriteProperties
¨       Terminate
 Scenario #5, Project is opened into Visual Basic IDE
The following events occur when you open project in VB IDE

¨       Initialize
¨       ReadProperties
¨       Resize
¨       Paint
¨       WriteProperties


Note: WriteProperties event occurs when you open the project because Visual Basic has to write the properties read using ReadProperties to in-memory copy of .frm file.

Properties persistence is very important part of ActiveX control. You need to maintain values for properties across control instance.
 

No comments:

Creating ActiveX Control



We have so far seen how to create an ActiveX DLL and ActiveX EXE.  Those two are called as ActiveX code components. We will now discuss about how to create ActiveX Control.
ActiveX Controls were previously known as OLE controls. The fundamental difference between those OLE controls and ActiveX controls is the support for Internet.  ActiveX control can be placed on web pages to make web pages more interactive.  Something like how you place a Java Applet in a web page.

In this chapter, first we will create a simple ActiveX control to get an overall idea about how to create ActiveX controls.  In the next chapter we will get into more details of ActiveX control.

Creating a Number control
Number ActiveX control is a modified version of Textbox. Unlike a textbox, Number control can accept only digits and backspace.  You can use this control instead of a textbox whenever you want to accept a number from user. As user cannot enter anything other than digits, there is no scope for making errors.  This control also contains a few user-defined properties, methods and events (see table 27.1)

Properties, Methods and Events of Number control are as follows:

Type
Name
Value
Property
Value
Sets/returns the value in number control.

MaxLength
Sets/ returns the maximum number of digits that can be entered.

MinLength
Sets/returns the minimum number of digits to be entered.
Method
Clear
Clears the content of the control.
Event
InvalidChar
Fired when an invalid character is entered. Passes invalid character as the parameter.

LengthError
Fired when minimum length is not entered by user.
Table 27.1 : Members of ActiveX controls.

The following are the major steps in creating an ActiveX control:

¨         Creating ActiveX control project
¨         Placing intrinsic controls (standard controls) on UserControl and changing their properties
¨         Writing code for events
¨         Changing properties of the project and creating .OCX file.

Let us follow the steps mentioned above to create Number control.

Creating an ActiveX control Project
Create a new project of type ActiveX control to create Number control as follows:

1.      Select File->New Project and choose ActiveX Control as the project type.
A new project is created with a single UserControl.  A UserControl object is similar to a form. It can contain intrinsic controls such as textbox, command button etc.
Placing control and changing properties
1.      Now invoke UserControl designer by double clicking on UserControl1 in Project Explorer.
2.      Place a textbox at the upper left corner of the UserControl. (See figure 27.1)
3.      Resize UserControl to the size of textbox.
When control is placed in client application, client application can change the size of the usercontrol according to its requirement.
Whenever user control’s size is changed the size of textbox should also be changed. This is done using Resize event of usercontrol (see listing 27.1).
4.      Change the following properties of Usercontrol and Textbox.
           
Object
Property
Value
UserControl
Name
Number
Text1
Name
Txtnumber

Text
“”(Null)

At the end of this step, UserControl designer should look like the one in figure 27.1.

Writing Code
We will write only a part of the code now.  Now concentrate on important events such as KeyPress event for textbox, Resize event of  UserControl.

Private Sub txtNumber_KeyPress(KeyAscii As Integer)
' ignore nondigits
 If KeyAscii < 48 Or KeyAscii > 57 Then
   ' if key is not tab key
   If KeyAscii <> 8 Then
      KeyAscii = 0  'ignore
   End If
 End If
End Sub

Private Sub UserControl_Resize ()

  txtNumber.Move 0, 0, UserControl.Width, UserControl.Height
 
End Sub
Listing 27.1:Code for user control.

UserControl object contains Width and Height properties that contain the width and height of the UserControl object.  So change the size of textbox to the size of UserControl object using Width and Height properties of UserControl.

Number control needs a few properties. So let us add required properties to ActiveX control.  To create properties we can use ActiveX Control Interface Wizard. But for now let us do it manually. In the next chapter we will see how to use ActiveX Control Interface Wizard.

To create Value property:

1.      Invoke code window and then Select  Tools -> Add Procedure.
2.      Enter Value as the name of the property and select Property radio button in Type group.
3.      Click on Ok.

Two property procedures are automatically created.  One is Property Let and another one is Property Get.  Write the following code. The code is used to map Text property of textbox to value property of number control.

Public Property Get Value() As Variant
      Value = txtNumber.Text
End Property

Public Property Let Value(ByVal vNewValue As Variant)
      txtNumber.Text = vNewValue
End Property
Listing 27.2: Code for Value property procedure

We will add remaining functionality to the control later. For the time being, let us create .OCX file and use it in a client application.

Creating .OCX file

Save project and give the following names.

Project             Numberctrl.vbp

UserControl     Number.ctl

Change required properties of the project using project properties window as follows

Project Name               NumberCtrl
Project Description      Number Control By P.Srikanth.

To create .OCX file:

1.      Select File-> Make Numberctrl.ocx
2.      Specify the directory in which .ocx file is to be created.
3.      Click on Ok.
Visual Basic creates .ocx file and also registers ActiveX control in system registry.

That's all you have to do to create a simple ActiveX control. Remember we still have to add some more features to our ActiveX control. In spite of that, let us use it in a client application to get an idea regarding how it works in client application.

Creating Testing Project
We create a testing project to test ActiveX control.  The project contains nothing but a single form and one instance of Number control.  Follow the steps given below.

1.      Select File->New Project and select  Standard Exe as the project type.
2.      Select  Project -> Components and select  Number Control By P.Srikanth.
Tool box contains a new icon (see figure 27.2) representing Number control.  If you take MousePointer on to it, it displays Number as the tooltip.
3.      Create an instance of Number control just like how you create an instance of standard control (by selecting the icon and then dragging on to form).
4.      Also place a command button to get the number that we have entered into it through value property.
5.      Change the following properties of command button and the form.

Object
Property
Value
Form
Name
txtNumctrl

Caption
Testing Number Control
Command1
Name
Cmddispvalue

Caption
&Display Value

Write the following code.

Private Sub cmddispvalue_Click()

  MsgBox Number1.Value, , "Value"
 
End Sub
Listing 27.3: Code for Display Value button.

Running test project

1.      Run the project by pressing F5.
2.      Enter a few digits into Number control. It will receive them. Now enter a few alphabets. It will ignore alphabets. Try pressing backspace. It will erase previously entered digit.
3.      Click on Display Value command button. A message box will be displayed with the value entered into the Number control. See figure 27.3.
4.      Close testing project and open  NumberCtrl (ActiveX control ) project. Now let us enhance our control by adding remaining properties, methods and events.

Enhancing Number Control
The only user-defined property that we have (Value) is mapped to Text property of txtNumber textbox. Now we want to limit the number of digits entered into text box. Text box control also contains MaxLength property. So let us create MaxLength property for UserControl and map it to MaxLength property of textbox.

To create MaxLength property:

1.      Get into code window and then select Tools -> Add Procedure.
2.      Enter MaxLength as the name and select Property radio button in Type group.
3.      Then change property procedures as shown in listing 27.4.



Public Property Get MaxLength() As Variant
   MaxLength = txtNumber.MaxLength
End Property

Public Property Let MaxLength(ByVal vNewValue As Variant)
    txtNumber.MaxLength = vNewValue
End Property
Listing 27.4: Code for MaxLength property.
Note: There is no MinLength property for text box. So creating MinLength property involves a bit more work. And we will do it later.

To create Clear method:

1.      Select Tools -> Add Procedure
2.      Enter Clear as the name and select Sub as type.
3.      Write the following code.

Public Sub Clear ()
    txtNumber.Text = ""
End Sub

To create InvalidChar event:

1.      Select Tools -> Add Procedure
2.      Enter InvalidChar as the name and select Event as the type.
 Visual Basic places a single statement in general/declaration as follows.

Public Event InvalidChar()

Add an argument to event of integer type as shown below.  This is to pass the Ascii code of the invalid character enter by the user.

Public Event InvalidChar(ch As Integer)

Modifying  KeyPress event procedure of Text box
KeyPress event is to be modified as it has to raise InvalidChar event whenever it encounters invalid character.   So modified code is shown in listing.

Private Sub txtNumber_KeyPress(KeyAscii As Integer)
' ignore nondigits
 If KeyAscii < 48 Or KeyAscii > 57 Then
   ' if key is not tab key
   If KeyAscii <> 8 Then
      KeyAscii = 0  'ignore
      RaiseEvent InvalidChar(KeyAscii)
   End If
 End If
End Sub
Listing 27.6: Code for KeyPress event of the textbox.

3.      Now save the project and recreate  .OCX file.
4.      Close NumberCtrl project and open tstNumctrl project.
At the time of opening Visual Basic detects that Number control was modified and a new version was created. So it displays a message box (see figure27.4) informing that the control will be upgraded to new one.

Click on Ok to use upgraded control.

To test InvalidChar event and clear method, add a label control to display the most recently entered invalid characters and a command button to clear the value from number control. 

 Change properties of all the controls that are added.

Control
Property
Value
Command button
Name
CmdClear

Caption
&Clear
Label
Name
Lblchar

Caption
“ “

BorderStyle
1-fixed Single

BackColor
White (&H8000000E&)
Label
Caption
Recent Invalid Character


Write the following code for click event of clear button and InvalidChar event of Number1.

Private Sub cmdClear_Click()
    Number1.Clear
    Number1.SetFocus
End Sub    

Private Sub Number1_InvalidChar(ch As Integer)
   lblchar.Caption = Chr$(ch)
End Sub
Listing 27.7: Code in testing form.
 
Run the project and enter 1583 followd by J.  As J is not a valid character for Number control, Number control fires InvalidChar event and passes the Ascii code of the character as the parameter. We used InvalidChar event of Number1 control and placed the character form of the Ascii code into label. See figure 27.5.

 Testing MaxLength Property
Now let us test maxlength property of the control by following the steps given below.

1. Invoke properties window of Number1 control and change MaxLength property to 10.
2 .Run the testing project and see whether you can enter more than 10 digits.

Shocked…

Oh, it does not work. You are able to enter as many digits as you want. But if we set MaxLength property to 10, it indirectly set MaxLength property of text box to 10.  Does it mean MaxLength property of text box is not working. I suggest before you come to any conclusion, try the following with Value property.

1.      Invoke properties window of Number1 control and change Value property to 100.
2.      When you dismiss Properties window, you see 100 in the control. That’s OK.
3.      Run the testing project and see what you have in Number control.

Shocked… again.

Don’t worry. We will see later what is happening. For now all that I can say is, it is a very important part of ActiveX controls. We will understand more about it  later in this chapter. For the time being it is a mystery.

Adding MinLength  property and LengthError event
MinLength property specifies the minimum number of digits to be entered by user. It is set to 0 by default.  If user doesn't enter given number of digits then LengthError event is fired and focus remains in the control.

Open NumberCtrl  project. If it is not already open and take the following steps:

To add MinLength property:

1.      Get into code window of UserControl.
2.      Select Tools ->Add Procedure and enter MinLength as name.
3.      Select  Property radio button from Type group.
4.      Click on ok

To add LengthError Event

1.      Select Tools-> Add Procedure option.
2.      Enter LengthError as name and select Event option in Type group.

Visual Basic places a single statement in general/declarations as follows.

Public Event LengthError()

Property Let and Property Get procedures are created for MinLength Property name is part of the interface of the control. But MinLength is not a variable. It can only interact but cannot store the value.  So declare a variable vMinLength and store minimum length in that variable.  When it comes to accessing minimum length, we use MinLength property but the value is actually stored in vMinLenth variable.  Here are the changes to be made to the existing code.

General / Declarations

Private vMinLength As Integer

Public Property Get MinLength() As Variant
    MinLength = vMinLength
End Property

Public Property Let MinLength(ByVal vNewValue As Variant)
        vMinLength = vNewValue

End Property
Listing  27.7: Code for MinLength property

We use LostFocus event of txtNumber text box to check whether user has entered the required number of digits. Here is the code for LostFocus event.


Private Sub txtNumber_LostFocus()
  ' check whether MinLength number of digits are given
  If Len(txtNumber.Text) < MinLength Then
       RaiseEvent LengthError
       txtNumber.SetFocus
  End If
End Sub
Listing 27.8: Checking for Minimum Number of digits.

Property Persistency
Recollect the problem with MaxLength and Value properties of Number control. When we set Value property to 100 in design mode, that value was not available at runtime. The same was the problem with MaxLength.  And, in fact, that will be the problem with all properties of the ActiveX control. Before we try to solve the problem, let us try to understand the reason for the problem.

ActiveX controls always run, when you place an ActiveX control on a form, even in design mode the ActiveX control runs. Actually an instance of ActiveX control is placed on the form and it is in run mode even when Form is in design mode.

When you place an ActiveX control on the form, an instance of ActiveX control is created and placed on the form.  When you are moving from design mode to run mode by running Visual Basic project,  the instance of ActiveX control that was placed in design mode is destroyed and a new instance of the ActiveX control is created at runtime. That means all the property settings that you have in design mode are gone as the instance itself is destroyed. When a new instance is created at runtime, it has all the properties reset to default values.

That means the property settings do not have any persistency. Properties lose their values when they move from design mode to run mode.  And also when you save and reopen the project and so on.

We can achieve property persistence by storing the property setting before the instance is destroyed and retrieve the setting when a new instance is created. This is what is called as property persistence. So we achieved property persistence by writing the values of properties to disk and then reading them back when they are required.

WriteProperties Event
This event of UserControl object occurs whenever a controls property settings are to be saved. For example, when you are moving from design mode to run mode, as the settings of properties are to be saved, WriteProperties event occurs.  

WriteProperties event is used to:

Write setting of properties into Propety Bag (PropBag) object using WriteProperty Method.

WriteProperties event doesn’t occurs in the following cases:

When Visual Basic believes no property values have changed.
When switching from run mode to design mode.

ReadProperties Event
This event occurs whenever the control is created except for the very first time. ReadProperties event is used to read the setting of properties that were written using WriteProperties event.  The following are the steps to be taken in this event:

Read the values of properties from Property Bag (PropBag) object.

InitProperties Event
This event occurs when control is created for the very first time. For example, when you drag and drop a control on the form. 

Use this event to set initial values to properties and perform any other operations that you want to perform only for once in the life time of the control.

PropertyChanged Method
PropetyChanged method is used to mark a property as changed.  Only those properties that are marked as changed will be written by Visual Basic into property bag (PropBag) object during WriteProperties event.

This method takes the name of the property that has been changed as the parameter and notifies Visual Basic that the property has changed.

The following is the syntax of PropertyChanged method.

PropertyChanged  propertyname

This method is used for the following reasons:

¨         To notify Visual Basic which properties need to be written to PropBag when project is saved or when switching from design mode to run mode.
¨         To update the value of the property when the property is changed through property page in design mode.
¨         To update database when a data bound property is changed
 Providing Object Persistency to Number control
Now let us put what we have understood to practice. As you know we have not taken care of property persistence in Number control. Now let us add code for the above mentioned event to provide object persistence. Actually  ActiveX Control Interface Wizard automatically writes code for these events. We will use it in the next chapter, but for the time being let us add the following code for Number control normally.

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
 Value = PropBag.ReadProperty("Value", 0)
 MinLength = PropBag.ReadProperty("MinLength", 0)
 MaxLength = PropBag.ReadProperty("MaxLength", 0)
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
 PropBag.WriteProperty "Value", Value, 0
 PropBag.WriteProperty "MinLength", MinLength, 0
 PropBag.WriteProperty "MaxLength", MaxLength, 0
End Sub
Listing  27.9: Code to write and read properties to and from property bag.

Test run
1.      Open the text project and do the following.
Now invoke properties window and change Value property to 100 and MaxLength property to 10.
2.      Run the project using F5.
You should see value 100 in Number control at runtime.  And you should not be able to enter more than 10 digits. That means whatever settings you have at design mode those settings are available even in run mode.
The following is the sequence of events that made the property persistence possible:

¨         When project is switching from design mode to run mode, WriteProperties event occurs.
¨         WriteProperty method of PropBag object writes the current values of properties into PropBag object.
¨         Then control's instance in design mode is removed.
¨         Project has entered into run mode.
¨         A new instance of control is created and placed on the form.
¨         ReadProperties event occurs.
¨         ReadProperty method of PropBag object is used to read the values of properties from PropBag and assign those values to properties.
Now let us understand what are the events that occur in various scenarios related to property persistence.

Scenario #1, creating a new control

Whenever you create a new instance of an ActiveX control by placing the control on the form,  the following event of ActiveX control occur in the given order.

¨       Initialize
¨       InitProperties
¨       Resize
¨       Paint

Scenario #2, Switching from Design mode to Run mode

The following events of ActiveX control occurs whenever you switch from design mode to run mode in Visual Basic IDE.

¨       WriteProperties
¨       Terminate
¨       Initialize
-       ReadProperties
¨       Resize
¨       Paint

 Scenario #3, Switching from Run mode to design mode

The following events of ActiveX control occurs whenever you switch from run mode to design mode in Visual Basic IDE.

¨       Terminate
¨       Initialize
¨       ReadProperties
¨       Resize
¨       Paint

 Scenario #4, saving the project
The following events occur when you save project in VB IDE.

¨       WriteProperties
¨       Terminate
 Scenario #5, Project is opened into Visual Basic IDE
The following events occur when you open project in VB IDE

¨       Initialize
¨       ReadProperties
¨       Resize
¨       Paint
¨       WriteProperties


Note: WriteProperties event occurs when you open the project because Visual Basic has to write the properties read using ReadProperties to in-memory copy of .frm file.

Properties persistence is very important part of ActiveX control. You need to maintain values for properties across control instance.
 

No comments: