📄 atldispa.h
字号:
#if !defined(AFX_ATLDISPA_H__20010608_7B20_BD08_5EED_0080AD509054__INCLUDED_)
#define AFX_ATLDISPA_H__20010608_7B20_BD08_5EED_0080AD509054__INCLUDED_
#pragma once
/////////////////////////////////////////////////////////////////////////////
// atldispa - Dynamic IDispatch handler
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2001-2005 Bjarke Viksoe.
//
// This code may be used in compiled form in any way you desire. This
// source file may be redistributed by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever. It's free, so don't hassle me about it.
//
// Beware of bugs.
//
#ifndef __cplusplus
#error ATL requires C++ compilation (use a .cpp suffix)
#endif
#ifndef __ATLCOM_H__
#error atldispa.h requires atlcom.h to be included first
#endif
/////////////////////////////////////////////////////////////////////////////
// Dynamic IDispatch macros
// Parameter types: by value VTs
#define VTS_EMPTY L"\x00"
#define VTS_I2 L"\x02" // a 'short'
#define VTS_I4 L"\x03" // a 'long'
#define VTS_R4 L"\x04" // a 'float'
#define VTS_R8 L"\x05" // a 'double'
#define VTS_CY L"\x06" // a 'CY'
#define VTS_DATE L"\x07" // a 'DATE'
#define VTS_BSTR L"\x08" // a 'BSTR'
#define VTS_DISPATCH L"\x09" // an 'IDispatch*'
#define VTS_SCODE L"\x0A" // a 'SCODE'
#define VTS_BOOL L"\x0B" // a 'BOOL'
#define VTS_VARIANT L"\x0C" // a 'VARIANT'
#define VTS_UNKNOWN L"\x0D" // an 'IUnknown*'
// Parameter types: by reference VTs
#define VTS_REF_I2 L"\x4002" // a 'short*'
#define VTS_REF_I4 L"\x4003" // a 'long*'
#define VTS_REF_R4 L"\x4004" // a 'float*'
#define VTS_REF_R8 L"\x4005" // a 'double*'
#define VTS_REF_CY L"\x4006" // a 'CY*'
#define VTS_REF_DATE L"\x4007" // a 'DATE*'
#define VTS_REF_BSTR L"\x4008" // a 'BSTR*'
#define VTS_REF_DISPATCH L"\x4009" // an 'IDispatch**'
#define VTS_REF_SCODE L"\x400A" // a 'SCODE*'
#define VTS_REF_BOOL L"\x400B" // a 'VARIANT_BOOL*'
#define VTS_REF_VARIANT L"\x400C" // a 'VARIANT*'
#define VTS_REF_UNKNOWN L"\x400D" // an 'IUnknown**'
template< class T >
struct _ATL_DISPATCH_ENTRY
{
OLECHAR *szName;
DISPID dispid;
UINT wFlags;
VARTYPE vtReturn;
UINT nArgs;
LPCWSTR vtArgs;
VARTYPE vtSingle;
void (__stdcall T::*pfn)();
};
#define BEGIN_DISPATCH_MAP(theClass) \
static const _ATL_DISPATCH_ENTRY<theClass>* _GetDispMap()\
{\
typedef theClass _atl_disp_classtype;\
static const _ATL_DISPATCH_ENTRY<_atl_disp_classtype> _dispmap[] = {
#define DISP_METHOD_ID(func, dispid, vtRet, nCnt, vtArgs) \
{ OLESTR(#func), dispid, DISPATCH_METHOD, vtRet, nCnt, { vtArgs }, VT_EMPTY, (void (__stdcall _atl_disp_classtype::*)())func },
#define DISP_METHOD(func, vtRet, nCnt, vtArgs) \
DISP_METHOD_ID(func, DISPID_UNKNOWN, vtRet, nCnt, vtArgs)
#define DISP_METHOD0_ID(func, dispid, vtRet) \
{ OLESTR(#func), dispid, DISPATCH_METHOD, vtRet, 0, { VTS_EMPTY }, VT_EMPTY, (void (__stdcall _atl_disp_classtype::*)())func },
#define DISP_METHOD0(func, vtRet) \
DISP_METHOD0_ID(func, DISPID_UNKNOWN, vtRet)
#define DISP_METHOD1_ID(func, dispid, vtRet, vtArg) \
{ OLESTR(#func), dispid, DISPATCH_METHOD, vtRet, 1, NULL, vtArg, (void (__stdcall _atl_disp_classtype::*)())func },
#define DISP_METHOD1(func, vtRet, vtArg) \
DISP_METHOD1_ID(func, DISPID_UNKNOWN, vtRet, vtArg)
#define DISP_PROP_ID(member, dispid, vt) \
{ OLESTR(#member), dispid, DISPATCH_PROPERTYGET, vt, 0, { VTS_EMPTY }, VT_EMPTY, (void (__stdcall _atl_disp_classtype::*)())get_##member }, \
{ OLESTR(#member), DISPID_PROPERTYPUT, DISPATCH_PROPERTYPUT, VT_EMPTY, 1, NULL, vt, (void (__stdcall _atl_disp_classtype::*)())put_##member },
#define DISP_PROP(member, vt) \
DISP_PROP_ID(member, DISPID_UNKNOWN, vt)
#define DISP_PROPGET_ID(member, dispid, vt) \
{ OLESTR(#member), dispid, DISPATCH_PROPERTYGET, vt, 0, { VTS_EMPTY }, VT_EMPTY, (void (__stdcall _atl_disp_classtype::*)())get_##member },
#define DISP_PROPGET(member, vt) \
DISP_PROPGET_ID(member, DISPID_UNKNOWN, vt)
#define DISP_PROPPUT_ID(member, dispid, vt) \
{ OLESTR(#member), dispid, DISPATCH_PROPERTYPUT, VT_EMPTY, 1, NULL, vt, (void (__stdcall _atl_disp_classtype::*)())put_##member },
#define DISP_PROPPUT(member, vt) \
DISP_PROPPUT_ID(member, DISPID_UNKNOWN, vt)
#define END_DISPATCH_MAP() {0}}; return _dispmap;}
/////////////////////////////////////////////////////////////////////////////
// IDispDynImpl
template< class T, const IID* pdiid = &IID_NULL >
class ATL_NO_VTABLE IDispDynImpl : public IDispatch
{
public:
IDispDynImpl()
{
}
// These are here only to support use in non-COM objects
STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject)
{
// NOTE: If compile errors occour at this location,
// add/remove the "ATL::" namespace qualifiers in front
// of the InlineIsEqualGUID() methods below.
// This is due to a problem in old MS Platform SDK releases.
if( ATL::InlineIsEqualGUID(riid, *pdiid) ||
InlineIsEqualUnknown(riid) ||
ATL::InlineIsEqualGUID(riid, IID_IDispatch) )
{
if( ppvObject==NULL ) return E_POINTER;
*ppvObject = this;
AddRef();
#ifdef _ATL_DEBUG_INTERFACES
_Module.AddThunk((IUnknown**)ppvObject, _T("IDispDynImpl"), riid);
#endif // _ATL_DEBUG_INTERFACES
return S_OK;
}
else {
return E_NOINTERFACE;
}
}
virtual ULONG STDMETHODCALLTYPE AddRef()
{
return 1;
}
virtual ULONG STDMETHODCALLTYPE Release()
{
return 1;
}
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
{
*pctinfo = 0;
return S_OK;
}
STDMETHOD(GetTypeInfo)(UINT /*itinfo*/, LCID /*lcid*/, ITypeInfo** /*pptinfo*/)
{
return E_NOTIMPL;
}
STDMETHOD(GetIDsOfNames)(REFIID /*riid*/, LPOLESTR* rgszNames, UINT cNames, LCID /*lcid*/, DISPID* rgdispid)
{
HRESULT Hr = S_OK;
for( UINT i=0; i<cNames; i++ ) {
const _ATL_DISPATCH_ENTRY<T>* pMap = T::_GetDispMap();
DISPID dispid = 1;
while( pMap->pfn!=NULL ) {
if( ::lstrcmpiW(pMap->szName, rgszNames[i])==0 ) {
rgdispid[i] = pMap->dispid==DISPID_UNKNOWN ? dispid : pMap->dispid;
break;
}
dispid++;
pMap++;
}
if( pMap->pfn==NULL ) {
rgdispid[i] = DISPID_UNKNOWN;
Hr = DISP_E_UNKNOWNNAME;
}
}
return Hr;
}
STDMETHOD(Invoke)(DISPID dispidMember, REFIID /*riid*/,
LCID /*lcid*/, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* /*pexcepinfo*/, UINT* /*puArgErr*/)
{
if( (DISPATCH_PROPERTYPUT!=wFlags) && (pdispparams->cNamedArgs>0) ) return DISP_E_NONAMEDARGS;
const _ATL_DISPATCH_ENTRY<T>* pMap = T::_GetDispMap();
DISPID i = 1;
while( pMap->pfn!=NULL ) {
DISPID dispid = pMap->dispid==DISPID_UNKNOWN ? i : pMap->dispid;
if( dispidMember==dispid ) {
if( (DISPATCH_PROPERTYPUT==wFlags) && (DISPID_PROPERTYPUT==(pMap+1)->dispid) )
pMap++;
VARTYPE* pArgs = (VARTYPE*) pMap->vtArgs;
if( pArgs == NULL ) pArgs = (VARTYPE*) &pMap->vtSingle;
UINT nArgs = pMap->nArgs;
if( pdispparams->cArgs != nArgs ) return DISP_E_BADPARAMCOUNT;
VARIANTARG** ppVarArgs = nArgs ? (VARIANTARG**)_alloca(sizeof(VARIANTARG*)*nArgs) : NULL;
VARIANTARG* pVarArgs = nArgs ? (VARIANTARG*)_alloca(sizeof(VARIANTARG)*nArgs) : NULL;
UINT i;
for( i=0; i<nArgs; i++ ) {
ppVarArgs[i] = &pVarArgs[i];
::VariantInit(&pVarArgs[i]);
if( FAILED(::VariantCopyInd(&pVarArgs[i], &pdispparams->rgvarg[nArgs-i-1])) ) return DISP_E_TYPEMISMATCH;
if( FAILED(::VariantChangeType(&pVarArgs[i], &pVarArgs[i], 0, pArgs[i])) ) return DISP_E_TYPEMISMATCH;
}
T *pT = static_cast<T*>(this);
CComStdCallThunk<T> thunk;
thunk.Init(pMap->pfn, pT);
CComVariant tmpResult;
if( pvarResult==NULL ) pvarResult = &tmpResult;
HRESULT Hr = ::DispCallFunc(
&thunk,
0,
CC_STDCALL,
pMap->vtReturn,
nArgs,
pArgs,
nArgs ? ppVarArgs : NULL,
pvarResult);
for( i=0; i<nArgs; i++ ) ::VariantClear(&pVarArgs[i]);
return Hr;
}
i++;
pMap++;
}
return DISP_E_MEMBERNOTFOUND;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -