131 lines
4.3 KiB
C
131 lines
4.3 KiB
C
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 2000.
|
||
|
//
|
||
|
// File: D I S P I M P L 2 . H
|
||
|
//
|
||
|
// Contents: Implementation of IDispatch without dual interfaces
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// Author: mbend 26 Sep 2000
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
// -IDelegatingDispImpl for implementing IDispatch by delegation
|
||
|
// to another interface (typically a custom interface).
|
||
|
//
|
||
|
// These classes are useful because ATL's IDispatchImpl can
|
||
|
// only implement duals.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// IDelegatingDispImpl: For implementing IDispatch in terms of another
|
||
|
// (typically custom) interface, e.g.:
|
||
|
//
|
||
|
// [oleautomation]
|
||
|
// interface IFoo : IUnknown
|
||
|
// {
|
||
|
// ...
|
||
|
// }
|
||
|
//
|
||
|
// IDelegatingDispImpl implements all four IDispatch methods.
|
||
|
// IDelegatingDispImpl gets the IDispatch vtbl entries by deriving from
|
||
|
// IDispatch in addition to the implementation interface.
|
||
|
//
|
||
|
// Usage:
|
||
|
// class CFoo : ..., public IDelegatingDispImpl<IFoo>
|
||
|
//
|
||
|
// In the case where the coclass is intended to represent a control,
|
||
|
// there is a need for the coclass to have a [default] dispinterface.
|
||
|
// Otherwise, some control containers (notably VB) throw arcane error when
|
||
|
// the control is loaded. For a control that you intend to provide the
|
||
|
// custom interface and delegating dispatch mechanism, you will have to
|
||
|
// provide a dispinterface defined in terms of a custom interface like
|
||
|
// so:
|
||
|
//
|
||
|
// dispinterface DFoo
|
||
|
// {
|
||
|
// interface IFoo;
|
||
|
// }
|
||
|
//
|
||
|
// coclass Foo
|
||
|
// {
|
||
|
// [default] interface DFoo;
|
||
|
// interface IFoo;
|
||
|
// };
|
||
|
//
|
||
|
// For every other situation, declaring a dispinterface in terms of a
|
||
|
// custom interface is not necessary to use IDelegatingDispatchImpl.
|
||
|
// However, if you'd like DFoo to be in the base class list (as needed
|
||
|
// for the caveat control), you may use DFoo as the base class instead
|
||
|
// of the default template argument IDispatch like so:
|
||
|
//
|
||
|
// Usage:
|
||
|
// class CFoo : ..., public IDelegatingDispImpl<IFoo, &IID_IFoo, DFoo>
|
||
|
//
|
||
|
|
||
|
#pragma once
|
||
|
#ifndef INC_DISPIMPL2
|
||
|
#define INC_DISPIMPL2
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// IDelegatingDispImpl
|
||
|
|
||
|
template <class T, const IID* piid = &__uuidof(T), class D = IDispatch,
|
||
|
const GUID* plibid = &CComModule::m_libid, WORD wMajor = 1,
|
||
|
WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
|
||
|
class ATL_NO_VTABLE IDelegatingDispImpl : public T, public D
|
||
|
{
|
||
|
public:
|
||
|
typedef tihclass _tihclass;
|
||
|
|
||
|
// IDispatch
|
||
|
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
|
||
|
{
|
||
|
*pctinfo = 1;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
|
||
|
{
|
||
|
return _tih.GetTypeInfo(itinfo, lcid, pptinfo);
|
||
|
}
|
||
|
|
||
|
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
|
||
|
LCID lcid, DISPID* rgdispid)
|
||
|
{
|
||
|
return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
|
||
|
}
|
||
|
|
||
|
STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
|
||
|
LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
|
||
|
EXCEPINFO* pexcepinfo, UINT* puArgErr)
|
||
|
{
|
||
|
// NOTE: reinterpret_cast because CComTypeInfoHolder makes the mistaken
|
||
|
// assumption that the typeinfo can only Invoke using an IDispatch*.
|
||
|
// Since the implementation only passes the itf onto
|
||
|
// ITypeInfo::Invoke (which takes a void*), this is a safe cast
|
||
|
// until the ATL team fixes CComTypeInfoHolder.
|
||
|
return _tih.Invoke(reinterpret_cast<IDispatch*>(static_cast<T*>(this)),
|
||
|
dispidMember, riid, lcid, wFlags, pdispparams,
|
||
|
pvarResult, pexcepinfo, puArgErr);
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
static _tihclass _tih;
|
||
|
|
||
|
static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
|
||
|
{
|
||
|
return _tih.GetTI(lcid, ppInfo);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <class T, const IID* piid, class D, const GUID* plibid, WORD wMajor, WORD wMinor, class tihclass>
|
||
|
IDelegatingDispImpl<T, piid, D, plibid, wMajor, wMinor, tihclass>::_tihclass
|
||
|
IDelegatingDispImpl<T, piid, D, plibid, wMajor, wMinor, tihclass>::_tih =
|
||
|
{ piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0 };
|
||
|
|
||
|
#endif // INC_DISPIMPL2
|