📄 utilcls.h
字号:
OLECHECK(src->QueryInterface(GetIID(), (LPVOID*)(&intf)));
}
return *this;
}
#if defined(SYSTOBJ_H)
template <class I>
TComInterface<T, piid>& operator=(const DelphiInterface<I>& src)
{
_ASSERTE_(/* Need have valid IID to invoke this */GetIID() != GUID_NULL);
Reset();
if (src)
{
OLECHECK(src->QueryInterface(GetIID(), (LPVOID*)(&intf)));
}
return *this;
}
#endif
TComInterface<T, piid>& operator=(const TComInterface<T, piid>& src)
{
if (src.intf != 0)
src.intf->AddRef();
Reset(src.intf);
return *this;
}
bool operator ! () const { return (intf == 0); }
operator bool () const { return (intf != 0); }
bool IsBound () const { return !!(*this); }
HRESULT CreateInstance(const CLSID& clsid, IUnknown* pOuter = 0, DWORD dwClsContext = CLSCTX_ALL);
HRESULT CreateInstance(LPOLESTR progid, IUnknown* pOuter = 0, DWORD dwClsContext = CLSCTX_ALL);
public:
__property IID iid = { read = GetIID };
protected:
T* intf;
};
// Create instance of interface via 'CoCreateInstance' with specified CLSID
//
template <class T, const IID* piid>
HRESULT TComInterface<T, piid>::CreateInstance(const CLSID& clsid, IUnknown* pOuter, DWORD dwClsContext)
{
Reset(); // Free any interface pointers
IUnknownPtr punk;
HRESULT hr = ::CoCreateInstance(clsid, pOuter, dwClsContext, IID_IUnknown, reinterpret_cast<LPVOID*>(&punk));
if (SUCCEEDED(hr))
{
hr = ::OleRun(punk);
if (SUCCEEDED(hr))
hr = punk->QueryInterface(GetIID(), reinterpret_cast<LPVOID*>(&intf));
}
return hr;
}
// Create instance of interface via 'CoCreateInstance' with specified progid
//
template <class T, const IID* piid>
HRESULT TComInterface<T, piid>::CreateInstance(LPOLESTR progid, IUnknown* pOuter, DWORD dwClsContext)
{
CLSID clsid;
HRESULT hr = ::CLSIDFromString(progid, &clsid);
if (SUCCEEDED(hr))
return CreateInstance(clsid, pOuter, dwClsContext);
return hr;
}
// Macro used to create typedefs of smart pointers for interfaces.
// Use this macro to create typedefs for standard interfaces not already
// typedefed.
//
#if !defined(_DEF_SMARTPTR)
#define _DEF_SMARTPTR(intf) class intf; typedef TComInterface<intf> intf ## Ptr
#define _DEF_SMARTPTR_IID(intf, iid) class intf; typedef TComInterface<intf, &iid> intf ## Ptr
#endif
// Typedefs for StdVCL interfaces
//
namespace Stdvcl
{class IStrings; class IStringsDisp; class IProvider; class IProviderDisp; class IDataBroker; class IDataBrokerDisp;}
typedef TComInterface<Stdvcl::IStrings /*,&IID_Istrings */> IStringsPtr;
typedef TComInterface<Stdvcl::IStringsDisp /*,&IID_IStringsDisp*/> IStringsDispPtr;
typedef TComInterface<Stdvcl::IProvider /*,&IID_IProvider */> IProviderPtr;
typedef TComInterface<Stdvcl::IProviderDisp /*,&IID_IProviderDisp*/> IProviderDispPtr;
typedef TComInterface<Stdvcl::IDataBroker /*,&IID_IDataBroker */> IDataBrokerPtr;
typedef TComInterface<Stdvcl::IDataBrokerDisp /*,&IID_IDataBrokerDisp*/> IDataBrokerDispPtr;
extern "C" const IID IID_IFont;
extern "C" const IID IID_IPicture;
extern "C" const IID IID_IFontDisp;
extern "C" const IID IID_IPictureDisp;
extern "C" const IID CLSID_StdFont;
extern "C" const IID CLSID_StdPicture;
_DEF_SMARTPTR_IID(IUnknown, IID_IUnknown);
_DEF_SMARTPTR_IID(IDispatch, IID_IDispatch);
_DEF_SMARTPTR_IID(IFont, IID_IFont);
_DEF_SMARTPTR_IID(IPicture, IID_IPicture);
_DEF_SMARTPTR_IID(IFontDisp, IID_IFontDisp);
_DEF_SMARTPTR_IID(IPictureDisp, IID_IPictureDisp);
_DEF_SMARTPTR_IID(IEnumVARIANT, IID_IEnumVARIANT);
typedef IUnknownPtr TCOMIUnknown; /* Backwards compatibility */
typedef IDispatchPtr TCOMIDispatch; /* Backwards compatibility */
// Template used to expose 'factory-like' Create/CreateRemote routines for Clients
//
template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
class TCoClassCreatorT : public CoClassCreator
{
public:
static TOBJ Create();
static HRESULT Create(TOBJ& intfObj);
static HRESULT Create(INTF** ppintf);
static TOBJ CreateRemote(LPCWSTR machineName);
static HRESULT CreateRemote(LPCWSTR machineName, TOBJ& intfObj);
static HRESULT CreateRemote(LPCWSTR machineName, INTF** ppIntf);
};
template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
TOBJ TCoClassCreatorT<TOBJ, INTF, clsid, iid>::Create()
{
TOBJ intfObj;
OLECHECK(Create(intfObj));
return intfObj;
}
template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::Create(TOBJ& intfObj)
{
return Create(&intfObj);
}
template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::Create(INTF **ppIntf)
{
return CoCreateInstance(*clsid, *iid, reinterpret_cast<LPVOID*>(ppIntf));
}
template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
TOBJ TCoClassCreatorT<TOBJ, INTF, clsid, iid>::CreateRemote(LPCWSTR machineName)
{
TOBJ intfObj;
OLECHECK(CreateRemote(machineName, intfObj));
return intfObj;
}
template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::CreateRemote(LPCWSTR machineName, INTF **ppIntf)
{
return CoClassCreator::CreateRemote(machineName, *clsid,*iid, ppIntf);
}
template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::CreateRemote(LPCWSTR machineName, TOBJ& intfObj)
{
return CreateRemote(machineName, &intfObj);
}
// Helper class for cases where VARIANT* or VARIANT& is expected for optional parameters
//
class TNoParam
{
public:
TNoParam()
{
m_Variant.vt = VT_ERROR;
V_ERROR(&m_Variant) = DISP_E_PARAMNOTFOUND;
}
operator VARIANT* () { return &m_Variant;}
operator VARIANT& () { return m_Variant; }
operator TVariant* () { return &m_Variant;}
operator TVariant& () { return m_Variant; }
private:
TVariant m_Variant;
};
// Helper class for default LOCALE values
//
class TDefLCID
{
public:
TDefLCID(LCID lcid = LOCALE_SYSTEM_DEFAULT) : m_Lcid(lcid) {}
operator LCID () const { return m_Lcid; }
protected:
LCID m_Lcid;
};
// Base class that exposes basic behaviour of our array of Variants
//
class TAutoArgsBase
{
protected:
TAutoArgsBase(VARIANTOBJ *pVariant, int count) : m_Variant(pVariant), m_Count(count)
{}
public:
VARIANTOBJ& operator[](int index) const
{
// NOTE: It's OK to use Count - there's an extra Variant for return result
// Zero'th entry's reserved for return value.
//
_ASSERTE_(index <= m_Count);
_ASSERTE_(index >= 0);
// Make up for C++ vs. Basic reverse indexing
//
return m_Variant[index ? (m_Count+1-index) : 0];
}
VARIANT* GetRetVal() const
{
return &m_Variant[0];
}
VARIANTOBJ& GetRetVariant()
{
return *m_Variant;
}
VARIANT* GetArgs() const
{
return (VARIANT*)(m_Variant+1);
}
int GetCount() const
{
return m_Count;
}
private:
TAutoArgsBase(const TAutoArgsBase&);
TAutoArgsBase& operator=(const TAutoArgsBase&);
VARIANTOBJ *m_Variant;
int m_Count;
};
// TAutoArgs - Encapsulates array of Variants. Use for Invoke calls
//
template <int Count>
class TAutoArgs : public TAutoArgsBase
{
public:
TAutoArgs();
~TAutoArgs();
private:
// Allocate an extra Variant. It's the first entry and
// it is reserved for return result. The rest are for parameters
//
VARIANTOBJ m_Array[Count+1];
};
// Build an array of Count (actualy Count+1, extra one for return value)
// of VARIANTs.
//
template <int Count>
TAutoArgs<Count>::TAutoArgs() : TAutoArgsBase(m_Array, Count)
{}
// Cleanup array of Variants
//
template <int Count>
TAutoArgs<Count>::~TAutoArgs()
{}
// Enumeration describing DISPATCH type
//
enum DispatchFlag
{
dfMethod = DISPATCH_METHOD,
dfPropGet = DISPATCH_PROPERTYGET,
dfPropPut = DISPATCH_PROPERTYPUT,
dfPropPutRef= DISPATCH_PROPERTYPUTREF
};
// Sets the value in the returnVariant to the retVal variable if SUCCEEDED(hr)
// Used by DispInterface Code Generated by TLIBIMP
//
template <class T>
HRESULT OutRetValSetterPtr(T* retVal, TAutoArgsBase& args, HRESULT hr)
{
if (SUCCEEDED(hr))
*retVal = T(args.GetRetVariant());
return hr;
}
// Sets the value in the returnVariant to the retVal variable if SUCCEEDED(hr)
// Used by DispInterface Code Generated by TLIBIMP
template <class T>
HRESULT OutRetValSetterRef(T& retVal, TAutoArgsBase& args, HRESULT hr)
{
if (SUCCEEDED(hr))
retVal = T(args.GetRetVariant());
return hr;
}
// (Dummy) Component Fake class
// (This class and the TDispatchDelegate template allows the TEventsDispatcher class to be used for
// generic [non-VCL, Component, Form-based] event dispatching, as well as be the base class of a
// Form-based component. The difficulties stem from the [f]rigid rules of VCL classes: no multiple
// inheritance... not even interfaces (Delphi allow these at least but the C++ side is more Delphiesque
// than Delphi). In order not to duplicate code in two templates, we'll use some dummy classes that
// remove IDispatch as a base class [since it can't be a base if TComponent is a base class] and allows
// for a TComponent-derived based class).
//
class TFakeComponentBase
{
public:
TFakeComponentBase() {}
TFakeComponentBase(TFakeComponentBase*) {}
};
// Template to delegate implementation of IDispatch to T
// (To work around not allowing MI in VCL class hierarchy - Compiler should allow interfaces but doesn't - BUG??)
//
template <class T>
class TDispatchDelegate : public IDispatch
{
T& m_DispImpl;
public:
TDispatchDelegate(T& impl) : m_DispImpl(impl) {}
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) { return m_DispImpl.QueryInterface(iid, ppvObject); }
ULONG STDMETHODCALLTYPE AddRef() { return m_DispImpl.AddRef(); }
ULONG STDMETHODCALLTYPE Release() { return m_DispImpl.Release(); }
// IDispatch
// IDispatch
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctInfo)
{
*pctInfo = 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT, LCID, ITypeInfo** ppTypeInfo)
{
*ppTypeInfo = 0;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID, LPOLESTR*, UINT, LCID, DISPID*)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispid, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgError)
{
return m_DispImpl.Invoke(dispid, iid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgError);
}
};
// TEventDispatcher<>
// ==================
//
// TEventDispatcher<> offer a simple sink implementation: i.e. an implementation of IDispatch that servers
// can call upon to fire events. The template also exposes routines to allow one to easy connect to and
// disconnect the sink from a Server.
//
template <class T, const IID *pEVENTSIID, class BASE = TFakeComponentBase>
class TEventDispatcher : public BASE
{
typedef TEventDispatcher<T, pEVENTSIID, BASE> ThisClass;
int m_Ref; // Ref count holder
DWORD m_EventCookie; // Event Advise/Unadvise cookie
TDispatchDelegate<ThisClass> m_Dispatch; // IDispatch implementation
protected:
// To be overriden in derived class to dispatch events
virtual HRESULT InvokeEvent(DISPID id, TVariant* params = 0) = 0;
public:
TEventDispatcher() : m_Ref(0), m_EventCookie(0), m_Dispatch(*this)
{}
TEventDispatcher(BASE* owner) : BASE(owner), m_Ref(0), m_EventCookie(0), m_Dispatch(*this)
{}
// COnnect Event IDispatch to Server
HRESULT ConnectEvents(IUnknown *server);
HRESULT DisconnectEvents(IUnknown *server);
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef() { return ++m_Ref; }
ULONG STDMETHODCALLTYPE Release() { return --m_Ref; }
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispid, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgError);
};
// TEventsDispatcher::IUnknown::QueryInterface
//
template <class T, const IID *pEVENTSIID, class BASE> HRESULT STDMETHODCALLTYPE
TEventDispatcher<T, pEVENTSIID, BASE>::QueryInterface(REFIID iid, void **ppvObject)
{
*ppvObject = 0;
if ((iid == IID_IDispatch) || (iid == *pEVENTSIID))
{
/*static_cast<T*>*/(this)->AddRef();
*ppvObject = static_cast<IDispatch*>(&m_Dispatch);
}
else if (iid == IID_IUnknown)
{
/*static_cast<T*>*/(this)->AddRef();
*ppvObject = static_cast<IUnknown*>(&m_Dispatch);
}
else
return E_NOINTERFACE;
return S_OK;
}
// TEventsDispatcher::ConnectEvents
//
template <class T, const IID *pEVENTSIID, class BASE> HRESULT
TEventDispatcher<T, pEVENTSIID, BASE>::ConnectEvents(IUnknown* pServer)
{
HRESULT hr = E_NOINTERFACE;
TComInterface<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC;
pCPC = pServer;
if (pCPC)
{
TComInterface<IConnectionPoint, &IID_IConnectionPoint> pCP;
hr = pCPC->FindConnectionPoint(*pEVENTSIID, &pCP);
if (SUCCEEDED(hr))
if (pCP)
hr = pCP->Advise(static_cast<IUnknown*>(&m_Dispatch), &m_EventCookie);
}
return hr;
}
// TEventsDispatcher::DisconnectEvents
//
template <class T, const IID *pEVENTSIID, class BASE> HRESULT
TEventDispatcher<T, pEVENTSIID, BASE>::DisconnectEvents(IUnknown* pServer)
{
if (m_EventCookie == 0)
return CONNECT_E_NOCONNECTION;
HRESULT hr = E_NOINTERFACE;
TComInterface<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC;
pCPC = pServer;
if (pCPC)
{
TComInterface<IConnectionPoint, &IID_IConnectionPoint> pCP;
hr = pCPC->FindConnectionPoint(*pEVENTSIID, &pCP);
if (SUCCEEDED(hr))
if (pCP)
hr = pCP->Unadvise(m_EventCookie);
if (SUCCEEDED(hr))
m_EventCookie = 0;
}
return hr;
}
// TEventsDispatcher::IDispatch::Invoke
//
template <class T, const IID *pEVENTSIID, class BASE> HRESULT STDMETHODCALLTYPE
TEventDispatcher<T, pEVENTSIID, BASE>::Invoke(DISPID dispid, REFIID /*iid*/, LCID /*lcid*/,
WORD /*wFlags*/, DISPPARAMS* pDispParams,
VARIANT* /*pVarResult*/, EXCEPINFO* /*pExcepInfo*/,
UINT* /*puArgError*/)
{
TAPtr<TVariant> pParamArray;
TVariant *pArrayPtr = 0;
if (pDispParams->cArgs)
{
int count = pDispParams->cArgs;
pParamArray = new TVariant[count];
// NOTE: row vs. column major!
for (UINT i=0; i<pDispParams->cArgs; i++)
pParamArray[count-(i+1)] = pDispParams->rgvarg[i];
pArrayPtr = pParamArray;
}
return InvokeEvent(dispid, pArrayPtr);
};
// If you want to access the following template you must make sure that CLASSES.HPP
// has been included before UTILCLS.H is included.
//
#if defined(ClassesHPP)
// Declare a macro so we may check if the headers were properly included
//
#define __BASE_OF_COMOBJECT_AS_COMPONENT_DEFINED
// TComponnentofCOMObjectWithEvents<
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -