Onega

a lot of VC++ posts, a few C# posts, and some miscellaneous stuff

Monday, November 15, 2004

Use IDispatch interface

Author: Onega(www.fruitfruit.com)
There are two wrappers provided in MSDN, invhelp.cpp implement
HRESULT CreateObject(LPOLESTR pszProgID, IDispatch FAR* FAR* ppdisp);
HRESULT
Invoke(LPDISPATCH pdisp,
WORD wFlags,
LPVARIANT pvRet,
EXCEPINFO FAR* pexcepinfo,
UINT FAR* pnArgErr,
LPOLESTR pszName,
LPCTSTR pszFmt,
...);
But I have problem using it.
So I found another one,
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,
LPOLESTR ptName, int cArgs...);
and extended it to
HRESULT AutoWrapEx(int autoType, VARIANT *pvResult, IDispatch *pDisp,
LPOLESTR ptName,
EXCEPINFO* pexcepinfo,//
UINT* pnum_of_Arg_Error,
int cArgs...);
The problem with its original implementation is that user has to reverse order of arguments passed to IDispatch via AutoWrap. I decide to remove the inconvenience, so my version looks like the following:
//caller is responsible for releasing the incoming VARIANT via VariantClear
HRESULT AutoWrapEx(int autoType, VARIANT *pvResult, IDispatch *pDisp,
LPOLESTR ptName,
EXCEPINFO* pexcepinfo,//
UINT* pnum_of_Arg_Error,
int cArgs...)
{
// Begin variable-argument list...
va_list marker;
va_start(marker, cArgs);

if(!pDisp) {
return E_INVALIDARG;
}
// Variables used...
DISPPARAMS dp = { NULL, NULL, 0, 0 };
DISPID dispidNamed = DISPID_PROPERTYPUT;
DISPID dispID = 0;
HRESULT hr = S_OK;
char buf[200];
// Get DISPID for name passed...
hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT,
&dispID);
if(FAILED(hr)) {
return hr;
}
// Allocate memory for arguments...
VARIANT *pArgs = new VARIANT[cArgs+1];
// Extract arguments...
for(int i=0; i pArgs[cArgs-1-i] = va_arg(marker, VARIANT);//reverse the arg order
}
// Build DISPPARAMS
dp.cArgs = cArgs;
dp.rgvarg = pArgs;
// Handle special-case for property-puts!
if(autoType & DISPATCH_PROPERTYPUT) {
dp.cNamedArgs = 1;
dp.rgdispidNamedArgs = &dispidNamed;
}
// Make the call!
hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType,
&dp, pvResult, pexcepinfo, pnum_of_Arg_Error);
// End variable-argument section...
va_end(marker);
delete [] pArgs;
return hr;
}

Sample usage:
IDispatchPtr pScriptControl(__uuidof(CLSID_ScriptControl));
_variant_t sitewnd((long)this->m_hWnd,VT_I4);
VARIANT ret;
VariantInit(&ret);
hr = AutoWrap(DISPATCH_PROPERTYPUT| DISPATCH_METHOD, NULL,pScriptControl,L"SitehWnd",1,sitewnd);
if(FAILED(hr))
return;
//http://support.microsoft.com/kb/184977/EN-US/
//FIX: ScriptControl Reports Invalid Language for VBScript in MFC
hr = AutoWrap(DISPATCH_PROPERTYPUT| DISPATCH_METHOD, NULL,pScriptControl,L"Language",1,_variant_t(_T("")) );
if(FAILED(hr))
return;
hr = AutoWrap(DISPATCH_PROPERTYPUT| DISPATCH_METHOD, NULL,pScriptControl,L"Language",1,_variant_t(language));
if(FAILED(hr))
return;
hr = AutoWrap(DISPATCH_PROPERTYPUT| DISPATCH_METHOD, NULL,pScriptControl,L"AllowUI",1,_variant_t(VARIANT_TRUE));
if(FAILED(hr))
return;
if(m_pControl && m_pControl->GetControlUnknown())
{
IDispatch* pControl=NULL;
hr = m_pControl->GetControlUnknown()->QueryInterface(IID_IDispatch,(void**)&pControl);
_variant_t name(control_name);
_variant_t obj(pControl);
_variant_t AddMembers( VARIANT_FALSE,VT_BOOL );
hr = AutoWrapEx(DISPATCH_METHOD,
NULL,
pScriptControl,
L"AddObject",
&excepInfo,
&nArgErr,
3,
name,
obj,
AddMembers
);
}
//var d; d = new ActiveXObject("Scripting.Dictionary");
//d.Add( "a" , "Athens" ) ;
//d.Items()
//for jscript
// Create a VARIANT array of VARIANTs which hold BSTRs
//http://support.microsoft.com/kb/165967/EN-US/
//PRB: Script Error Occurs When Referencing Non-variant Array
IDispatchPtr scriptdic(_T("Scripting.Dictionary")); //
if(scriptdic)
{
hr = AutoWrap(DISPATCH_METHOD,NULL,pScriptControl,L"AddObject",3,
_variant_t(_T("jarray")),
_variant_t((IDispatch *)scriptdic.Detach()),
_variant_t(false)
);
}
_variant_t result;
hr = AutoWrapEx(DISPATCH_METHOD, &result,pScriptControl,L"AddCode",&excepInfo,&nArgErr,1,_variant_t(code_start));

0 Comments:

Post a Comment

<< Home