C# - 在 WebBrowser 控件中捕获 CTRL-鼠标滚轮
我正在用 C# 开发一个 Windows 窗体应用程序,其中嵌入了 WebBrowser
控件,以“防伪”(即禁用上下文菜单、后退按钮、自由导航等)访问第三方 Web应用。
现在我正在尝试将缩放功能添加到我的自定义浏览器中。我有键盘组合(CTRL + 和 CTRL - 对底层 ActiveX WebBrowser 对象进行正确的 OLE 调用),但在我必须处理的关于 WebBrowser
的其他令人沮丧的事情中,我似乎不知道如何像 IE 那样捕获 CTRL-鼠标滚轮来模拟缩放功能。我到处寻找解决方案,但没有成功。
为了尝试弄清楚这一点,我创建了一个空表单,其中仅包含 WebBrowser 控件,并发现以下内容:
- 当父窗体具有焦点并且鼠标光标悬停在窗口顶部(例如,悬停在应用程序的标题上)时,或者当鼠标光标悬停时,CTRL-MouseWheel 始终会触发
MouseWheel
事件当WebBrowser
控件看起来没有焦点时,即使父窗体具有焦点,也会覆盖该控件。 - 当鼠标光标悬停在
WebBrowser
控件上并且WebBrowser
具有焦点时,CTRL-MouseWheel 永远不会触发MouseWheel
事件,并且似乎没有影响。 - 使用不按 CTRL 的鼠标滚轮可滚动
WebBrowser
的窗口内容,但不会触发MouseWheel
事件,直到垂直滚动条完全到达顶部或底部。 - 通过重写继承自
WebBrowser< 的示例类的
WndProc
和DefWndProc
来拦截WM_MOUSEWHEEL
的Message
/code> 和父表单仅适用于上述条件(使用wParam
正确表示MK_CONTROL
)。 - 正如预期的那样,当按下 CTRL 时,
PreviewKeyDown
事件会触发,但仍然不会与鼠标滚轮同步执行任何操作。
所以我猜 Message
正在父表单和托管控件级别下进行处理,并且不会冒泡到我可以拦截甚至处理它的位置。有没有办法做到这一点,或者有其他方法来使用 CTRL-MouseWheel 模拟放大和缩小?
感谢您的阅读!
I'm developing a Windows Forms application in C# with an embedded WebBrowser
control to "dummy-proof" (i.e. disable context menus, back button, free navigation, etc.) access to a third-party web application.
Right now I'm trying to add the Zoom feature to my custom browser. I have the keyboard combos working for it (CTRL + and CTRL - make the correct OLE calls to the underlying ActiveX WebBrowser object), but among the other frustrating things about WebBrowser
I've had to deal with, I can't seem to figure out how to capture CTRL-Mouse wheel to simulate the Zoom function like IE does. I've looked everywhere to find a solution to this but to no avail.
To try to figure it out, I created an empty form with just the WebBrowser control in it, and found the following:
- CTRL-MouseWheel always fires the
MouseWheel
event when the parent form has focus and the mouse cursor is hovering over the top of the window (e.g. over the title of the application), or when the mouse cursor is hovering over theWebBrowser
control when it does not appear to have focus even though the parent form has focus. - CTRL-MouseWheel never fires the
MouseWheel
event when the mouse cursor is hovering over theWebBrowser
control andWebBrowser
has focus, and there seems to be no effect. - Using the mouse wheel without CTRL scrolls the window contents of
WebBrowser
but does not fire theMouseWheel
event until the vertical scroll bar has fully reached either the top or the bottom. - Intercepting the
Message
forWM_MOUSEWHEEL
by overridingWndProc
andDefWndProc
both for a sample class inherited fromWebBrowser
and for the parent form applies only for the above conditions (withwParam
properly denotingMK_CONTROL
). - The
PreviewKeyDown
event fires when CTRL is pressed, as expected, but still does nothing in unison with the mouse wheel.
So I guess the Message
is being processed below the parent form and the managed control level and does not bubble up to where I can intercept or even handle it. Is there a way to do this, or some other way to simulate zooming in and out using CTRL-MouseWheel?
Thanks for reading!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
首先将
WebBrowser.Document.DomDocument
转换为 mshtml 命名空间中的正确接口,例如mshtml.HTMLDocumentEvents2_Event
,然后您可以处理(和取消)鼠标滚轮事件。我不确定,但我认为您需要在文档更改时连接事件处理程序,因此我在WebBrowser.DocumentCompleted
事件上执行此操作。我也不确定您是否需要释放任何 COM 对象。这太令人沮丧了,我让它工作并不再关心......
这里至少有一份解释基础知识的文档:如何在 Visual C# .NET 应用程序中处理文档事件
对于您的具体情况,只需根据
CTRL
是否有条件地压缩onmousewheel
事件即可键被按下。现在,如果您需要知道滚轮增量(滚动量),您将需要将事件对象转换为另一个接口。
First cast the
WebBrowser.Document.DomDocument
to the right interface in the mshtml namespace, likemshtml.HTMLDocumentEvents2_Event
, then you can handle (and cancel) mousewheel events. I'm not sure, but I think you need to wire up the event handler anytime the document is changed, so I do it on theWebBrowser.DocumentCompleted
event. I'm also not sure if you need to release any COM objects.This was frustrating enough that I got it to work and stopped caring...
Here is at least one document explaining the basics: How to handle document events in a Visual C# .NET application
For your specific case, just conditionally squash the
onmousewheel
event, based on whether or not theCTRL
key is pressed.Now if you need to know the Wheel Delta (scroll amount), you'll want to cast the events object to yet another interface.
也许使用 SetWindowsHookEx 来查找这些事件可能对您有用。这就是我用来获取 ActiveX MapPoint 控件顶部的滚轮事件的方法。
请注意,Windows 7 上存在一些怪癖,可能需要进行一些修改。有关更多详细信息,请在 MSDN 论坛上搜索 Windows 7 上的 SetWindowsHookEx。
Perhaps using SetWindowsHookEx to look for these events may work for you. This is what I've used to get scroll wheel events on top of the ActiveX MapPoint control.
Be aware there are some quirks with this on Windows 7 that may require some tinkering. For more details do a search for SetWindowsHookEx on Windows 7 on the MSDN forums.
要解决此问题,您必须侦听并处理以下消息:
它们由 Internet Explorer 调度。请参阅MSDN 上的注释。
To solve this problem you have to listen for and handle these messages:
They're dispatched by Internet Explorer. See the remarks on MSDN.
这是我用来禁用 ctrl+shift 的代码:
您需要更改最深层控件“Internet Explorer_Server”中 WndProc 的行为,
在您的网络浏览器准备就绪后执行此操作:
您可以从 MSDN 找到有关 WM_MOUSEWHEEL 的更多消息。
我从 MSDN 找到这个。但我忘记了链接,一旦找到,将附加在这里。
This is the code I used to disable ctrl+shift:
You need to change the behavior of WndProc in the deepest control "Internet Explorer_Server",
Do this after your web browser is ready:
You can find more message about WM_MOUSEWHEEL from MSDN.
I find this from MSDN. But I forgot the link, Once find, will append it here.
我无法让其中任何一个可靠地工作,因此经过一些(令人沮丧的)实验后,我想出了 TCC 发布的答案的衍生结果。我的网络浏览器控件托管在用户控件中。主要区别是我对 HTMLDocumentEvents2_Event 使用类级变量,这样我就可以成功取消订阅,并且我将 mshtml.IHTMLEventObj pEvtObj.Returnvalue 设置为 true.. 现在似乎工作得很好。
I couldn't get any of these to work reliably so after some (frustrating) experimentation, I came up with a derivative of the answer posted by TCC. My webbrowser control is hosted in a usercontrol. The main differences are I use a class-level variable for the HTMLDocumentEvents2_Event so I can unsubscribe successfully, and I set the mshtml.IHTMLEventObj pEvtObj.Returnvalue to true.. seems to work well now..