如何在IE Mobile上检索IPIEHTMLDocument2接口

时间:2020-03-05 18:48:11  来源:igfitidea点击:

我为IE7编写了一个Active X插件,该插件除了实现一些其他必要的接口(请注意,没有IOleClient)之外还实现了IObjectWithSite。该接口由IE7查询和调用。在SetSite()调用期间,我检索了指向IE7站点接口的指针,可以使用它通过以下方法来检索IHTMLDocument2接口:

IUnknown *site = pUnkSite; /* retrieved from IE7 during SetSite() call */
IServiceProvider *sp = NULL;
IHTMLWindow2 *win = NULL;
IHTMLDocument2 *doc = NULL;

if(site) {
    site->QueryInterface(IID_IServiceProvider, (void **)&sp);
    if(sp) {
        sp->QueryService(IID_IHTMLWindow2, IID_IHTMLWindow2, (void **)&win);
        if(win) {
            win->get_document(&doc);
        }
    }
}
if(doc) {
    /* found */
}

我也使用以下代码在PIE上尝试了类似的方法,但是,即使IPIEHTMLWindow2接口也无法获取,所以我陷入了困境:

IUnknown *site = pUnkSite; /* retrieved from PIE during SetSite() call */
IPIEHTMLWindow2 *win = NULL;
IPIEHTMLDocument1 *tmp = NULL;
IPIEHTMLDocument2 *doc = NULL;

if(site) {
    site->QueryInterface(__uuidof(*win), (void **)&win);
    if(win) { /* never the case */
        win->get_document(&tmp);
        if(tmp) {
            tmp->QueryInterface(__uuidof(*doc), (void **)&doc);
        }
    }
}
if(doc) {
    /* found */
}

使用IServiceProvider接口也不起作用,因此我已经对此进行了测试。

有任何想法吗?

解决方案

回答

我在这里的Google Gears代码中找到了以下代码。我在这里复制了我认为我们需要的功能。我们需要的一个在底部(GetHtmlWindow2),但另外两个也是必需的。希望我什么都没错过,但是如果我做了什么,我们可能需要在链接上。

#ifdef WINCE
// We can't get IWebBrowser2 for WinCE.
#else
HRESULT ActiveXUtils::GetWebBrowser2(IUnknown *site, IWebBrowser2 **browser2) {
  CComQIPtr<IServiceProvider> service_provider = site;
  if (!service_provider) { return E_FAIL; }

  return service_provider->QueryService(SID_SWebBrowserApp,
                                        IID_IWebBrowser2,
                                        reinterpret_cast<void**>(browser2));
}
#endif

HRESULT ActiveXUtils::GetHtmlDocument2(IUnknown *site,
                                       IHTMLDocument2 **document2) {
  HRESULT hr;

#ifdef WINCE
  // Follow path Window2 -> Window -> Document -> Document2
  CComPtr<IPIEHTMLWindow2> window2;
  hr = GetHtmlWindow2(site, &window2);
  if (FAILED(hr) || !window2) { return false; }
  CComQIPtr<IPIEHTMLWindow> window = window2;
  CComPtr<IHTMLDocument> document;
  hr = window->get_document(&document);
  if (FAILED(hr) || !document) { return E_FAIL; }
  return document->QueryInterface(__uuidof(*document2),
                                  reinterpret_cast<void**>(document2));
#else
  CComPtr<IWebBrowser2> web_browser2;
  hr = GetWebBrowser2(site, &web_browser2);
  if (FAILED(hr) || !web_browser2) { return E_FAIL; }

  CComPtr<IDispatch> doc_dispatch;
  hr = web_browser2->get_Document(&doc_dispatch);
  if (FAILED(hr) || !doc_dispatch) { return E_FAIL; }

  return doc_dispatch->QueryInterface(document2);
#endif
}

HRESULT ActiveXUtils::GetHtmlWindow2(IUnknown *site,
#ifdef WINCE
                                     IPIEHTMLWindow2 **window2) {
  // site is javascript IDispatch pointer.
  return site->QueryInterface(__uuidof(*window2),
                              reinterpret_cast<void**>(window2));
#else
                                     IHTMLWindow2 **window2) {
  CComPtr<IHTMLDocument2> html_document2;
  // To hook an event on a page's window object, follow the path
  // IWebBrowser2->document->parentWindow->IHTMLWindow2

  HRESULT hr = GetHtmlDocument2(site, &html_document2);
  if (FAILED(hr) || !html_document2) { return E_FAIL; }

  return html_document2->get_parentWindow(window2);
#endif
}

回答

好吧,我已经知道了齿轮代码。 Gears使用的机制基于一种变通方法,该解决方案是通过从Gears加载器对gears插件执行显式方法调用来设置窗口对象并将其用作站点接口,而不是由IE Mobile在SetSite调用中提供的IUnknown。关于齿轮代码,Google工程师知道我要问的相同问题,并提出了我所描述的解决方法。

但是,我认为必须存在另一种"官方"方式来解决此问题,因为在Active X控件/插件上显式设置站点不是很好。我现在要直接询问MS IE Mobile团队,一旦获得解决方案,我们将立即通知我们。这可能是IE Mobile中的错误,这是我能想到的最有可能发生的事情,但是谁知道...

但是无论如何,谢谢回复;))