A Beginner's Guide to COM Interfaces

Saturday Nov 16th 2002 by Sam Huggill

A beginner's guide to COM interfaces.

Before the release of Visual Basic 5, many people could be heard saying COM?? Now professional developers are laughed at if they don't know what COM stands for. Well, it stands for the Component Object Model. In this article I will take you through using COM Interfaces with class modules to create an object orientated program. As we go along, I will try and explain some confusing terms and how they are useful.

Visual Basic makes using COM Interfaces much much easier then C++. In C++ you have to worry about sorting through a mound of information on GUIDs (Globally Unique IDs) and other complicated procedures and functions. Visual Basic takes care of most of this low level stuff, leaving us to have some fun.

When I first heard of COM, Interfaces and Objects I thought I had just landed on planet mars. And to tell the truth, not many other developers actually really understood these terms. So, I grabbed a copy of Deborah Kurata's award winning book, Doing Objects in MS Visual Basic. This book uses her no jargon style writing to clearly explain object orientated programming, including COM. I suggest you take a look.

At the time, many people were asking why should we use COM Interfaces/Objects? Well, the simple answer is that it saves time. One of the points of object orientated programming is code reuse, and, as I explain our demo project, you will see that it creates reusable class modules.

So far I have outlined the background of COM Interfaces etc and you are still wondering what is a COM Interface? Well, an Interface is a way of publishing a set of properties and methods so that other programs can interface with your application through COM. This can be seen in the highly popular VBA scripting language found in most new Microsoft products. To see this in action, open VB, add a reference to the Microsoft Word 8 Object Model, and load up the Object Browser. From the Libraries combo box select Word. Take a look at the properties and methods that it exposes.

To use an interface within your own program you need to use class modules. First of all you create a class that contains only methods and member variables, except you place no code within these methods. This class will be implemented into another class. Let me explain. Say this first class is called IDataOject, and it contains a GetInfo and Save method. Well, you will want another class to take on or 'implement' IDataObject's methods and properties. We do this by using the Implements keyword. We now have another class that implements the IDataObject interface.

I know what you are saying now, why on Earth is this useful? Well, instead of spending another ten pages explaining it, here is a little example.

Open VB and create a new Standard EXE Project. Click Project, Add Class Module. Repeat this. Also Click Project, References. Select Microsoft DAO 3.51 Object Library. Now you should have two class modules. Rename the first IDataObject and the second CPerson. To the IDataObject add the following code:

Option Explicit

Public IsChanged As Boolean

Public Sub Save()
End Sub
Public Sub GetInfo()
End Sub

Open the second class, CPerson and add the following code:

Option Explicit

Implements IDataObject

Private m_db As Database
Private m_rs As Recordset

Private m_lngID As Long
Private m_strName As String
Private m_strAddress As String
Private m_blnChanged As Boolean

Private Sub Class_Initialize()
Set m_db = OpenDatabase(App.Path & "\people.mdb")
End Sub

Private Sub Class_Terminate()
Set m_rs = Nothing
Set m_db = Nothing
End Sub

Private Sub IDataObject_GetInfo()
If ID = 0 Then
Err.Raise vbObjectError, "CPerson", "A valid ID must be set before
attempting to retrieve data."
End If

Set m_rs = m_db.OpenRecordset("SELECT * FROM People WHERE ID =" & ID)

Name = m_rs.Fields("Name").Value
Address = m_rs.Fields("Address").Value
End Sub

Private Property Let IDataObject_IsChanged(ByVal RHS As Boolean)
m_blnChanged = RHS
End Property

Private Property Get IDataObject_IsChanged() As Boolean
IDataObject_IsChanged = m_blnChanged
End Property

Private Sub IDataObject_Save()
If ID <> 0 Then
End If

m_rs.Fields("Name").Value = Name
m_rs.Fields("Address").Value = Address
End Sub

Public Property Get ID() As Long
ID = m_lngID
End Property

Public Property Let ID(ByVal NewID As Long)
m_lngID = NewID
End Property

Public Property Get Name() As String
Name = m_strName
End Property

Public Property Let Name(ByVal NewName As String)
m_strName = NewName
End Property

Public Property Get Address() As String
Address = m_strAddress
End Property

Public Property Let Address(ByVal NewAddr As String)
m_strAddress = NewAddr
End Property

As you can see we are using a database to store the CPerson information. We have used DAO 3.5 for this although you can modify it to whatever data access you want. Notice that all the methods and properties have been implemented. This is neccessary when implementing an interface otherwise you will run into errors. Take a closer look at the IDataObject_Save method. If the ID is 0, then it is not a current record and therefore a new one needs to be added. Also take a look at the IDataObject_GetInfo method. As with all code in class modules, you should always raise the error and let the module / form / usercontrol handle the error.

The clever bit is now in the form's code. On the form add two command buttons (cmdGet and cmdSave) and a text box (txtName). In the General Declarations procedure declare these two variables:

Private Person As CPerson
Private DataObj As IDataObject

The best code is in the Form_Load procedure. What we are going to do is to create a new instance of the CPerson class, and set the DataObj variable to the new CPerson instance. What this does is it makes both variables point to the same object, that is IDataObject. But Person also points to CPerson. So if you want to interface with the database, use the DataObj variable and if you want to interface with the person information use the Person variable. To demonstrate this, copy the following code into the form:

Private Sub cmdUpdate_Click()

If DataObj.IsChanged Then
Person.ID = 1
Person.Name = txtName
End If

End Sub

Private Sub cmdGet_Click()
Person.ID = 1
txtName = Person.Name
End Sub

Private Sub Form_Load()
Set Person = New CPerson
Set DataObj = Person
DataObj.IsChanged = False
End Sub

Private Sub txtName_Change()
DataObj.IsChanged = True
End Sub

This reads in the first record (cmdGet) into txtName where you can change it (and if you do then it sets the IsChanged flag to True). Then the cmdSave button saves the new name if the IsChanged flag is True.

You can now create multiple classes that implement the IDataObject interface very quickly and easily. Take a look at the example below.

Now that you have made your first COM Interface you will be wanting to look for some more examples. Well, look to http://www.eastwood60.freeserve.co.uk/ and download either version 1 or version 2 of the VBCodeLibrary project. The source code demonstrates how to use DAO 3.5 data access with COM Interfaces and Objects. Take a look, as it should help you out.

That's it from me this time, and I hope you understand COM Interfaces a bit better now. If you have any comments on this article then please email them to me at shugill@domain.softnet.co.uk or drop in on my Visual Basic web site at http://www.vbsquare.com/

Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved