脚本中传来的函数指针是LPDISPATCH,如果直接用ChangeType转为String,得到的结果是包含函数代码在内的整个函数而不是函数名[即便能通过分析来获得...],请问我要如何能够通过这个Dispatch指针来调用这个函数呢?
难道只能生成一个调用字符串插入执行吗?

解决方案 »

  1.   

    JavaScript Calls from C++
    http://www.codeguru.com/ieprogram/JSCalls.html
      

  2.   

    我也看了一下,这个地址确实不错的:http://www.codeguru.com/ieprogram/JSCalls.html
      

  3.   

    确实不错,通过GetIDsOfNames获取函数名称对应的DISPID,然后Invoke。但是前提是我知道这个函数的名称啊,通过return funcHandle这种方式传回来的指针的Variant Type(vt)是VT_DISPATCH而不是函数名称,强制转换为BSTR也是包含了函数代码的。这种方法实际上还是要我回到解析强制转换后的字符串的老路子上啊...而且我也有点奇怪,为什么返回的是DISPATCH接口?而且这个接口下似乎没有实现任何属性/方法啊...
      

  4.   

    通过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();}
      

  5.   

    函数对象用DISPID=0来调用。
    pObj->Invoke(0,IID_NULL,0,DISPATCH_METHOD,&Params,&result,NULL,NULL);
      

  6.   

    阿拉真主,我赞美Analyst!哦,顺便赞美一下jiangsheng和saucer前辈~就是那个DISPID=0,看到一些相关资料里面有所谓调用该Dispatch接口的缺省方法的说法,不过不知道如何做,大概便是这个吧?谢了,头疼了两三天了:)顺便感谢另两位帮忙解惑的,看了那些资料也获益良多呢。真恨不得拿我剩下的10000可用分把你们脑子里的东西都挖出来,口黑口黑...