描述:
脚本中传来的函数指针是LPDISPATCH,如果直接用ChangeType转为String,得到的结果是包含函数代码在内的整个函数而不是函数名[即便能通过分析来获得...],请问我要如何能够通过这个Dispatch指针来调用这个函数呢?
难道只能生成一个调用字符串插入执行吗?
解决方案1:
函数对象用DISPID=0来调用。
pObj->Invoke(0,IID_NULL,0,DISPATCH_METHOD,&Params,&result,NULL,NULL);
通过GetTypeInfo可以获得类型信息
参见http://www.csdn.net/develop/read_article.asp?id=21702
HRESULT CIEAutomationView::DumpTypeInfo(LPDISPATCH pDisp)
{
if(pDisp==NULL)return OLE_E_BLANK;
CComPtr<ITypeInfo> pTypeInfo;
HRESULT hr = S_OK;
hr= pDisp->GetTypeInfo(0, GetUserDefaultLCID(), &pTypeInfo);
if(FAILED(hr))return hr;
CSmartTypeAttr pTypeAttr( pTypeInfo );
CSmartFuncDesc pFuncDesc( pTypeInfo );
hr= pTypeInfo->GetTypeAttr( &pTypeAttr );
if(FAILED(hr))return hr;
for(int iMethod = 0; iMethod < pTypeAttr->cFuncs; iMethod++){
hr= pTypeInfo->GetFuncDesc(iMethod, &pFuncDesc);
if(FAILED(hr))return hr;
CString strInvokeType;
switch(pFuncDesc->invkind){
case INVOKE_FUNC :strInvokeType="Function";break;
case INVOKE_PROPERTYGET :strInvokeType="Property(Get)";break;
case INVOKE_PROPERTYPUT :strInvokeType="Property(Put)";break;
case INVOKE_PROPERTYPUTREF:strInvokeType="Property(Putref)";break;
default:break;
}
CComBSTR bstrName;
unsigned int nNames;
hr= pTypeInfo->GetNames(pFuncDesc->memid, &bstrName, 1,&nNames );
if(FAILED(hr))return hr;
ASSERT( nNames == 1 );
TRACE("%s\t%s\r\n",CString(bstrName.m_str),strInvokeType);
pFuncDesc.Release();
}
return S_OK;
}
void CIEAutomationView::OnDocumentComplete(LPDISPATCH pDisp, LPCTSTR lpszUrl)
{
// make sure the main frame has the new URL. This call also stops the animation
((CChildFrame*)GetParentFrame())->SetAddress(lpszUrl);
CString strURL(lpszUrl);
IUnknown* pUnkBrowser = NULL;
IUnknown* pUnkDisp = NULL;
TRACE(_T("Document %s Done\r\n"),lpszUrl);
//is it top level document?
HRESULT hr = m_pBrowserApp->QueryInterface( IID_IUnknown, (void**)&pUnkBrowser);
if ( SUCCEEDED(hr) ){
hr = pDisp->QueryInterface( IID_IUnknown, (void**)&pUnkDisp );
if ( SUCCEEDED(hr) ){
if ( pUnkBrowser == pUnkDisp ){
//top level
m_spHtmlDoc=NULL;
hr=m_pBrowserApp->get_Document(&m_spHtmlDoc);
TRACE(_T("Downloading Complete\r\n"),lpszUrl);
DumpTypeInfo(m_spHtmlDoc);
CComQIPtr<IHTMLDocument2> pHtmlDoc(m_spHtmlDoc);
IShellBrowser* pShellBrowser=(IShellBrowser*)m_wndBrowser.SendMessage(WM_USER+7,0,0);
if(pHtmlDoc){
CComPtr<IHTMLWindow2> pWindow;
pHtmlDoc->get_parentWindow(&pWindow);
CComQIPtr<IDispatch> spWindow(pWindow);
m_domExternal.SetMenuArguments(spWindow);
}
if(pShellBrowser){
CComPtr<IShellView> pIShellView;
pShellBrowser->QueryActiveShellView(&pIShellView);
if(pIShellView){
FOLDERSETTINGS fs;
pIShellView->GetCurrentInfo(&fs);
CComQIPtr<IFolderView> pIFolderView(pIShellView);
if(pIFolderView){
pIFolderView->SetCurrentViewMode(FVM_DETAILS);
}
}
TRACE("Get Shell Browser\r\n");
}
}
pUnkDisp->Release();
}
pUnkBrowser->Release();
}
}
void CIEAutomationView::CallScript(IHTMLWindow2* pWindow2
,BSTR bstrCode
,BSTR bstrLanguage)
{
ASSERT(pWindow2);
HRESULT hr = S_OK;
COleVariant ret;
hr = pWindow2->execScript(bstrCode, bstrLanguage, &ret);
}
void CIEAutomationView::CallScriptDirect(IHTMLWindow2* pWindow2
,BSTR bstrMethod)
{
DISPID dispidScriptObject, dispidMethodToInvoke;
IDispatch *pDispScriptObject;
DISPPARAMS dispparamsNoArgs = { NULL, NULL, 0, 0};
HRESULT hr;
OLECHAR *szScript = L"script";
OLECHAR *szFuncName = bstrMethod;
IHTMLDocument2* pDocument2 = NULL;
hr = pWindow2->get_document(&pDocument2);
ASSERT(SUCCEEDED(hr) && pDocument2);
IDispatch* pDocDisp = NULL;
hr = pDocument2->QueryInterface(IID_IDispatch, (void**)&pDocDisp);
ASSERT(SUCCEEDED(hr) && pDocDisp);
// Get the DISPID of the document's Script property.
hr = pDocDisp->GetIDsOfNames(IID_NULL, &szScript,
1, LOCALE_USER_DEFAULT, &dispidScriptObject);
ASSERT(SUCCEEDED(hr));
COleVariant varResult;
// Get the document's Script property.
hr = pDocDisp->Invoke(dispidScriptObject,
IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
&dispparamsNoArgs, &varResult, NULL, NULL);
ASSERT(SUCCEEDED(hr) && varResult.pdispVal);
pDispScriptObject = varResult.pdispVal;
varResult.Clear();
// Get the DISPID of the script method to invoke.
hr = pDispScriptObject->GetIDsOfNames(IID_NULL, &szFuncName, 1,
LOCALE_USER_DEFAULT, &dispidMethodToInvoke);
ASSERT(SUCCEEDED(hr));
// Invoke the script method.
hr = pDispScriptObject->Invoke(dispidMethodToInvoke, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs,
&varResult, NULL, NULL);
ASSERT(SUCCEEDED(hr));
pDocDisp->Release();
pDocument2->Release();
}
JavaScript Calls from C++
http://www.codeguru.com/ieprogram/JSCalls.html