IWebBrowser2::get_HWND "gets the handle of the Microsoft Internet Explorer main window". As any COM method
get_HWND returns a
HRESULT value. According to MSDN, the method "
returns S_OK if successful, or an error value otherwise".It was hard for me to imagine how this method could fail but I still got an
E_FAIL return value. This happened because the
IWebBrowser2 object was not the top level browser. A web page containing frames/iframes is represented by a hierarchy of
IHTMLWindow objects. Each window has an associated
IHTMLDocument2 object exposed by
IHTMLWindow2::get_document. An
IHTMLWindow can be also converted to a
IWebBrowser2 object. Here's my solution to get the main window handle starting from a non-top level browser object (this is a common scenario when adding your custom menu item in the IE context menu).
// IHTMLWindow2 to IWebBrowser2
CComQIPtr<IWebBrowser2> IHTMLWindow2ToIWebBrowser2(CComQIPtr<IHTMLWindow2> spHTMLWindow)
{
ATLASSERT(spHTMLWindow != NULL);
// Query for a service provider.
CComQIPtr<IWebBrowser2> spBrowser;
CComQIPtr<IServiceProvider> spServiceProvider = spHTMLWindow;
if (spServiceProvider != NULL)
{
// Ask the service provider for a IWebBrowser2 object.
spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spBrowser);
}
return spBrowser;
}
// IWebBrowser2 to IHTMLWindow2
CComQIPtr<IHTMLWindow2> IWebBrowserToIHTMLWindow(CComQIPtr<IWebBrowser2> spBrowser)
{
ATLASSERT(spBrowser != NULL);
CComQIPtr<IHTMLWindow2> spWindow;
// Get the document of the browser.
CComQIPtr<IDispatch> spDisp;
spBrowser->get_Document(&spDisp);
// Get the window of the document.
CComQIPtr<IHTMLDocument2> spDoc = spDisp;
if (spDoc != NULL)
{
spDoc->get_parentWindow(&spWindow);
}
return spWindow;
}
CComQIPtr<IWebBrowser2> TopBrowser(CComQIPtr<IWebBrowser2> spBrowser)
{
ATLASSERT(spBrowser != NULL);
// Retrieve IHTMLWindow2 from browser.
CComQIPtr<IHTMLWindow2> spHTMLWnd = IWebBrowserToIHTMLWindow(spBrowser);
if (spHTMLWnd != NULL)
{
// Find top window.
CComQIPtr<IHTMLWindow2> spTopWindow;
HRESULT hResult = spHTMLWnd->get_top(&spTopWindow);
if (SUCCEEDED(hResult) && (spTopWindow != NULL))
{
// Convert the browser object to window.
return IHTMLWindow2ToIWebBrowser2(spTopWindow);
}
}
return CComQIPtr<IWebBrowser2>();
}
This technique was successfully implemented and tested in
My web automation library.
codeproject