ATL Tutorial
If you are new to ATL ( Active Template Library ) please refer the below items.
In this tutorial we will be creating
-
MathComp which is a DLL or Inproc server and exposes the Add and Sub functions.
-
An MFC Dialog Based Application which acts like a Client for MathComp
Steps for creating MathComp
- Open VS 2008
- File->NewProject Click OK -> Click Next Select Server type: as DLL Select Addition options: as 'Allow merging of proxy/stub code' and click Finish
- Add Component Class
Select ATL simple Object
Enter Short name: "CMath" to add the component class -> Click 'Finish'
Add a Method to ICMath Interface
The classes created are shown below in the class diagram.
CCMath
// CCMath
class ATL_NO_VTABLE CCMath :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CCMath, &CLSID_CMath>,
public IDispatchImpl<ICMath, &IID_ICMath, &LIBID_MathCompLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public :
CCMath()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_CMATH)
BEGIN_COM_MAP(CCMath)
COM_INTERFACE_ENTRY(ICMath)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public :
STDMETHOD(Add)(DOUBLE i, DOUBLE j, DOUBLE* result);
STDMETHOD(Sub)(DOUBLE i, DOUBLE j, DOUBLE* result);
};
OBJECT_ENTRY_AUTO( __uuidof(CMath), CCMath)
CMath.h
// CCMath
STDMETHODIMP CCMath::Add(DOUBLE i, DOUBLE j, DOUBLE* result)
{
*result = i + j;
return S_OK;
}
STDMETHODIMP CCMath::Sub(DOUBLE i, DOUBLE j, DOUBLE* result)
{
*result = i - j;
return S_OK;
}
MathComp.idl
// MathComp.idl : IDL source for MathComp
// This file will be processed by the MIDL tool to
// produce the type library (MathComp.tlb) and marshalling code.
import "oaidl.idl" ;
import "ocidl.idl" ;
[
object ,
uuid (F3BDE3CF-884A-461A-A377-1F96A72239B0),
dual ,
nonextensible ,
helpstring ("ICMath Interface" ),
pointer_default (unique )
]
interface ICMath : IDispatch{
[ id (1), helpstring ( "method Add")] HRESULT Add([ in ] DOUBLE i, [in ] DOUBLE j, [out ] DOUBLE* result);
[ id (2), helpstring ( "method Sub")] HRESULT Sub([ in ] DOUBLE i, [in ] DOUBLE j, [out ] DOUBLE* result);
};
[
uuid (44FF4D78-6AAD-4D2B-9150-DEBCCE79D8E0),
version (1.0),
helpstring ("MathComp 1.0 Type Library" )
]
library MathCompLib
{
importlib ("stdole2.tlb" );
[
uuid (4A8C8314-6C03-4AF7-96A1-9D6052A89363),
helpstring ("CMath Class" )
]
coclass CMath
{
[ default ] interface ICMath;
};
};
NOTE: Other classes are not shown here please Download the source for complete code.
Steps for creating MFC Client
-
Create an MFC Dialog based application
-
Design the Dialog as shown below
-
Add a Add button Handler (OnBnClickedButtonAdd) 4. Inside Add button handler add the below code
//Step1: import include .tlb file
#import "..MathCompMathComp.tlb" no_namespace
void CCMathClientDlg::OnBnClickedButtonAdd()
{
//Step2/////////////// Initialize the COM libraries ///////////////////////////////
CoInitialize(NULL);
//Step3/////////////////////////Retriving CLSID from ProgID///////////////////////
CLSID clsid;
CLSIDFromProgID(OLESTR("MathComp.CMath.1"),&clsid); // will be in CMath.rgs file
//Step4/////////////////////////////Creating instance of server///////////////////
ICMath *pICMath;
HRESULT hr = CoCreateInstance(
clsid, //The CLSID associated with the data and code that will be used to create the object.
NULL, //If NULL, indicates that the object is not being created as part of an aggregate
CLSCTX_LOCAL_SERVER|CLSCTX_INPROC_SERVER, //ontext in which the code that manages the newly created object will run
__uuidof(ICMath), //riid: A reference to the identifier of the interface to be used to communicate with the object.
(LPVOID*)&pICMath); //*ppv: Address of pointer variable that receives the interface pointer requested in riid.
//Upon successful return, *ppv contains the requested interface pointer. Upon failure, *ppv contains NULL.
if (FAILED(hr))
{
AfxMessageBox(_T("ICMath Failed"));
}
//Step5/////////////////////////////Using COM Component//////////////////////////
UpdateData(TRUE);
double res =0;
pICMath->Add(m_i, m_j, &res);
m_Result = res;
pICMath->Release(); // To avoid memory leak
pICMath = NULL;
//Step6////////////////////////////Uninit'ializing the COM libraries//////////////
CoUninitialize();
UpdateData(FALSE);
}