Pergunta

Eu escrevi um plugin Active X para IE7 que implementa IObjectWithSite além de algumas outras interfaces necessárias (observe que não há IOleClient).Esta interface é consultada e chamada pelo IE7.Durante a chamada SetSite() eu recupero um ponteiro para a interface do site do IE7 que posso usar para recuperar a interface IHTMLDocument2 usando a seguinte abordagem:

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 */
}

Também tentei uma abordagem semelhante no PIE usando o código a seguir, no entanto, mesmo a interface IPIEHTMLWindow2 não pode ser adquirida, então estou preso:

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 */
}

Usar a interface IServiceProvider também não funciona, então já testei isso.

Alguma ideia?

Foi útil?

Solução

Encontrei o seguinte código no código do Google Gears, aqui.Copiei as funções que acho que você precisa aqui.O que você precisa está na parte inferior (GetHtmlWindow2), mas os outros dois também são necessários.Espero não ter perdido nada, mas se eu fiz o que você precisa provavelmente está no link.

#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
}

Outras dicas

Bem, eu já estava ciente do código das engrenagens.O mecanismo que o gears usa é baseado em uma solução alternativa através da execução de uma chamada de método explícita no plugin gears do carregador do gears para definir o objeto window e usá-lo como interface do site em vez do IUnknown fornecido pelo IE Mobile na chamada SetSite.Em relação ao código do Gears, os engenheiros do Google estão cientes do mesmo problema que estou perguntando e criaram a solução alternativa que descrevi.

No entanto, acredito que deve haver outra maneira mais "oficial" de lidar com esse problema, já que definir explicitamente o site em um controle/plugin Active X não é muito bom.Vou perguntar diretamente à equipe do MS IE Mobile agora e mantê-lo-ei informado assim que conseguir uma solução.Pode ser um bug no IE Mobile, que é a coisa mais provável que posso imaginar, mas quem sabe...

Mas de qualquer forma obrigado pela sua resposta ;))

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top