[ Home | Syllabus | Course Notes | Assignments | Search]
ATL handles much of the overhead for generating COM objects and is intended primarily for implementing COM servers. Consists of the following:
Create an ATL project using AppWizard
DLL management
Class Factory creation
Register/Unregister COM server
Create a ATL Object using the ATL Object wizard
Interface/Implementation Classes
COM attributes
After following directions on page 129
WritersComponent.cpp
WritersComponent.def: DLL entry points
WritersComponent.idl
WritersComponent.rc: contains registration info (with UUID's already chosen)
DocumentChecker.h
// DocumentChecker.h : Declaration of the CDocumentChecker #ifndef __DOCUMENTCHECKER_H_ #define __DOCUMENTCHECKER_H_ #include "resource.h" // main symbols ///////////////////////////////////////////////////////////////////////////// // CDocumentChecker class ATL_NO_VTABLE CDocumentChecker : // multiple inheritance public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CDocumentChecker, &CLSID_DocumentChecker>, public ISupportErrorInfo, public ISpellChecker { public: CDocumentChecker() { } DECLARE_REGISTRY_RESOURCEID(IDR_DOCUMENTCHECKER)// registry info in this resource ID DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CDocumentChecker) COM_INTERFACE_ENTRY(ISpellChecker) COM_INTERFACE_ENTRY(ISupportErrorInfo) END_COM_MAP() // ISupportsErrorInfo STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid); // ISpellChecker public: }; #endif //__DOCUMENTCHECKER_H_
F1: This class provides the IUnknown interface. It does not assume that the code will be thread safe (because of "Apartment" threading model chosen (by default) when creating the ATL Object
F2: provides the class factory (book calls this the "class object")
F3: Provides a meaningful error message - COM exception object
F4: used by CComObjectRootEx to implement queryinterface - table driven access to the v-table
Need to:
Add to "idl" file
Add to prototype to header file
Add definition to implementation file
Use the "AddMethod" menu in the classview - fill in dialog box info (figure 5.5). Adds the following code to your project
// IDL
interface ISpellChecker : IUnknown { [helpstring("method CheckSpelling")] HRESULT CheckSpelling( [in] LPOLESTR word, [out,retval] VARIANT_BOOL *result); }; [ uuid(9C8DB519-4E59-4E2A-A291-4AC5E712A474), version(1.0), helpstring("WritersComponent 1.0 Type Library") ]
// header file
// ISpellChecker public: STDMETHOD(CheckSpelling)( /*[in]*/ LPOLESTR word, /*[out,retval]*/ VARIANT_BOOL *result); };
// implementation file
STDMETHODIMP CDocumentChecker::CheckSpelling(LPOLESTR word, VARIANT_BOOL *result) { // TODO: Add your implementation code here return S_OK; }
The implementation of this method is almost identical to that for the previous version
A COM "object" can support more
than one interface.
In this example - you may wish to provide a grammar checking interface which
although related to the spelling check interface (because they both provide
tools to writing documents), they could be considered separate objects if you
wished. The decision to provide a second interface to the DocumentChecker Object
vs providing a second COM object is a organizational and packaging
decision. Two interfaces are more tightly coupled since they share a
queryinterface.
Since the wizard does not provide a easy way to add a second interface- you need to edit the "idl" file by hand.
interface ISpellChecker : IUnknown { [helpstring("method CheckSpelling")] HRESULT CheckSpelling([in] LPOLESTR word, [out,retval] VARIANT_BOOL *result); }; [ object, uuid(48B08493-DB68-49fe-8AB7-2DCB56955625), helpstring("IGrammarChecker Interface"), pointer_default(unique) ] interface IGrammarChecker : IUnknown { [helpstring("method CheckGrammar")] HRESULT CheckGrammar( [in] LPOLESTR sentence, [out,retval] VARIANT_BOOL *result); }; // ..... coclass DocumentChecker { [default] interface ISpellChecker; interface IGrammarChecker; }; };
Now you can compile the "idl" file - which will create the type library. Now the wizard can use the type library to assist in implementing this new interface.
Follow directions on page 144. It is worth following the directions for the entire project and see what is produced at each step.
Similar interface built in MFC - but access to the COM object is different. Since we will use visual C++ NATIVE COM support by importing the type library. Notice we are using non-native types (OLESTR, LPOLESTR and VARIANT_BOOL. These types are language independent types.
With the type library you can examine the interface using OLEviewer or other suitable object browser.
By adding an "import" of the type library into "stdafx.h", when the project is built - Visual C++ will use the type library to write "wrapper" classes around the COM interface to make the COM object act like a normal C++ object.