Como faço para recuperar a interface IPIEHTMLDocument2 no IE Mobile
-
09-06-2019 - |
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?
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 ;))