Introduction
During discussion on forums, I come across many people who want to write COM/ATLDLL, but don�t know how to create properties, methods or raise events from Component or strive for fundamental knowledge to create them. In this Article, I am going to write a simple, ATL DLL step by step using VC++ 6.0 and demonstrate creation and usage of property, method and event.
Convention Used
- Symbol �-->� means Author Comments.
- Symbol �|� means Menus Operation, i.e., File|New means clicking new item of File Menu.
Let�s Start
Since I am writing a Beginner Article, I have included as many screen shots to explain the creation of COM DLL and let me explain that to you step by step.
- Open Visual Studio 6.0 and click Menu Item File|NEW to get this Dialog Box.
Fiqure 1: Visual Studio App Wizard |
|
- Now select ATL COM AppWizard and give a project name SimpleAtlCom and click OK to Accept Project Setting, and in next step you will see this dialog box.
Figure 2 ATL/COM App Wizard |
|
- Click Finish to Accept Project Setting.
These above written two steps will create a blank COM DLL project for you.
- Now from menu Insert|NEW ATL Object... , add an ATL object to project. You will see this figure when you click the above menu item.
figure 3:ATL Object Wizard |
|
- Select the Object|Simple object and click Next, then you will see this Property page. Take a view of the following figure.
Figure 4: ATL Object Wizard after selection of SimpleAtl Object. |
|
- Here ( in fig. 4 ) give the Short Name as SimpleObj and you will see other fields in this dialog box get self generated.
Figure 5 :Showing the Attribute of ATL Object |
|
- In fig. 5, let me explain every thing.
- First you see the Threading Model; here I have selected Compiler default which is apartment as most of other applications using our component is comfortable with this model.
- Second you see Interface, again I have selected the Wizard Default to Dual (the benefit of using dual interface is that, you can use it in scripting language also).
- Leave the topics of Aggregation and free thread Marshaler, as they are too advanced to be used in this article.
- Now look at ISupportErrorInfo, this is provided to send rich textual information back to Client Application which is using our Interface. As we are not going to send any Error Information back to Client, I have left this Check Box unchecked.
- Last but not the least, for invoking event from component, you need support of ConnectionPoint Interface. So check the box for supporting the connection point, click OK to Add the Object.
- Now in your project, a new IDL file is added (simpleAtlCom.idl). Here, take a look at IDL file, how�s it look like:
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(10CDF249-A336-406F-B472-20F08660D609),
dual,
helpstring("ISimpleObj Interface"),
pointer_default(unique)
]
interface ISimpleObj : IDispatch
{
};
[
uuid(8B1C3F79-07BA-44F8-8C47-AE2685488DFA),
version(1.0),
helpstring("SimpleAtlCom 1.0 Type Library")
]
library SIMPLEATLCOMLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
uuid(9B5BC0F8-7421-4C46-AA5F-539ECCAFCB82),
helpstring("_ISimpleObjEvents Interface")
]
dispinterface _ISimpleObjEvents
{
properties:
methods:
};
[
uuid(27BF0027-BECC-4847-AF91-99652BCE9791),
helpstring("SimpleObj Class")
]
coclass SimpleObj
{
[default] interface ISimpleObj;
[default, source] dispinterface _ISimpleObjEvents;
};
};
- Now add property and method to our Interface. Let's make a simple application based on class application. Any way, do you know what is a property and a method. If not, here is brief description about them. Method is the name given to a function in interface and property to variable. But remember one thing, every thing in COM/ATL is based on function, one major difference between property and method is that, you can make a property read only (means you can only get data from property but you can�t put them). Now let's get back to our application.
- Now put three methods, both Get and Put and one method in our interface. Now you are going to ask how and where to put them. Right click on your interface. You will get the option for putting both the method and property. For clarity, let's take a look on these pictures.
Figure 6: Showing Popup menu |
Figure 7: Showing Property Wizard |
|
|
- Figure 6 shows you from where you can add the properties and methods to your interface. Now as in figure 7, you can add three properties,
Name
, ATLMarks
and ComMarks
and one method Calculate
and for raising, I will tell you at the end. After adding that, your interface looks like this: interface ISimpleObj : IDispatch
{
[propget, id(1), helpstring("property Name")]
HRESULT Name([out, retval] BSTR *pVal);
[propput, id(1), helpstring("property Name")]
HRESULT Name([in] BSTR newVal);
[propget, id(2), helpstring("property ATLMarks")]
HRESULT ATLMarks([out, retval] short *pVal);
[propput, id(2), helpstring("property ATLMarks")]
HRESULT ATLMarks([in] short newVal);
[propget, id(3), helpstring("property COMMarks")]
HRESULT COMMarks([out, retval] short *pVal);
[propput, id(3), helpstring("property COMMarks")]
HRESULT COMMarks([in] short newVal);
[id(4), helpstring("method Calculate")]
HRESULT Calculate();
};
- Now you will see function for every properties and methods in you class
CSimpleObj
. Before going for actual coding, I think you want to know propget
, propput
and method
in above Interface.
Propget
� stands for property for getting the value from Component.
PropPut
�stands for property for putting property to Component. This can be optional and if you remove it, this can make your property readonly.
Method
�simple function to perform some calculation.
[in]
--- means data is going in or you are putting some value to Component.
[out,retval]
--- notation states that argument using this will return with data.
HRESULT
--- Standard Error reporting variable.
- Now add some useful variables in the class that will take care of above properties. Add
char Name[100]
, short AtlMarks
and short COMMarks
in your CSimpleObj
class and I have coded the rest of the simple class for you. Let's see and explain each function, I have included. One more property viz total
, which will return the total. Still we don�t implement Events.
Here is our SimpleObj
class code.
STDMETHODIMP CSimpleObj::get_Name(BSTR *pVal)
{
CComBSTR bstStr(this->Name);
*pVal=bstStr.Detach();
return S_OK;
}
STDMETHODIMP CSimpleObj::put_Name(BSTR newVal)
{
::wcstombs(this->Name,newVal,99);
return S_OK;
}
STDMETHODIMP CSimpleObj::get_ATLMarks(short *pVal)
{
*pVal=this->ATLMarks;
return S_OK;
}
STDMETHODIMP CSimpleObj::put_ATLMarks(short newVal)
{
this->ATLMarks=newVal;
return S_OK;
}
STDMETHODIMP CSimpleObj::get_COMMarks(short *pVal)
{
*pVal=this->COMMarks;
return S_OK;
}
STDMETHODIMP CSimpleObj::put_COMMarks(short newVal)
{
this->COMMarks=newVal;
return S_OK;
}
STDMETHODIMP CSimpleObj::get_Total(short *pVal)
{
*pVal=this->m_iTotalMarks;
return S_OK;
}
STDMETHODIMP CSimpleObj::Calculate()
{
this->m_iTotalMarks=this->ATLMarks+this->COMMarks;
return S_OK;
}
- Now compile and build the SimpleAtlCom.dll using BUILD|BUILD SimpleATLCom.dll, and I think, you successfully get yourself a SimpleATLCom.dll.
- Now develop a simple Visual Basic Project for it. I have created a sample UI for the above component, let's take a look on it.
Figure 8: Visual Basic Interface for above Com DLL |
|
- Now let's go for coding side, first add reference of our com DLLs to project. You can find option for it in PROJECT|REFRENCES of Visual Basic IDE. After clicking that you will get a dialog box like this, just find our SimpleAtlCom library in it and check the box against it. This will refer that DLL in your project (it is same as including a header file in C++ project) and press OK. This is how the dialog application looks like.
Figure 9 :Reference Dialog Box of Visual Basic IDE |
|
- Now let's look at the backend coding of VB application.
Private Obj As SIMPLEATLCOMLib.SimpleObj
Private Sub cmdPutValue_Click()
Set Obj = New SIMPLEATLCOMLib.SimpleObj
Obj.ATLMarks = txtPutATL
Obj.COMMarks = Me.txtPutCom
Obj.Name = Me.txtPutName
End Sub
Private Sub cmdGetValue_Click()
Obj.Calculate
Me.txtGetAtl = Obj.ATLMarks
Me.txtGetCom = Obj.COMMarks
Me.txtGetName = Obj.Name
Me.txtTotalMarks = Obj.Total
End Sub
- Now before going for events, let's see test running of our application. Here it is:
Figure 10:First Run of Our Com DLL |
|
- I think, till now nobody have faced any problem. I am getting above. Now take a look at events and how to create them and raise them. You can see an Interface name
_ISimpleObjEvents
. This is disinterface created by APP Wizard which provides support for events. You can see a prefix '_' (underscore). This underscore notifies MIDL (Microsoft IDL compiler) that this interface is disinterface and don�t make it part of TLB files. Now right click on this interface and add a method say, Void TOTAL([in]short marks)
as shown in this fiqure:
Figure 11: Adding Method to DisInterface |
|
- Now right Click on your
CSimpleObj
class and click on Implement Connection Point Option. You will see this figure, check on _ISimpleObjEvents
check box and Click OK. Voila! The CProxy_ISimpleObjEvents
class is get added to your project. This is the proxy class that will fire event for you. You can see that, it contains the function VOID Fire_TotalMarks(SHORT TotalMarks)
which is a proxy function and raises events. Oh! I forgot, take a look at the picture for Connection Point implementation.
Fiqure 12: Adding Connection Point |
|
- Now event is added to your class. Let's modify the
CSimpleObj::Calculate()
.
Now new CSimpleObj::Calculate()
looks like this:
STDMETHODIMP CSimpleObj::Calculate()
{
this->m_iTotalMarks=this->ATLMarks + this->COMMarks;
this->Fire_TotalMarks(this->m_iTotalMarks);
return S_OK;
}
- Now let's modify our Visual Basic application to handle events.
Change
Private Obj As SIMPLEATLCOMLib.SimpleObj
to
Private withevents Obj As SIMPLEATLCOMLib.SimpleObj
This helps us to implement events, look this figure for more clarity.
Figure 14:Visual Basic, Adding Event to Project |
|
- Now look at code for implementation of events, as
TotalMarks
comes from event, just add a line to show total marks. So our event code looks like: Private Sub Obj_TotalMarks(ByVal TotalMarks As Integer)
MsgBox "total marks " & TotalMarks
End Sub
- Now test and run the application. Here it is the message box showing the event.
Figure 15: Our Fully Functionable DLL and Application |
|
Download Codes Includes
Source Code Includes
- SimpleAtlCom.dll (with source code).
- Test Project in Visual Basic.
Test Project Includes
- Compiled Test Application.
- Compiled SimpleAtlCom.dll.
Using of Demo Application
If you like, use the Com DLL and Test application first. Don�t forget to register Com DLL i.e., SimpleAtlCom.dll, to your computer. You can use this command line to register the Component.
Drive:> %sys%regsvr32 SimpleAtlCom.dll
Author Comment
I tried my level best to tell each and every simple aspect of com DLL. If it is missing something, feel free to contact me.
Special Thanks
- To My Mother and Father.
- To CodeProject.com providing platform for Programmer Interaction.