0

MouseWheelフォーム レベルで生成されたイベントを転送しWebBrowserて、そのコントロールにフォーカスがない場合でも、埋め込みコントロールによって処理されるようにしたいと考えていました。

これが私がやったことです:

  1. 実装されIMessageFilter.PreFilterMessageました。
  2. でフィルタを登録しましたApplication.AddMessageFilter
  3. フィルターで、WM_MOUSEWHEELメッセージをリッスンします。
  4. 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);
}

これは動作しません。何も起こりません。

ただし、 a の代わりに aWebBrowserをターゲットとして指定するPanelと、これは非常にうまく機能します。

4

2 に答える 2

1

Spy++ で調査したところWebBrowser、WinForms のコントロールが複数のコンテナー層を使用して実際の 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);
}
于 2013-06-21T05:07:20.700 に答える
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
于 2014-11-08T11:36:47.150 に答える