在Internet Explorer编程中,获取WebBrowser指针通常是一件很重要的事情,因为有了WebBrowser指针,我们就有了对IE完整的控制权。我们就可以对IE浏览器为所欲为了,想干什么都可以。比方说获取或者设置DOM控件的值。调用页面中的JavaScript,或者控制浏览器的行为 比方说刷新,前进、后退等等等等。
下面两篇文章中,我将介绍两种方法来获取IWebBrowser2指针。
第一种
使用OLEACC.dll动态库中的ObjectFromLresult函数来获取。
第二种
使用IShellWindows 获取当前浏览器个数,然后遍历获取浏览器对象和IWebBrowser指针。
下面介绍第一种方法:
在MSDN中对ObjectFromLresult函数的解释
The LresultFromObject function returns a reference, that is similar to a handle, to the specified object. Servers return this reference when handling WM_GETOBJECT.
所以就必须要调用::RegisterWindowMessage( _T(“WM_HTML_GETOBJECT”) );和SendMessageTimeout返回的与WM_GETOBJECT消息关联的值。这样就可以利用ObjectFromLresult来获取IHTMLDocument2指针,有了IHTMLDocument2,剩下的事情就是QueryInterface来获取IWebBrowser2指针,这样就很轻松了。
下面看下代码:
view plaincopy to clipboardprint?
//用来接收EnumChildWindows的回调函数
//根据类名Internet Explorer_Server来判断是否是Internet Explorer控件
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
{
TCHAR buf[100];
::GetClassName( hwnd, (LPTSTR)&buf, 100 );
if ( _tcscmp( buf, _T("Internet Explorer_Server") ) == 0 )
{
*(HWND*)lParam = hwnd; return FALSE;
}
else return TRUE;
};
IWebBrowser2* GetWBByhWnd(HWND hIEWindow)
{
CoInitialize( NULL );
// Explicitly load MSAA so we know if it's installed
HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") );
IWebBrowser2* pWebBrowser2=NULL;
if ( hInst != NULL )
{
HWND hWnd ;
if(hIEWindow==NULL)
{
hWnd= FindWindow("IEFrame", NULL);
if(hWnd==NULL)
hWnd= FindWindow("CabinetWClass", NULL);
if( hWnd == NULL)
{
MessageBox (NULL,"No Running instance of Internet Explorer!","message", MB_OK);
}
// walk Shell DocObject View->Internet Explorer_Server
HWND hWndChild = FindWindowEx(hWnd, 0, "Shell DocObject View", NULL);
if(hWndChild !=0)
{
hWndChild = FindWindowEx(hWndChild, 0, "Internet Explorer_Server", NULL);
}
hWnd=hWndChild;
}
else
{
hWnd = hIEWindow;
HWND hWndChild=NULL;
// Get 1st document window
EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
if ( hWndChild )
{
CComPtr<IHTMLDocument2> spDoc;
LRESULT lRes;
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes );
LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, _T("ObjectFromLresult") );
if ( pfObjectFromLresult != NULL )
{
HRESULT hr;
hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument2, 0, (void**)&spDoc );
if ( SUCCEEDED(hr) )
{
CComPtr<IHTMLWindow2>spWnd2;
CComPtr<IServiceProvider>spServiceProv;
hr=spDoc->get_parentWindow ((IHTMLWindow2**)&spWnd2);
if(SUCCEEDED(hr))
{
hr=spWnd2->QueryInterface (IID_IServiceProvider,(void**)&spServiceProv);
if(SUCCEEDED(hr))
{
hr = spServiceProv->QueryService(SID_SWebBrowserApp,IID_IWebBrowser2,(void**)&pWebBrowser2);
if(SUCCEEDED(hr))
{
return pWebBrowser2;
}
}
}
}
}
} // else document not ready
} // else Internet Explorer is not running
::FreeLibrary( hInst );
} // else Active Accessibility is not installed
CoUninitialize();
return NULL;
}
下面介绍第二种方法:
这种方法是通过创建ShellWindows实例,得到浏览器对象实例的个数,通过遍历浏览器对象,获得IWebBrowser指针。
在构造SHDocVw::IWebBrowser2Ptr spBrowser对象的适合,构造不成功 就会返回NULL,这样的化调用QueryInterface来获取IWebBrowser2指针是获取不到的。所有有了if(spBrowser!=NULL)这样一个判断。
下面看代码:
view plaincopy to clipboardprint?
IWebBrowser2* GetWB()
{
SHDocVw::IShellWindowsPtr m_spSHWinds;
CComPtr<IDispatch> spDispatch;
CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> pDoc2;
CComPtr<IHTMLElement> pElement;
CComPtr<IHTMLElementCollection> pElementCol;
CComPtr<IHTMLFormElement> pFormElement;
CComPtr<IHTMLInputTextElement> pInputElement;
IWebBrowser2 * pWebBrowser = NULL;
//创建ShellWindows实例
if (m_spSHWinds == NULL)
{
if (m_spSHWinds.CreateInstance(__uuidof(SHDocVw::ShellWindows)) != S_OK)
{
MessageBox("Failed");
CoUninitialize();
return NULL;
}
}
if (m_spSHWinds)
{
// 取得浏览器实例个数
int n = m_spSHWinds->GetCount();
for (int i = 0; i < n; i++)
{
_variant_t v = (long)i;
IDispatchPtr spDisp = m_spSHWinds->Item(v);
SHDocVw::IWebBrowser2Ptr spBrowser(spDisp); //生成一个IE窗口的智能指针
//SHDocVw::IWebBrowser2Ptr与IWebBrowser2是不一样的
//SHDocVw::IWebBrowser2Ptr是经过COM封装的,所以在此判断一下
//否则QueryInterface 会出错的。
if (spBrowser!=NULL)
{
HRESULT hr = spDisp.QueryInterface(IID_IWebBrowser2, &pWebBrowser);
if (SUCCEEDED(hr))
{
if (pWebBrowser !=NULL)
{
return pWebBrowser;
}
}
}
}
}
return NULL;
}