Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Creating and Using ActiveX DLL's.

ActiveX and DLL Creation

Creating and Using ActiveX DLL's.

by  BobRodes  Posted    (Edited  )
I'm going to give a step by step example of creating and using ActiveX DLL's. We'll use a DLL called DogClass, with two classes: Dog and Puppy. Puppy will be an example of a dependent class in a class hierarchy.

We'll start by creating a new ActiveX DLL Project. Change Class1's Name property to Dog. Change the Project name to DogClass. Save the Project.

Next, add the following code to the Dog class window:

Code:
Option Explicit
'in General Declaration
Public Size As Integer

Public Sub Bark()
If Me.Size = 1 Then
    MsgBox "WOOF WOOF"
Else
    MsgBox "warf warf"
End If
End Sub

Save your work. You now have a usable, bare-bones DLL. You can compile this, set a reference to the DogClass DLL from another project, instantiate a Dog class, set the size property (it will default to 0 if you don't set it, of course), and call the Bark method. If you like, go ahead and try that.

However, we're going to use a test environment, that will allow you to step through code in the client and the DLL simultaneously. To do this, first add Standard EXE project to your DogClass project (File/Add Project). Name this project TestDogClass, and I prefer to name the form frmDogClassTest and caption it "Test Dog Class." To this form, add a command button called cmdTestDogClass and caption it appropriately. In the Project Explorer window, right click on the TestDogClass project and select "Set as Start Up." This line should become boldfaced. Save your work.

Now, making sure that you have something in the TestDogClass project highlighted (as opposed to the DogClass project) in the Project Explorer window, go to References. You should see DogClass near the top. Notice also that DogClass.vbp is listed as the source file. (If you were to remove the DogClass project, and a compiled version existed of it, VB would fix up the reference to DogClass.dll.) Select DogClass. Now, add the following code to the frmTestDogClass code window:
Code:
Option Explicit
'General Declarations section
Dim Fido As DogClass.Dog
Dim Fifi As DogClass.Dog

Private Sub Form_Load()
Set Fido = New DogClass.Dog
Fido.Size = 1
Set Fifi = New DogClass.Dog
Fifi.Size = 0
End Sub

Private Sub cmdTestDogClass_Click()
Fido.Bark
Fifi.Bark
End Sub

Save your work. You'll find you're prompted to save a file called Groupl.grp. Change this to DogClassGroup and save. When you revisit this project, open the group file, not one of the individual projects files. You'll open both of the projects as they are now instead of just one or the other.

Now, run the program, and hit the command button. You should see a big bark and a little bark. If you like, set a breakpoint on the Form_Load event and step through the code, to see what gets called when.

You now have a bare bones class and the testing mechanism for same. Let's add a few enhancements to show some other ideas.

First, let's add an Enum to make the Size property look nicer, and restrict its values to allowable ones. In the General Declarations section of the DogClass code module, comment out the Size property declaration and add the following:
Code:
Enum DogSize
    Big = 1
    Little = 0
End Enum
Public Size As DogSize
'Public Size as Integer

Now, change the Size property assignments and Bark method as follows:
Code:
Private Sub Form_Load()
Set Fido = New DogClass.Dog
Fido.Size = Big
Set Fifi = New DogClass.Dog
Fifi.Size = Little
End Sub

Public Sub Bark()
If Me.Size = Big Then
    MsgBox "WOOF WOOF"
Else
    MsgBox "warf warf"
End If
End Sub
The Enum has the effect of restricting allowable values to 0 and 1.

Now, let's look further at the Size property. A public variable is fine, as far as it goes. But if you need more control, you'll need to use property procedures. For example, if you want to raise custom errors to developers setting properties incorrectly, you'll need them. Also, if you want to create a read-only property, you'll need them.

To create a property using property procedures, there are three steps:
1. Create a module-level variable (any name you like) to hold the current value of the property.
2. Create a Property Let procedure that sets the value of this variable.
3. Create a Property Get procedure that returns the value of this variable.
If you want to create a read-only property, just omit the Let procedure. (For completeness's sake, if the property value is itself an object, you use a property Set procedure instead of a property Let procedure.)
In our case, change the code in the DogClass code window as follows:
Code:
'Public Size As Integer
'Public Size As DogSize
Private cSize As DogSize 'You can use Dim here too

Public Property Get Size() As DogSize
Size = cSize
End Property

Public Property Let Size(x As DogSize)
cSize = x
End Property

So, cSize holds the current value of the property, and the Get and Let property procedures set and return, respectively, the value of cSize.

Next, let's build a dependent object, Puppy. A dependent object is one that can't be directly instantiated by a client. Instead, it's instantiated by calling some method of another class that is itself instantiable, that returns an instance of the class. A well-known example of this is ADO's Field object, which can't be directly instantiated. Rather, you have to instantiate a recordset and open it, and reference the resulting Fields collection of the recordset.

To create the Puppy class, first add a Class to the DogClass project. Name it Puppy. Change (and this is important) the Instancing property to PublicNotCreateable. In this way, clients won't be able to create an instance of Puppy directly. Now, add the following Bark method code to the Puppy class:
Code:
Public Sub Bark()
MsgBox "yip yip"
End Sub
And, add the following Puppy instantiation code to the Dog class:
Code:
Public Function CreatePuppy() As Puppy
Set CreatePuppy = New Puppy
End Function
Note that we don't have to specifically declare a Puppy variable in this context before using the New keyword. In effect, we've done this by returning a variable of type Puppy.

Change the code in frmTestDogClass to look like this, adding Puppy support:
Code:
Option Explicit
Dim Fido As DogClass.Dog
Dim Fifi As DogClass.Dog
Dim Rover As DogClass.Puppy

Private Sub Form_Load()
Set Fido = New DogClass.Dog
Fido.Size = Big
Set Fifi = New DogClass.Dog
Fifi.Size = Little
Set Rover = Fido.CreatePuppy
End Sub

Private Sub cmdTestDogClass_Click()
Fido.Bark
Fifi.Bark
Rover.Bark
End Sub
Save your work, and run it.

Finally, let's do one more thing. We want to know the parent of the puppy, and make it bark in accordance with the parent's size. Now, the clean way to set up the Parent property is to maie it read only, setting it to a reference to the instantiating Dog class at the point of instantiation. This is the sort of thing that constructors are generally used for. In VB6, you have to find another way. With a little work, you can do the same thing.

First, create a read-only property Parent in the Puppy class module, of type Dog. Now, you only want to be able to set this property from the CreatePuppy method of the Dog class. As such, you need to access the Private variable in the Puppy class that holds the current value of the Parent property (we'll use cParent for the name), which you can't do directly. So, how do we do it? We don't want to make cParent public, since then it won't be read only anymore. So, we should create a Sub in Puppy that sets cParent. But, if it's Private, we can't call it from CreatePuppy, and if it's Public, anyone can call it. So, this is where Friend comes in. We want to create a method in Puppy called SetParent, which takes an argument of type Dog which is then assigned to cParent. And, we want this method to be visible throughout the Project, but not to clients of the classes in the project. This is Friend.

So, change the existing code as follows. In Puppy, add the read only Parent property, and evaluate it in the Bark method:
Code:
Private cParent As Dog

Public Property Get Parent() As Dog
Set Parent = cParent
End Property

Friend Sub SetParent(x As Dog)
Set cParent = x
End Sub

Public Sub Bark()
If Me.Parent.Size = Big Then
    MsgBox "yap yap"
Else
    MsgBox "yip yip"
End If
End Sub
In Dog, call the SetParent sub from the CreatePuppy method, passing a reference to the calling Dog instance as the argument:
Code:
Public Function CreatePuppy() As Puppy
Set CreatePuppy = New Puppy
CreatePuppy.SetParent Me
End Function
In the Test module, add another Puppy, and set one parent to the big dog and one to the little:
Code:
Option Explicit
Dim Fido As DogClass.Dog
Dim Fifi As DogClass.Dog
Dim Rover As DogClass.puppy
Dim Lassie As DogClass.puppy

Private Sub Form_Load()
Set Fido = New DogClass.Dog
Fido.Size = Big
Set Fifi = New DogClass.Dog
Fifi.Size = Little
Set Rover = Fifi.CreatePuppy
Set Lassie = Fido.CreatePuppy
End Sub

Private Sub cmdTestDogClass_Click()
Fido.Bark
Fifi.Bark
Rover.Bark
Lassie.Bark
End Sub

All right. This should give you a good grounding in the fundamentals of ActiveX DLLs.

Bob
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top