我想转发在表单级别生成的MouseWheel
个事件,以便嵌入式WebBrowser
控件处理这些事件,即使该控件没有焦点也是如此。
这就是我所做的:
IMessageFilter.PreFilterMessage
。Application.AddMessageFilter
注册过滤器。WM_MOUSEWHEEL
条消息。SendMessage
将消息转发给目标控件(在我的情况下为WebBrowser
)。在代码中,这看起来像这样:
bool IMessageFilter.PreFilterMessage(ref Message m)
{
if (m.Msg == 0x20A) // WM_MOUSEWHEEL
{
if (this.target != null)
{
var handle = this.target.Handle;
Native.SendMessage (handle, m.Message, m.WParam, m.LParam);
return true;
}
}
return false;
}
// Registering the message filter:
System.Windows.Forms.Application.AddMessageFilter (this);
// Win32 code:
protected static class NativeMethods
{
[System.Runtime.InteropServices.DllImport ("user32.dll")]
public static extern System.IntPtr SendMessage(System.IntPtr hWnd, System.Int32 Msg, System.IntPtr wParam, System.IntPtr lParam);
}
这不起作用。没有任何事情发生。
但是,如果不是WebBrowser
而是指定Panel
作为目标,那么这种效果非常好。
答案 0 :(得分:1)
使用Spy ++进行调查显示,WinForms中的WebBrowser
控件使用多层容器来包装真实的IE组件:
System.Windows.Forms.WebBrowser
Shell Embedding
Shell DocObject View
Internet Explorer_Server
将事件发送到任何容器都不会有任何影响。 WM_MOUSEWHEEL
事件必须发送到Internet Explorer_Server
句柄才能生效。
以下是修改后的代码,它通过挖掘容器来找到IE组件:
bool IMessageFilter.PreFilterMessage(ref Message m)
{
if (m.Msg == 0x20A) // WM_MOUSEWHEEL
{
if (this.target != null)
{
var handle = this.target.Handle;
handle = NativeMethods.FindWindowEx (handle, IntPtr.Zero, "Shell Embedding", null);
handle = NativeMethods.FindWindowEx (handle, IntPtr.Zero, "Shell DocObject View", null);
handle = NativeMethods.FindWindowEx (handle, IntPtr.Zero, "Internet Explorer_Server", null);
Native.SendMessage (handle, m.Msg, m.WParam, m.LParam);
return true;
}
}
return false;
}
protected static class NativeMethods
{
[System.Runtime.InteropServices.DllImport ("user32.dll")]
public static extern System.IntPtr SendMessage(System.IntPtr hWnd, System.Int32 Msg, System.IntPtr wParam, System.IntPtr lParam);
[System.Runtime.InteropServices.DllImport ("user32.dll")]
public static extern System.IntPtr FindWindowEx(System.IntPtr hwndParent, System.IntPtr hwndChildAfter, string className, string windowName);
}
答案 1 :(得分:1)
皮埃尔的回答对我有用(不能投票,因为没有足够的声誉)。但是,它需要调整才能在VB.NET中工作,所以我想我会发帖以防有人坚持这一点:
Imports System.Runtime.InteropServices
Public Class Form1 Implements IMessageFilter
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
System.Windows.Forms.Application.AddMessageFilter(Me)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.WebBrowser1.Navigate("D:\Development\test3.html")
End Sub
Private Function IMessageFilter_PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage
If m.Msg = &H20A Then
' WM_MOUSEWHEEL
If m.HWnd <> 0 Then
Dim handle = m.HWnd
handle = NativeMethods.FindWindowEx(handle, IntPtr.Zero, "Shell Embedding", Nothing)
handle = NativeMethods.FindWindowEx(handle, IntPtr.Zero, "Shell DocObject View", Nothing)
handle = NativeMethods.FindWindowEx(handle, IntPtr.Zero, "Internet Explorer_Server", Nothing)
NativeMethods.SendMessage(handle, m.Msg, m.WParam, m.LParam)
Return True
End If
End If
Return False
End Function
Protected NotInheritable Class NativeMethods
Private Sub New()
End Sub
<System.Runtime.InteropServices.DllImport("user32.dll")> _
Public Shared Function SendMessage(hWnd As System.IntPtr, Msg As System.Int32, wParam As System.IntPtr, lParam As System.IntPtr) As System.IntPtr
End Function
<System.Runtime.InteropServices.DllImport("user32.dll")> _
Public Shared Function FindWindowEx(hwndParent As System.IntPtr, hwndChildAfter As System.IntPtr, className As String, windowName As String) As System.IntPtr
End Function
End Class
End Class