Dear John, How Do I... Create and Use an ActiveX EXE?

ActiveX EXEs and ActiveX DLLs are similar creatures. In Chapter 27, "Advanced Programming Techniques," I'll walk you through the creation of an ActiveX DLL; here I'll walk you through the creation of an ActiveX EXE. An ActiveX EXE can run by itself, yet it also provides objects for use by external applications. As mentioned, these objects run out-of-process, which means that they run in their own code space, separate from a client application's code space.

Chance—An ActiveX EXE Example

In this example, we'll build a very simple ActiveX EXE containing the definition for one type of object. Or, to use the correct terminology, we'll create one class. The class can then function as a template to produce copies of the object. Once the ActiveX EXE is up and running and automatically registered with the system, we'll build a second, more conventional Visual Basic application that will create a couple of these objects on the fly and manipulate properties and methods of these objects to get the desired results.

We'll create an object named Dice in an ActiveX EXE component named Chance. Even though I've named the object Dice, I've provided properties that let the calling application set the number of sides so that each die can act more like a coin (if it has two sides), like a dodecahedron-shaped die (if the number of sides is set to 12), and so on.

DICE.CLS

Let's jump right in and start building the ActiveX EXE. Start a new project and double-click the ActiveX EXE icon in the New Project dialog box. Add the following lines of code to the class module, change its Name property to Dice, save this class module as DICE.CLS, and save the project as CHANCE.VBP:

Option Explicit
`Declare properties that define the range of possible values
Public Smallest As Integer
Public Largest As Integer

`Declare a read-only property and define its value
`as a roll of the die
Public Property Get Value() As Integer
    Value = Int(Rnd * (Largest - Smallest + 1)) + Smallest
End Property

`Use a method to shuffle the random sequence
Public Sub Shuffle()
    Randomize
End Sub

This class module defines three properties and one method for the Dice object. Smallest and Largest are two properties that I've declared as public variables so that the client application (which is created a little later on) can set the range of returned values—in this case, the number of sides of the die. Properties of objects are often simply declared as public variables in this way.

Value is another property of the Dice object, but in this case we want to perform a little calculation before handing a number back to the client application. The Property Get statement provides the mechanism for performing any extra steps we specify when the property's value is requested. In this case, a random number is generated to simulate a roll of the die, and this number is returned as the value of the property. (For the mathematical purists among us, the number is not truly random, but it's close enough for our needs.) The Value property is read-only for the client application because the Property Get statement was used but there is no corresponding Property Let statement. Adding a Property Let statement would enable the client application to write a new value to the Value property. In this example, we just want to return a random roll of the die, so we have no need to let the client application set a value for this property.

Shuffle is a simple method I've added so that the object will have at least one method to show for itself. When this method is called, the object will randomize the random number generator to effectively shuffle the outcome of rolls of the die.

Let's add a little code that runs when the Chance ActiveX EXE starts up. This will make it easier to follow the action later on. From the Project menu, choose Add Module and then double-click the Module icon in the Add Module dialog box. Add the following code to this module, and save it as CHANCE.BAS:

Option Explicit
Sub Main()
    Dim diceTest As New Dice
    diceTest.Smallest = 1
    diceTest.Largest = 6
    diceTest.Shuffle
    MsgBox "A roll of two dice: " & _
        diceTest.Value & "," & diceTest.Value, _
        0, "Message from the Chance ActiveX EXE"
End Sub

From the Project menu, choose Project1 Properties to open the Project Properties dialog box. From the Startup Object drop-down list, select Sub Main, enter Chance in the Project Name field, enter Chance - ActiveX EXE Example in the Project Description field, and then click OK. Finally, from the File menu, choose Make Chance.exe. In the displayed Make Project dialog box, select a location and click OK. This will compile and automatically register the Chance ActiveX EXE.

Testing the ActiveX EXE Component

Now that the Chance ActiveX EXE is compiled and registered, we can reference it and use its objects from any application that supports ActiveX programming. Let's demonstrate this by creating a second Visual Basic application that uses the ActiveX EXE we just created.

Start a new Standard EXE project, save its default form as DICEDEMO.FRM, and save the project itself as DICEDEMO.VBP. Change the form's Caption property to Taking a Chance with Our ActiveX EXE, and add a single command button. I changed the button's Caption property to Roll 'em and moved it off to the upper right side of the form. Add the following code to the form to complete it, and then save your work:

Option Explicit    
Dim diceTest As New Dice
Private Sub Command1_Click()
    diceTest.Shuffle

    diceTest.Smallest = 1
    diceTest.Largest = 2
    Print "Coin:" & diceTest.Value,
    diceTest.Largest = 6
    Print "Dice:" & diceTest.Value,
    diceTest.Largest = 12
    Print "Dodecahedron:" & diceTest.Value
End Sub

Figure 5-3 shows the form during development.

Figure 5-3. The DiceDemo form.

This form creates an instance of our new Dice object, so we need to add a reference to the Chance ActiveX EXE in order for the current project to know where the Dice object is defined. Choose References from the Project menu, and locate the check box labeled Chance - ActiveX EXE Example in the References dialog box. (Remember that this is the project description we gave the Chance project.) Check this box, and then click OK to add this reference to the DiceDemo project.

That should do it! Run the program and notice what happens. First our new test form opens, ready for us to click the Roll 'em button. When you click this button, the Dice object is created, and rolls of 2-sided, 6-sided, and 12-sided dice are tallied and displayed on the form. Each click creates another line of pseudorandom values. Figure 5-4 shows the results of clicking this button several times.

Figure 5-4. The DiceDemo application after the Roll 'em button has been clicked several times.

One other significant message appears the first time you click the Roll 'em button. As the Chance ActiveX EXE loads into memory, its Sub Main startup code displays a message box, and it also rolls a pair of dice using the Dice object defined within Chance's interior. The result is shown in Figure 5-5.

Figure 5-5. The Chance ActiveX EXE displays this message when it loads.

This message box appears only once, when the Chance component first loads. In case you're wondering, the Chance ActiveX component will unload from memory when the last reference to any of its objects goes away—which happens when we terminate the DiceDemo application.