CComCoClass
Revisited
Earlier in this chapter, you saw how deriving
from CComCoClass provided your class with a default
implementation of a class factory, as well as default support for
aggregation.
CComCoClass provides aggregation
support via inheritance of the DECLARE_AGGREGATABLE
macro's typedef of _CreatorClass. It also provides the
default implementation of a class factory via inheritance of the
DECLARE_CLASS_FACTORY macro's
_ClassFactoryCreatorClass typedef.
The Error
Methods
CComCoClass also provides a number of
other useful static methods. Six of the methods are overloaded and
call Error. They set up the COM Error object
using its IErrorInfo interface to provide rich error
information to the client. To call Error, your object must
implement the ISupportErrorInfo interface.
When the hRes parameter is nonzero,
Error returns the value of hRes. When
hRes is zero, the first four versions of Error
return DISP_E_EXCEPTION. The remaining two functions
return the result of the macro MAKE_HRESULT(3, FACILITY_ITF,
nID), creating a custom failure hrESULT.
static HRESULT WINAPI
Error(LPCOLESTR lpszDesc, const IID& iid = GUID_NULL,
HRESULT hRes = 0);
static HRESULT WINAPI
Error(LPCOLESTR lpszDesc, DWORD dwHelpID, LPCOLESTR lpszHelpFile,
const IID& iid = GUID_NULL, HRESULT hRes = 0);
static HRESULT WINAPI
Error(LPCSTR lpszDesc, const IID& iid = GUID_NULL,
HRESULT hRes = 0);
static HRESULT WINAPI
Error(LPCSTR lpszDesc, DWORD dwHelpID, LPCSTR lpszHelpFile,
const IID& iid = GUID_NULL, HRESULT hRes = 0);
static HRESULT WINAPI
Error(UINT nID, const IID& iid = GUID_NULL, HRESULT hRes = 0,
HINSTANCE hInst = _AtlBaseModule.GetResourceInstance());
static HRESULT WINAPI
Error(UINT nID, DWORD dwHelpID, LPCOLESTR lpszHelpFile,
const IID& iid = GUID_NULL, HRESULT hRes = 0,
HINSTANCE hInst = _AtlBaseModule.GetResourceInstance());
It might seem odd that ATL includes the
Error functionality in CComCoClass instead of in
a more widely applicable place, such as CComObjectRootEx.
The reason for this placement is that COM error reporting needs a
CLSID, and the CLSID is stored in CComCoClass. If you need
to generate rich error information when your class isn't derived
from CComCoClass, you can always call the ATL helper
function AtlReportError. The CComCoClass::Error
methods all use this helper function.
inline HRESULT WINAPI AtlReportError(const CLSID& clsid,
UINT nID,
const IID& iid = GUID_NULL,
HRESULT hRes = 0,
HINSTANCE hInst = _AtlBaseModule.GetResourceInstance());
inline HRESULT WINAPI AtlReportError(const CLSID& clsid,
UINT nID, DWORD dwHelpID, LPCOLESTR lpszHelpFile,
const IID& iid = GUID_NULL,
HRESULT hRes = 0,
HINSTANCE hInst = _AtlBaseModule.GetResourceInstance());
inline HRESULT WINAPI AtlReportError(const CLSID& clsid,
LPCSTR lpszDesc,
DWORD dwHelpID, LPCSTR lpszHelpFile,
const IID& iid = GUID_NULL,
HRESULT hRes = 0);
inline HRESULT WINAPI AtlReportError(const CLSID& clsid,
LPCSTR lpszDesc,
const IID& iid = GUID_NULL, HRESULT hRes = 0);
inline HRESULT WINAPI AtlReportError(const CLSID& clsid,
LPCOLESTR lpszDesc,
const IID& iid = GUID_NULL, HRESULT hRes = 0);
inline HRESULT WINAPI AtlReportError(const CLSID& clsid,
LPCOLESTR lpszDesc, DWORD dwHelpID, LPCOLESTR lpszHelpFile,
const IID& iid = GUID_NULL, HRESULT hRes = 0);
The Instantiation
Methods
CComCoClass also
provides two useful overloaded CreateInstance methods that
create an instance of your class, one for creating an aggregated
instance of your class and one that creates a nonaggregated
instance:
template <class Q>
static HRESULT CreateInstance(IUnknown* punkOuter, Q** pp) {
return T::_CreatorClass::CreateInstance(punkOuter, __uuidof(Q),
(void**) pp);
}
template <class Q>
static HRESULT CreateInstance(Q** pp) {
return T::_CreatorClass::CreateInstance(NULL, __uuidof(Q),
(void**) pp);
}
You use these two methods like this.
ISpeaker* pSpeaker;
// Creates non-aggregated instance
HRESULT hr = CDemagogue::CreateInstance (&pSpeaker);
// Creates aggregated instance (assuming the class supports aggregation
HRESULT hr = CDemagogue::CreateInstance (punkOuter, &pSpeaker);
Note that the use of the
__uuidof operator in the template functions means that you
do not have to specify the interface ID for the interface that you
want on the newly instantiated object. The compiler gets the ID
from the type of the interface pointer variable you pass as an
argument to the CreateInstance method.
|