Created
February 22, 2015 08:11
-
-
Save cdecl/eb2ebc97111bcbc70ce6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// COMDispatch.h: interface for the IDispatch class. | |
////////////////////////////////////////////////////////////////////// | |
#ifndef _DISPATCH_H_20011012_BY_CDECL_ | |
#define _DISPATCH_H_20011012_BY_CDECL_ | |
#include <comdef.h> | |
#include <vector> | |
#define BYREF(x) GLASS::COMDispatch::ToRefParam((x)) | |
namespace GLASS { | |
class COMDispatch | |
{ | |
public: | |
typedef std::vector<_variant_t> vec_param; | |
typedef _variant_t PT; | |
// Proxy Class | |
class Proxy | |
{ | |
public: | |
void SetParent(COMDispatch *p) { pDisp_ = p; } | |
void SetPropName(const _bstr_t &bstrName) { bstrName_ = bstrName; } | |
_variant_t operator=(const _variant_t &var) const | |
{ | |
pDisp_->PutProperty(bstrName_, var); | |
return var; | |
} | |
operator _variant_t() const { | |
return pDisp_->GetProperty(bstrName_); | |
} | |
_variant_t operator() () | |
{ | |
vec_param vecParams; | |
return pDisp_->Call(bstrName_, vecParams); | |
} | |
template <typename...VARS> | |
_variant_t operator() (VARS...param) | |
{ | |
vec_param vecParams = Param(param...); | |
return pDisp_->Call(bstrName_, vecParams); | |
} | |
private: | |
template <typename Vartype> | |
vec_param Param(Vartype p) | |
{ | |
vec_param v; | |
v.push_back(p); | |
return std::move(v); | |
} | |
template <typename Vartype, typename...VARS> | |
vec_param Param(Vartype p, VARS...vs) | |
{ | |
vec_param v = Param(vs...); | |
v.push_back(p); | |
return std::move(v); | |
} | |
private: | |
COMDispatch *pDisp_; | |
_bstr_t bstrName_; | |
}; | |
public: | |
COMDispatch() : spDispatch_(NULL) { proxy_.SetParent(this); } | |
COMDispatch(const COMDispatch &disp) : spDispatch_(disp.spDispatch_) { proxy_.SetParent(this); } | |
explicit COMDispatch(const _variant_t &var) : spDispatch_(var) { proxy_.SetParent(this); } | |
COMDispatch(const char *) = delete; | |
COMDispatch(const wchar_t *) = delete; | |
virtual ~COMDispatch() { Release(); } | |
COMDispatch& operator=(const COMDispatch &disp); | |
COMDispatch& operator=(const _variant_t &var); | |
public: | |
_variant_t Call(const _bstr_t &bstrMethodName, vec_param &vecParams); | |
void PutProperty(const _bstr_t &strPropName, const _variant_t &var, bool bRef = false); | |
_variant_t GetProperty(const _bstr_t &strPropName); | |
virtual Proxy& operator[](const _bstr_t &bstrPropName); | |
virtual void CreateObject(const _bstr_t &bstrProgID); | |
virtual void Release(); | |
public: | |
virtual void GetIDsOfNames(const _bstr_t &bstrMethodName, DISPID &lDispID); | |
protected: | |
virtual void Invoke(const DISPID lDispID, vec_param &vecParams, _variant_t &varRetVal, const WORD wFlags = DISPATCH_METHOD); | |
public: | |
static _variant_t ToRefParam(_variant_t &var); | |
protected: | |
Proxy proxy_; | |
IDispatchPtr spDispatch_; | |
}; | |
////////////////////////////////////////////////////////////////////// | |
// Dispatch implementation | |
COMDispatch& COMDispatch::operator=(const COMDispatch &disp) | |
{ | |
if (this != &disp) { | |
spDispatch_ = disp.spDispatch_; | |
proxy_.SetParent(this); | |
} | |
return *this; | |
} | |
COMDispatch& COMDispatch::operator=(const _variant_t &var) | |
{ | |
spDispatch_ = var; | |
proxy_.SetParent(this); | |
return *this; | |
} | |
void COMDispatch::Release() | |
{ | |
if (spDispatch_ != NULL) { | |
spDispatch_.Release(); | |
} | |
} | |
void COMDispatch::CreateObject(const _bstr_t &bstrProgID) | |
{ | |
HRESULT hr = spDispatch_.CreateInstance((LPCSTR)bstrProgID); | |
if (FAILED(hr)) { | |
_com_raise_error(hr); | |
} | |
} | |
_variant_t COMDispatch::Call(const _bstr_t &bstrMethodName, vec_param &vecParams) | |
{ | |
DISPID lDispID; | |
GetIDsOfNames(bstrMethodName, lDispID); | |
_variant_t varRetVal; | |
Invoke(lDispID, vecParams, varRetVal); | |
return varRetVal; | |
} | |
COMDispatch::Proxy& COMDispatch::operator[](const _bstr_t &bstrPropName) | |
{ | |
proxy_.SetPropName(bstrPropName); | |
return proxy_; | |
} | |
void COMDispatch::PutProperty(const _bstr_t &strPropName, const _variant_t &var, bool bRef) | |
{ | |
DISPID lDispID; | |
GetIDsOfNames(strPropName, lDispID); | |
vec_param vecParams; | |
vecParams.push_back(var); | |
_variant_t varRetVal; | |
Invoke(lDispID, vecParams, varRetVal, bRef ? DISPATCH_PROPERTYPUTREF : DISPATCH_PROPERTYPUT); | |
} | |
_variant_t COMDispatch::GetProperty(const _bstr_t &strPropName) | |
{ | |
DISPID lDispID; | |
GetIDsOfNames(strPropName, lDispID); | |
vec_param vecParams; | |
_variant_t varRetVal; | |
Invoke(lDispID, vecParams, varRetVal, DISPATCH_PROPERTYGET); | |
return varRetVal; | |
} | |
void COMDispatch::GetIDsOfNames(const _bstr_t &bstrMethodName, DISPID &lDispID) | |
{ | |
BSTR bstrMN = static_cast<BSTR>(bstrMethodName); | |
HRESULT hr = spDispatch_->GetIDsOfNames(IID_NULL, &bstrMN, 1, LOCALE_SYSTEM_DEFAULT, &lDispID); | |
if (FAILED(hr)) { | |
_com_raise_error(hr); | |
} | |
} | |
void COMDispatch::Invoke(const DISPID lDispID, vec_param &vecParams, _variant_t &varRetVal, const WORD wFlags) | |
{ | |
DISPPARAMS dispparams = { 0 }; | |
DISPID dsipid_put = DISPID_PROPERTYPUT; | |
if (DISPATCH_PROPERTYGET != wFlags) { | |
dispparams.cArgs = vecParams.size(); | |
dispparams.rgvarg = (vecParams.size() == 0) ? NULL : &vecParams.front(); | |
if ((DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF) & wFlags) { | |
dispparams.rgdispidNamedArgs = &dsipid_put; | |
dispparams.cNamedArgs = 1; | |
} | |
} | |
HRESULT hr = spDispatch_->Invoke( | |
lDispID, | |
IID_NULL, | |
LOCALE_USER_DEFAULT, | |
wFlags, | |
&dispparams, | |
DISPATCH_PROPERTYPUT == wFlags ? NULL : &varRetVal, | |
NULL, | |
NULL | |
); | |
if (FAILED(hr)) { | |
_com_raise_error(hr); | |
} | |
} | |
_variant_t COMDispatch::ToRefParam(_variant_t &var) | |
{ | |
_variant_t varRet; | |
varRet.vt = VT_BYREF | VT_VARIANT; | |
varRet.pvarVal = &var; | |
return varRet; | |
} | |
} // end namespace | |
#endif // _DISPATCH_H_20011012_BY_CDECL_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment