如何在 WebView2 控件中显示查找对话框?
How to display Find dialog in a WebView2 control?
我已将旧的 C++ MFC 应用程序升级为使用基于 Edge 的 WebView2 网络浏览器控件。否则我已经让它工作正常,剩下的问题之一是通过主 MFC 应用程序编辑-查找菜单项或通过 Ctrl+F(它也被 MFC 框架拦截)打开其中的查找对话框。我现在拥有的是:
m_webView->ExecuteScript(L"window.find(\"\", 0, 0, 0, 0, 0, 1);");
其中 m_webView
是指向 ICoreWebView2
接口的指针。
问题是有时会弹出“查找”对话框,有时不会。有时它会在页面刷新后执行,有时不会。当我从 cross 关闭“查找”对话框时,它通常拒绝再次打开它。
如何让它正常运行?也许有一种方法不需要经过Javascript?
更新:似乎只有当 Ctrl+F 键击以某种方式绕过 MFC 直接发送到 WebView2 控件时它才有效。看起来上面的 Javascript 行从未起作用。那么也许有一种方法可以为 WebView2 控件模拟 Ctrl+F?
据我所知,WebView2 当前不支持您调用或以其他方式控制“在页面中查找”对话框。也可以参考GitHub中的this thread. There is a similar thread,官方还没给出解决方法
您可以直接在 WebView2 控件中使用 Ctrl+F 击键或在 WebView2 Feedback page 上提供有关此问题的反馈。感谢您的理解。
正如@yu-zhou 回答的那样,目前还没有正式的方法来做我想做的事情。现在我又回到了以编程方式为 WebView2 控件模拟 Ctrl+F,但结果不是很好。作为记录,我仍然在这里展示它:
首先,用户必须至少在 webview2 控件中单击一次,因此我可以将其 HWND 记录在 add_GotFocus():
注册的 GotFocus 事件处理程序中
void MyHtmlView::OnGotFocus() {
if (!m_webview2_hwnd) {
m_webview2_hwnd = ::GetFocus();
}
}
现在,当我想以编程方式调出查找栏时,我需要确保正确的 window 获得焦点并向其发送 Ctrl+F 键。 las,控件似乎以异步方式检查 Ctrl 键状态,所以它有点棘手,我需要更改线程的键盘状态并添加一个额外的事件处理程序以在之后恢复它。经过反复试验,我得出了这个(为简洁起见省略了错误检查):
void MyHtmlView::Find() {
if (::GetFocus()!=m_webview2_hwnd) {
::SetFocus(m_webview2_hwnd);
}
std::uint8_t state[256];
::GetKeyboardState(state);
bool restoreCtrlState = false;
if ((state[VK_CONTROL] & 0x80)==0) {
// Ctrl key is currently not pressed.
// Mark it pressed.
state[VK_CONTROL] |= 0x80;
::SetKeyboardState(state);
restoreCtrlState = true;
}
std::thread auxThread([this, restoreCtrlState]() {
::SendMessage(m_webview2_hwnd, WM_KEYDOWN, 'F', 1);
::SendMessage(m_webview2_hwnd, WM_KEYUP, 'F', 1);
if (restoreCtrlState) {
::PostMessage(m_hWnd, WM_COMMAND, ID_RESTORE_CONTROL_STATE, 0);
}
});
auxThread.detach();
}
// This needs to be registered to handle ID_RESTORE_CONTROL_STATE
void HtmlView::OnRestoreCtrlState() {
std::uint8_t state[256];
::GetKeyboardState(state);
if ((state[VK_CONTROL] & 0x80)!=0) {
state[VK_CONTROL] &= ~0x80;
::SetKeyboardState(state);
}
}
不用说,如果他们更改了 webview2 实现中的某些内容,这个 hack 可能很容易停止工作。
我已将旧的 C++ MFC 应用程序升级为使用基于 Edge 的 WebView2 网络浏览器控件。否则我已经让它工作正常,剩下的问题之一是通过主 MFC 应用程序编辑-查找菜单项或通过 Ctrl+F(它也被 MFC 框架拦截)打开其中的查找对话框。我现在拥有的是:
m_webView->ExecuteScript(L"window.find(\"\", 0, 0, 0, 0, 0, 1);");
其中 m_webView
是指向 ICoreWebView2
接口的指针。
问题是有时会弹出“查找”对话框,有时不会。有时它会在页面刷新后执行,有时不会。当我从 cross 关闭“查找”对话框时,它通常拒绝再次打开它。
如何让它正常运行?也许有一种方法不需要经过Javascript?
更新:似乎只有当 Ctrl+F 键击以某种方式绕过 MFC 直接发送到 WebView2 控件时它才有效。看起来上面的 Javascript 行从未起作用。那么也许有一种方法可以为 WebView2 控件模拟 Ctrl+F?
据我所知,WebView2 当前不支持您调用或以其他方式控制“在页面中查找”对话框。也可以参考GitHub中的this thread. There is a similar thread,官方还没给出解决方法
您可以直接在 WebView2 控件中使用 Ctrl+F 击键或在 WebView2 Feedback page 上提供有关此问题的反馈。感谢您的理解。
正如@yu-zhou 回答的那样,目前还没有正式的方法来做我想做的事情。现在我又回到了以编程方式为 WebView2 控件模拟 Ctrl+F,但结果不是很好。作为记录,我仍然在这里展示它:
首先,用户必须至少在 webview2 控件中单击一次,因此我可以将其 HWND 记录在 add_GotFocus():
注册的 GotFocus 事件处理程序中void MyHtmlView::OnGotFocus() {
if (!m_webview2_hwnd) {
m_webview2_hwnd = ::GetFocus();
}
}
现在,当我想以编程方式调出查找栏时,我需要确保正确的 window 获得焦点并向其发送 Ctrl+F 键。 las,控件似乎以异步方式检查 Ctrl 键状态,所以它有点棘手,我需要更改线程的键盘状态并添加一个额外的事件处理程序以在之后恢复它。经过反复试验,我得出了这个(为简洁起见省略了错误检查):
void MyHtmlView::Find() {
if (::GetFocus()!=m_webview2_hwnd) {
::SetFocus(m_webview2_hwnd);
}
std::uint8_t state[256];
::GetKeyboardState(state);
bool restoreCtrlState = false;
if ((state[VK_CONTROL] & 0x80)==0) {
// Ctrl key is currently not pressed.
// Mark it pressed.
state[VK_CONTROL] |= 0x80;
::SetKeyboardState(state);
restoreCtrlState = true;
}
std::thread auxThread([this, restoreCtrlState]() {
::SendMessage(m_webview2_hwnd, WM_KEYDOWN, 'F', 1);
::SendMessage(m_webview2_hwnd, WM_KEYUP, 'F', 1);
if (restoreCtrlState) {
::PostMessage(m_hWnd, WM_COMMAND, ID_RESTORE_CONTROL_STATE, 0);
}
});
auxThread.detach();
}
// This needs to be registered to handle ID_RESTORE_CONTROL_STATE
void HtmlView::OnRestoreCtrlState() {
std::uint8_t state[256];
::GetKeyboardState(state);
if ((state[VK_CONTROL] & 0x80)!=0) {
state[VK_CONTROL] &= ~0x80;
::SetKeyboardState(state);
}
}
不用说,如果他们更改了 webview2 实现中的某些内容,这个 hack 可能很容易停止工作。