Visual Basic Concepts

Ensuring Communication Among ActiveX Documents

Designing ActiveX documents requires a different mindset. Not only are you bereft of QueryUnload and similar events, but you don’t even know when your ActiveX document may be invoked: In an ordinary application, you might have a user navigate through three forms to get to a particular point in your application, but if those forms are ActiveX documents, the user could place the last one in her Favorites list, and come back to it after a week, without going through the intermediate forms! This topic explains how you can control this behavior.

A Little Play: Socrates and Plato

The key to determining whether the user has come to an ActiveX document "cold" (for example, from the Favorites list), or from a known ActiveX document is in setting up a signaling system of some kind. The known ActiveX document must have some way of declaring itself to another ActiveX document in the same suite, and when the second document receives that signal, it can proceed.

One way to set up a signal is to use a global variable. When the global variable is set by a known document, the second document can detect it by using the Is Nothing statement. To illustrate, imagine that the global variable is an envelope that is being passed between two people, Socrates and Plato. Whenever Socrates wants to send a message to Plato, he stuffs the envelope with the message, and leaves it on a pedestal where Plato always passes. When Plato passes the pedestal, he always picks up the envelope, opens it, and checks for a message from Socrates. If there is a message, Plato executes the instructions. Otherwise, he goes on his way.

To implement this metaphor, we need three "actors":

  • Socrates: played by UserDocument1

  • Plato: played by UserDocument2

  • The Envelope: played by global variable named "gEnvelope" in a code module named "Module1."

In order to create a global variable, we must first declare it in a code module (Module1):

Public gEnvelope As UserDocument1

Now imagine that UserDocument1 has a single button on it named "cmdGoPlato." The code for it is:

Private Sub cmdGoPlato_Click()
   Set gEnvelope = Me ' Stuff the envelope.
   Hyperlink.NavigateTo "c:\pedestal\UserDocument2"
End Sub

The stage is now set. When the user clicks the button, the "envelope" is stuffed, and, using the Hyperlink object, sent to UserDocument2.

UserDocument2, meanwhile, has code in the Show event that will check the envelope. It does this by first checking if the global variable is not set to Nothing. If it is not set to Nothing, then the "envelope" is filled, and the code can proceed. Otherwise, it displays a message that requests the user to open UserDocument1 and click the "Go Plato" button.

Private Sub UserDocument_Show()
   If Not gEnvelope Is Nothing Then' proceed normally.
      ' Set properties using the object reference etc.

      ' VERY IMPORTANT! Set the variable to Nothing.
      ' Otherwise the object reference will keep the
      ' object in existence!
      Set gEnvelope = Nothing
   Else
      MsgBox "Sorry, please open UserDocument1 first."
      ' If you're really feeling agressive about this,
      ' you can even hyperlink the user to Socrates:
      Hyperlink.NavigateTo _
         "c:\pedestal\UserDocument1.vbd"
   End If
End Sub

Tracking Your Object References

You may notice that the preceding code sets the object reference to Nothing after the first document hyperlinks to the second. It's very important that you set all such global object references to Nothing. Because as long as the object exists, it continues to use resources and memory. A more complete discussion of this can be found in "Object References and Reference Counting," in "Programming With Objects" of the Programmer's Guide.