1

我遇到了一个问题,我很确定这个论坛能够帮助我解决这个问题。

我正在尝试向脚本添加一些自动化对象(通过单独的进程(ATL EXE 服务器)托管)。此外,我试图从我的 ATL EXE 脚本引擎中的这些自动化对象中接收事件。

为了实现这一点,我正在使用 CDispExSinkConnector,如http://www.codeproject.com/Articles/3326/Extending-the-Internet-Explorer-Scripting-Engine 中所述,我正在使用 IDispatchEx::GetDispID() 来创建脚本引擎中的新成员。创建成员 DISPID 后,我将使用 InvokeEx() 设置属性值。但是这些方法调用返回 RPC_E_SYS_CALL_FAILED。

注意 - 这里我从 OUT-OF-PROC IDispatch 指针中获取 IDispEx 指针。

更详细的描述:我在 ATL EXE 服务器中确实有一个由 CAxWindow 托管的 BrowserCtrl,我用它来为我的 MFC 客户端应用程序创建 HTML 插件。ATL EXE 服务器为 IWebBrowser2 方法提供包装器方法,以便我可以调用 IWebBrowser2Ptr->Navigate2() 之类的方法。

我还可以在此 ATL EXE 服务器中订阅 IWebBrowser2 事件,例如 OnDocumentComplete(....),并最终将这些事件转发到我的 MFC 客户端应用程序以在那里处理这些事件。下面是我的 ATL EXE 服务器 (BrowserCtrl) 的一些代码片段:

第一个是 CreateControl(),它创建 CAxWindow,创建 WebBrowser 控件并将控件托管在内部默认 CAxHostWindow 上。

STDMETHODIMP BrowserCtrl::CreateControl(ULONG hwndParent, LONG left,LONG top, LONG right, LONG bottom)
{
  CRect rc(left, top, right, bottom);

  // Create the AX host window. m_wndBrowserCtrl is CAxWindow object
HWND hwndAxHost = m_wndBrowserCtrl.Create(reinterpret_cast<HWND>(hwndParent), &rc, L"Shell.Explorer", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,  0, ID_BROWSERCTRL );

  //Obtain a pointer to the container object
  CComQIPtr<IAxWinHostWindow> ptrWinHost;
  HRESULT hr = m_wndBrowserCtrl.QueryHost(&ptrWinHost);


  LPOLESTR lpszCLSID = NULL;
  hr = StringFromCLSID(CLSID_WebBrowser, &lpszCLSID);


  // Create the WebBrowser Ctrl
  CComPtr<IUnknown> cpIUnknown = NULL;
hr = ptrWinHost->CreateControlEx(lpszCLSID, m_wndBrowserCtrl, NULL, &cpIUnknown, __uuidof(SHDocVw::DWebBrowserEvents2), reinterpret_cast<IUnknown*>(reinterpret_cast<DWebBrowserEvents2Impl*>(this)));

// Get the IWebBrowser2 interface pointer for the control
// CComQIPtr<IWebBrowser2> m_cpIBrowser;
  m_cpIBrowser = cpIUnknown;
  return S_OK;
}

//现在是 IWebBrowser2 方法的包装器方法

STDMETHODIMP BrowserCtrl::Navigate2(VARIANT *pwszUrl, VARIANT *Flags, VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
{
  HRESULT hr = m_cpIBrowser->Navigate2(pwszUrl, Flags,TargetFrameName,PostData,Headers);
}

//现在是 IWebBrowser2 事件的事件处理程序:

void __stdcall BrowserCtrl::OnDocumentComplete(IDispatch* pDisp, VARIANT* pvaURL)
{
Fire_OnDocumentComplete(pDisp , pvaURL);// forwarding to the MGC client APP

}

现在的问题:

1.在 MFC 客户端应用程序和事件处理函数 OnDocumentComplete() 中,我执行以下操作:

 void MFCClientApp::HandleDocumentComplete(LPDISPATCH pIDisp, VARIANT* pvaURL)
    {
      CComPtr<IDispatch> pDispDoc;
      CComQIPtr<IDispatch> pScriptDisp;
      CComQIPtr<IDispatchEx> pDispEx;
      CComQIPtr<IHTMLDocument> pHTMLDoc;
      CComQIPtr<IWebBrowser2> pWebBrowser;

    if (pIDisp != NULL)
          {
            pWebBrowser = pIDisp;
            //CComPtr<IDispatch> ptrIDisp;
            //BOOL bResult = GetOPBrowser()->GetDisp(&ptrIDisp);
            //pWebBrowser = ptrIDisp;
            pWebBrowser->get_Document(&pDispDoc);

            if (pDispDoc != NULL)
            {
              // Get the IDispatchEx interface
              pHTMLDoc = pDispDoc;
              if (pHTMLDoc != NULL)
              {
                pHTMLDoc->get_Script(&pScriptDisp);
                pDispEx = pScriptDisp;

                if (pDispEx != NULL)
                {
                         CDispExSinkConnector pDispExSinkConnector = new CDispExSinkConnector();
    Hr = pDispExSinkConnector->SetDispEx(pDispEx); // here the Hr returned is 0x80010100  “System Call Failed” i.e. RPC_E_SYS_CALL_FAILED
    ……
    ……..
    ………
    }

这是 SetDispEx() 和内部相关函数:

void CDispExSinkConnector::SetDispEx(IDispatchEx *pDispEx)
{
       CComBSTR bstrThisGuid("AC0B188C-6B55-408f-9E8C-821B9B5467CB"); // @!I8NIGNORE

       HRESULT hr = m_pDispExGIT.Attach(pDispEx);//add it to the GIT Table
       ASSERT(pDispEx);
       // We need to add ourselves to the script engine
       AddNamedObject(bstrThisGuid, this);
}
HRESULT CDispExSinkConnector::AddNamedObject(BSTR bsName, IDispatch *pDisp)
{
       HRESULT hr = 0;

       CComPtr<IDispatchEx> pDispEx;
       GetDispEx(&pDispEx); 

       if(pDispEx == NULL)
              return E_FAIL;

       if(!bsName || SysStringLen(bsName) == 0 || !pDisp)
              return E_INVALIDARG;

       // Also, add our root objects into the script namespace
       DISPID dispIdThis = 0;     
hr = pDispEx->GetDispID(bsName, fdexNameEnsure | fdexNameCaseSensitive,&dispIdThis);     // here the Hr returned is 0x80010100  “System Call Failed” i.e. RPC_E_SYS_CALL_FAILED

       if (hr == DISP_E_UNKNOWNNAME)
…
..
}

请帮助我找出根本原因和解决此问题的解决方案。您的快速帮助将不胜感激。谢谢, SP

4

0 回答 0