我在基于对话框的MFC窗口中使用嵌入式web browser control,我需要知道其中的Web浏览器控件的HWND。我能够找到声称检索它的以下代码:
HWND hWndWebBrowser = NULL;
LPUNKNOWN unknown = m_browser.GetControlUnknown();
IWebBrowser2* pWB = NULL;
if(SUCCEEDED(unknown->QueryInterface(IID_IWebBrowser2,(void **)&pWB)))
{
CComPtr<IServiceProvider> pServiceProvider;
if (SUCCEEDED(pWB->QueryInterface(IID_IServiceProvider, (void**)&pServiceProvider)))
{
CComPtr<IOleWindow> pWindow;
if (SUCCEEDED(pServiceProvider->QueryService(SID_SShellBrowser, IID_IOleWindow, (void**)&pWindow)))
{
SHANDLE_PTR hBrowser = 0;
if (SUCCEEDED(pWindow->GetWindow(&hBrowser)))
{
hWndWebBrowser = (HWND)hBrowser;
}
}
}
}
if(unknown)
{
unknown->Release();
}
但问题是,当它运行时,它返回一个句柄,但不是我期望的句柄。说明它的最好方法是使用这个Spy ++截图:
我知道我可以使用EnumChildWindows并查找包含Internet Explorer_Server
类的窗口,但我有点担心使用此未记录的类名。
有没有人有更好的方法来检索该(Web浏览器)窗口句柄?
答案 0 :(得分:1)
每Obtaining the HWND for the WebBrowser control。您可以使用以下函数来检索HWND。
IOleWindow *pOWin;
HWND hBWnd;
HRESULT hRes = m_pBrowserApp->QueryInterface(IID_IOleWindow, (void **)&pOWin);
if (SUCCEEDED(hRes)) {
hRes = pOWin->GetWindow(&hBWnd);
if (SUCCEEDED(hRes)) {
// Place hBWnd-manipulating code here
}
}
答案 1 :(得分:1)
这个问题的词汇有点棘手。
(Web浏览器)的HWND确实是答案 你发布的帖子和Santosh Dhanawade发布的答案。
加载文档后,Web浏览器控件会创建一个 新窗口或iframe,请参阅DWebBrowserEvents2::DocumentComplete事件。
事件处理程序参数:
“ pDisp [in] ”指向加载文档的窗口或框架的IDispatch接口的指针。可以为IWebBrowser2接口查询此IDispatch接口。
所以,改变问题:
“有没有人有更好的方法来检索(网络浏览器)窗口句柄?”
为:
“有没有人有更好的方法来检索(窗口或iframe )窗口句柄?”
我们有你要锁定的窗口或iframe HWND, 在文件加载完毕后将可以使用。
这意味着我们可以执行以下操作:
实现DocumentComplete事件处理程序抛出原始c或c ++实现 IDispatch或ATL DispEventImpl或ATL DispEventSimpleImpl。 请参阅Understanding COM Event Handling。
将我们的事件处理程序接收到Web浏览器控件中以获取事件报告。
从DocumentComplete事件中获取窗口或iframe HWND:
假设原始c ++ IDispatch实现:
IFACEMETHODIMP DWebBrowserEvents2Impl::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult, EXCEPINFO * pExcepInfo, UINT * puArgErr)
{
if (dispIdMember == DISPID_DOCUMENTCOMPLETE) {
VARIANT variantDispatch;
VariantInit(&variantDispatch);
HRESULT hr = DispGetParam(pDispParams, 0, VT_DISPATCH, &variantDispatch, NULL);
if (SUCCEEDED(hr)) {
IOleWindow* iOleWindow;
hr = variantDispatch.pdispVal->QueryInterface(IID_IOleWindow, (LPVOID*) &iOleWindow);
if (SUCCEEDED(hr)) {
HWND hwnd;
hr = iOleWindow->GetWindow(&hwnd);
iOleWindow->Release();
if (SUCCEEED(hr)){
//now the hwnd correponds to the Internet Explorer_Server window.
//Do what ever you want with the HWND handler.
}
}
}
return S_OK;
}
return E_NOTIMPL;
}
答案 2 :(得分:0)
根据我的经验,我们正在寻找的窗口是 CHtmlView 派生的 CWnd 的直接后代,所以我使用这个 hack 来获取窗口并将焦点设置到它:
static CWnd* findChildWebbrowser(CWnd* pWnd) {
if(pWnd == NULL) { return NULL; }
CWnd* pC = pWnd->GetWindow(GW_CHILD);
if(pC == NULL) { return NULL; };
CString buf;
::GetClassName(pC->GetSafeHwnd(), buf.GetBuffer(2048), 2047);
buf.ReleaseBuffer();
if(buf == _T("Internet Explorer_Server")) {
return pC;
}
return findChildWebbrowser(pC);
}
void CMyWebView::OnSetFocus(CWnd* pOldWnd) {
// CHtmlView::OnSetFocus(pOldWnd);
CWnd* pIE = findChildWebbrowser(this);
if(pIE!=NULL) {
// this makes cursor/page keys work
pIE->SetFocus();
// this makes the TAB key work
pIE->SendMessage(WM_LBUTTONDOWN);
pIE->SendMessage(WM_LBUTTONUP);
}
}