将MouseWheel消息发送到System.Windows.Forms.WebBrowser

时间:2013-06-21 05:07:21

标签: winforms webbrowser-control mousewheel

我想转发在表单级别生成的MouseWheel个事件,以便嵌入式WebBrowser控件处理这些事件,即使该控件没有焦点也是如此。

这就是我所做的:

  1. 已实施IMessageFilter.PreFilterMessage
  2. 使用Application.AddMessageFilter注册过滤器。
  3. 在过滤器中,收听WM_MOUSEWHEEL条消息。
  4. 使用SendMessage将消息转发给目标控件(在我的情况下为WebBrowser)。
  5. 在代码中,这看起来像这样:

    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作为目标,那么这种效果非常好。

2 个答案:

答案 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