//+--------------------------------------------------------------------------- // // 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 // // 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 // #pragma once #ifndef INC_DISPIMPL2 #define INC_DISPIMPL2 ///////////////////////////////////////////////////////////////////////////// // IDelegatingDispImpl template 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(static_cast(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 IDelegatingDispImpl::_tihclass IDelegatingDispImpl::_tih = { piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0 }; #endif // INC_DISPIMPL2