如何从应用程序中捕获鼠标窗口消息?

时间:2014-05-13 09:00:59

标签: .net vb.net winforms windows-messages

首先抱歉'因为这对于C#可能是一个过于本地化的问题,但无论如何我没有找到VB.NET的相关信息,而且我的理解程度不高C# {1}}代码。

基本上我需要从应用程序中捕获/处理一些鼠标消息。

我怎么能这样做?

这只是我需要在应用程序之外重现的代码示例:

Protected Overrides Sub WndProc(ByRef m As Message)

    Select Case m.Msg

        Case &H200 ' WM_MOUSEMOVE
            MsgBox("Mouse Move")

        Case &H201 ' WM_LBUTTONDOWN
            MsgBox("Left Button Down")

        Case &H202 ' WM_LBUTTONUP 
            MsgBox("Left Button Up")

        Case Else
            MyBase.WndProc(m)

    End Select

End Sub

主要思想是按下一个隐藏应用程序的按钮,让用户在屏幕上选择一个区域,我需要捕获那些窗口消息,以便知道何时需要开始/结束区域选择。

3 个答案:

答案 0 :(得分:2)

有两种方法可以做到这一点。

  1. 使用全局挂钩(Google it) 我不推荐。

  2. 让你的winform透明。

  3. 你需要设置ur winform的透明颜色作为背景控制颜色。要使表单不可聚焦,您需要将此代码添加到您的消息处理程序

    if (m.Msg == WM_MOUSEACTIVATE)
    {
        m.Result = new IntPtr(MA_NOACTIVATE);
        return;
    }  
    

    如果您想接收左键单击消息,只需在MouseActivate按摩之前添加此代码。

    if (m.Msg == WM_LBUTTONDOWN)
    {
    } 
    

    完整示例

    namespace
    {
        public partial class XXXXXForm : Form
        {
            private const int WM_MOUSEACTIVATE = 0x21;
            private const int WM_LBUTTONDOWN = 0x0201;
            private const int MK_LBUTTON = 0x0001;
            private const int MA_NOACTIVATE = 3;
    
            public ClockForm()
            {
                InitializeComponent();
    
                this.DoubleBuffered = true;
                this.TopMost = true;
                this.FormBorderStyle = FormBorderStyle.None;
                this.ShowIcon = false;
                this.ShowInTaskbar = false;
                this.TransparencyKey = this.BackColor;
    
            }
    
    
            [DllImport("User32.dll", EntryPoint = "SendMessage")]
            private extern static int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
            [DllImport("user32.dll")]
            public static extern bool ReleaseCapture();
            private const int WM_SYSCOMMAND = 0x112;
            private const int SC_MOVE = 0xF010;
            private const int HTCAPTION = 0x0002;
    
    
            protected override void WndProc(ref Message m)
            {
    
                if (m.Msg == WM_LBUTTONDOWN)
                {
    ...
                }
                else if (m.Msg == WM_MOUSEACTIVATE)
                {
                    m.Result = new IntPtr(MA_NOACTIVATE);
                    return;
                }
                base.WndProc(ref m);
    
            }
    
            protected override bool ShowWithoutActivation
            {
                get
                {
                    return false;
                }
            }
    
            private void Form_Paint(object sender, PaintEventArgs e)
            {
    
            }
    
        }
    }
    

答案 1 :(得分:2)

首先,我不太确定你的问题,因为你问如何接收Windows消息来捕获一个区域。但根据我的理解,您甚至不需要Windows消息来捕获屏幕上的区域。

这是一个小例子,它有点儿马车但检查出来。

[DllImport("User32.dll")]
public static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("User32.dll")]
public static extern void ReleaseDC(IntPtr hwnd, IntPtr dc);
[DllImport("user32.dll")]
static extern bool InvalidateRect(IntPtr hWnd, IntPtr lpRect, bool bErase);
Rectangle rect;
bool drawmode = false;
Point startLoc;
Point CurrentLoc;

private void button1_Click(object sender, EventArgs e)
{
    if (!drawmode)
    {
        WindowState = FormWindowState.Maximized;
        Opacity = 0.01;
        drawmode = true;
    }
}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        CurrentLoc = Cursor.Position;
        IntPtr desktopPtr = GetDC(IntPtr.Zero);
        Graphics g = Graphics.FromHdc(desktopPtr);

        InvalidateRect(IntPtr.Zero, IntPtr.Zero, true);
        rect = new Rectangle(startLoc.X, startLoc.Y, CurrentLoc.X - startLoc.X, CurrentLoc.Y - startLoc.Y);
        g.DrawRectangle(Pens.Red, rect);

        g.Dispose();
        ReleaseDC(IntPtr.Zero, desktopPtr);
    }
    else
    {
        startLoc = Cursor.Position;
    }
}

private void Form1_MouseClick(object sender, MouseEventArgs e)
{
    if (drawmode)
    {
        WindowState = FormWindowState.Normal;
        Opacity = 1;
        drawmode = false;
        // do somthing with rect after selection
    }
}

我不认为这是你正在寻找的,但我相信这可以帮助有人下线。

答案 2 :(得分:0)

我发现here是一个适用于我所有需求的通用鼠标钩子

代码(需要XML文档,还需要为我的案例清除不必要的说明,但只是为了展示它):

  

编辑:

代码已更新。

#Region " Imports "

Imports System.Runtime.InteropServices
Imports System.ComponentModel
Imports System.Reflection

#End Region

''' <summary>
''' Class MouseHook.
''' </summary>
Public Class MouseHook

#Region " WinAPI "

#Region " Methods "

    ''' <summary>
    ''' Passes the hook information to the next hook procedure in the current hook chain. 
    ''' A hook procedure can call this function either before or after processing the hook information.
    ''' For more info see here:
    ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms644974%28v=vs.85%29.aspx
    ''' </summary>
    ''' <param name="idHook">
    ''' This parameter is ignored.
    ''' </param>
    ''' <param name="nCode">
    ''' The hook code passed to the current hook procedure. 
    ''' The next hook procedure uses this code to determine how to process the hook information.
    ''' </param>
    ''' <param name="wParam">
    ''' The wParam value passed to the current hook procedure. 
    ''' The meaning of this parameter depends on the type of hook associated with the current hook chain.
    ''' </param>
    ''' <param name="lParam">
    ''' The lParam value passed to the current hook procedure. 
    ''' The meaning of this parameter depends on the type of hook associated with the current hook chain.
    ''' </param>
    ''' <returns>
    ''' This value is returned by the next hook procedure in the chain. 
    ''' The current hook procedure must also return this value. 
    ''' The meaning of the return value depends on the hook type. 
    ''' For more information, see the descriptions of the individual hook procedures.
    ''' </returns>
    <DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Auto)>
    Private Shared Function CallNextHookEx(
           ByVal idHook As Integer,
           ByVal nCode As Integer,
           ByVal wParam As Integer,
           ByVal lParam As MSLLHOOKSTRUCT
    ) As Integer
    End Function

    ''' <summary>
    ''' Installs an application-defined hook procedure into a hook chain. 
    ''' You would install a hook procedure to monitor the system for certain types of events. 
    ''' These events are associated either with a specific thread 
    ''' or with all threads in the same desktop as the calling thread.
    ''' For more info see here:
    ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990%28v=vs.85%29.aspx
    ''' </summary>
    ''' <param name="idHook">
    ''' The type of hook procedure to be installed.
    ''' </param>
    ''' <param name="lpfn">
    ''' A pointer to the hook procedure. 
    ''' If the dwThreadId parameter is zero or specifies the identifier of a thread created by a different process, 
    ''' the lpfn parameter must point to a hook procedure in a DLL. 
    ''' Otherwise, lpfn can point to a hook procedure in the code associated with the current process.
    ''' </param>
    ''' <param name="hInstance">
    ''' A handle to the DLL containing the hook procedure pointed to by the lpfn parameter. 
    ''' The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by 
    ''' the current process and if the hook procedure is within the code associated with the current process.
    ''' </param>
    ''' <param name="threadId">
    ''' The identifier of the thread with which the hook procedure is to be associated. 
    ''' For desktop apps, if this parameter is zero, the hook procedure is associated 
    ''' with all existing threads running in the same desktop as the calling thread. 
    ''' </param>
    ''' <returns>
    ''' If the function succeeds, the return value is the handle to the hook procedure.
    ''' If the function fails, the return value is NULL.
    ''' </returns>
    <DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Auto)>
    Private Shared Function SetWindowsHookEx(
           ByVal idHook As HookType,
           ByVal lpfn As MouseProcDelegate,
           ByVal hInstance As IntPtr,
           ByVal threadId As Integer
    ) As Integer
    End Function

    ''' <summary>
    ''' Removes a hook procedure installed in a hook chain by the 'SetWindowsHookEx' function.
    ''' For more info see here:
    ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms644993%28v=vs.85%29.aspx
    ''' </summary>
    ''' <param name="idHook">
    ''' A handle to the hook to be removed. 
    ''' This parameter is a hook handle obtained by a previous call to SetWindowsHookEx.
    ''' </param>
    ''' <returns>
    ''' If the function succeeds, the return value is nonzero.
    ''' If the function fails, the return value is zero.
    ''' </returns>
    <DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Auto)>
    Private Shared Function UnhookWindowsHookEx(
           ByVal idHook As Integer
    ) As Boolean
    End Function

#End Region

#Region " Enums "

    ''' <summary>
    ''' Indicates a type of Hook procedure to be installed.
    ''' </summary>
    <Description("Enum used in 'idHook' parameter of 'SetWindowsHookEx' function")>
    Private Enum HookType As Integer

        ' **************************************
        ' This enumeration is partially defined.
        ' **************************************

        ''' <summary>
        ''' Installs a hook procedure that monitors low-level mouse input events. 
        ''' For more information, see the LowLevelMouseProc hook procedure.
        ''' </summary>
        WH_MOUSE_LL = 14

    End Enum

#End Region

#Region " Structures "

    ''' <summary>
    ''' Contains information about a low-level mouse input event.
    ''' </summary>
    <Description("Structure used in 'lParam' parameter of 'CallNextHookEx' function")>
    Private Structure MSLLHOOKSTRUCT

        ''' <summary>
        ''' The ptThe x- and y-coordinates of the cursor, in screen coordinates.
        ''' </summary>
        Public pt As Point

        ''' <summary>
        ''' If the message is 'WM_MOUSEWHEEL', the high-order word of this member is the wheel delta. 
        ''' The low-order word is reserved. 
        ''' A positive value indicates that the wheel was rotated forward, away from the user; 
        ''' a negative value indicates that the wheel was rotated backward, toward the user. 
        ''' One wheel click is defined as 'WHEEL_DELTA', which is '120'.
        ''' </summary>
        Public mouseData As Integer

        ''' <summary>
        ''' The event-injected flag.
        ''' </summary>
        Public flags As Integer

        ''' <summary>
        ''' The time stamp for this message. 
        ''' </summary>
        Public time As Integer

        ''' <summary>
        ''' Additional information associated with the message.
        ''' </summary>
        Public dwExtraInfo As Integer

    End Structure

#End Region

#End Region

#Region " Variables "

    ''' <summary>
    ''' 
    ''' </summary>
    Private MouseHook As Integer

#End Region

#Region " Delegates "

    ''' <summary>
    ''' Delegate MouseProcDelegate
    ''' </summary>
    ''' <returns>System.Int32.</returns>
    Private Delegate Function MouseProcDelegate(
            ByVal nCode As Integer,
            ByVal wParam As Integer,
            ByRef lParam As MSLLHOOKSTRUCT
    ) As Integer

    ''' <summary>
    ''' 
    ''' </summary>
    Private MouseHookDelegate As MouseProcDelegate

#End Region

#Region " Enums "

    ''' <summary>
    ''' Indicates a Windows Message related to a mouse events.
    ''' For more info see here:
    ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ff468877%28v=vs.85%29.aspx
    ''' </summary>
    Private Enum MouseWindowsMessages As Integer

        ''' <summary>
        ''' Posted to a window when the cursor moves. 
        ''' If the mouse is not captured, the message is posted to the window that contains the cursor. 
        ''' Otherwise, the message is posted to the window that has captured the mouse
        ''' </summary>
        WM_MOUSEMOVE = &H200

        ''' <summary>
        ''' Posted when the user presses the left mouse button while the cursor is in the client area of a window.
        ''' If the mouse is not captured, the message is posted to the window beneath the cursor.
        ''' Otherwise, the message is posted to the window that has captured the mouse
        ''' </summary>
        WM_LBUTTONDOWN = &H201

        ''' <summary>
        ''' Posted when the user releases the left mouse button while the cursor is in the client area of a window. 
        ''' If the mouse is not captured, the message is posted to the window beneath the cursor. 
        ''' Otherwise, the message is posted to the window that has captured the mouse
        ''' </summary>
        WM_LBUTTONUP = &H202

        ''' <summary>
        ''' Posted when the user double-clicks the left mouse button while the cursor is in the client area of a window. 
        ''' If the mouse is not captured, the message is posted to the window beneath the cursor. 
        ''' Otherwise, the message is posted to the window that has captured the mouse
        ''' </summary>
        WM_LBUTTONDBLCLK = &H203

        ''' <summary>
        ''' Posted when the user presses the right mouse button while the cursor is in the client area of a window. 
        ''' If the mouse is not captured, the message is posted to the window beneath the cursor. 
        ''' Otherwise, the message is posted to the window that has captured the mouse
        ''' </summary>
        WM_RBUTTONDOWN = &H204

        ''' <summary>
        ''' Posted when the user releases the right mouse button while the cursor is in the client area of a window. 
        ''' If the mouse is not captured, the message is posted to the window beneath the cursor. 
        ''' Otherwise, the message is posted to the window that has captured the mouse
        ''' </summary>
        WM_RBUTTONUP = &H205

        ''' <summary>
        ''' Posted when the user double-clicks the right mouse button while the cursor is in the client area of a window. 
        ''' If the mouse is not captured, the message is posted to the window beneath the cursor. 
        ''' Otherwise, the message is posted to the window that has captured the mouse
        ''' </summary>
        WM_RBUTTONDBLCLK = &H206

        ''' <summary>
        ''' Posted when the user presses the middle mouse button while the cursor is in the client area of a window. 
        ''' If the mouse is not captured, the message is posted to the window beneath the cursor. 
        ''' Otherwise, the message is posted to the window that has captured the mouse
        ''' </summary>
        WM_MBUTTONDOWN = &H207

        ''' <summary>
        ''' Posted when the user releases the middle mouse button while the cursor is in the client area of a window. 
        ''' If the mouse is not captured, the message is posted to the window beneath the cursor. 
        ''' Otherwise, the message is posted to the window that has captured the mouse
        ''' </summary>
        WM_MBUTTONUP = &H208

        ''' <summary>
        ''' Posted when the user double-clicks the middle mouse button while the cursor is in the client area of a window. 
        ''' If the mouse is not captured, the message is posted to the window beneath the cursor. 
        ''' Otherwise, the message is posted to the window that has captured the mouse
        ''' </summary>
        WM_MBUTTONDBLCLK = &H209

        ''' <summary>
        ''' Sent to the active window when the mouse's horizontal scroll wheel is tilted or rotated. 
        ''' The DefWindowProc function propagates the message to the window's parent. 
        ''' There should be no internal forwarding of the message, 
        ''' since DefWindowProc propagates it up the parent chain until it finds a window that processes it.
        ''' </summary>
        WM_MOUSEWHEEL = &H20A

    End Enum

    ''' <summary>
    ''' Indicates the whell direction of the mouse.
    ''' </summary>
    Public Enum WheelDirection

        ''' <summary>
        ''' The wheel is moved up.
        ''' </summary>
        WheelUp

        ''' <summary>
        ''' The wheel is moved down.
        ''' </summary>
        WheelDown

    End Enum

#End Region

#Region " Events "

    ''' <summary>
    ''' Occurs when the mouse moves.
    ''' </summary>
    Public Event MouseMove(ByVal ptLocat As Point)

    ''' <summary>
    ''' Occurs when the mouse left button is pressed.
    ''' </summary>
    Public Event MouseLeftDown(ByVal ptLocat As Point)

    ''' <summary>
    ''' Occurs when the mouse left button is released.
    ''' </summary>
    Public Event MouseLeftUp(ByVal ptLocat As Point)

    ''' <summary>
    ''' Occurs when the mouse left button is double-clicked.
    ''' </summary>
    Public Event MouseLeftDoubleClick(ByVal ptLocat As Point)

    ''' <summary>
    ''' Occurs when the mouse right button is pressed.
    ''' </summary>
    Public Event MouseRightDown(ByVal ptLocat As Point)

    ''' <summary>
    ''' Occurs when the mouse right button is released.
    ''' </summary>
    Public Event MouseRightUp(ByVal ptLocat As Point)

    ''' <summary>
    ''' Occurs when the mouse right button is double-clicked.
    ''' </summary>
    Public Event MouseRightDoubleClick(ByVal ptLocat As Point)

    ''' <summary>
    ''' Occurs when the mouse middle button is pressed.
    ''' </summary>
    Public Event MouseMiddleDown(ByVal ptLocat As Point)

    ''' <summary>
    ''' Occurs when the mouse middle button is released.
    ''' </summary>
    Public Event MouseMiddleUp(ByVal ptLocat As Point)

    ''' <summary>
    ''' Occurs when the mouse middle button is double-clicked.
    ''' </summary>
    Public Event MouseMiddleDoubleClick(ByVal ptLocat As Point)

    ''' <summary>
    ''' Occurs when [mouse move].
    ''' </summary>
    Public Event MouseWheel(ByVal ptLocat As Point,
                            ByVal Direction As WheelDirection)

#End Region

#Region " Constructors "

    ''' <summary>
    ''' Initializes a new instance of this class.
    ''' </summary>
    Public Sub New()

        MouseHookDelegate = New MouseProcDelegate(AddressOf MouseProc)

        MouseHook = SetWindowsHookEx(HookType.WH_MOUSE_LL,
                                     MouseHookDelegate,
                                     Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly.GetModules()(0)).ToInt32, 0)
    End Sub

#End Region

#Region " Protected Methods "

    ''' <summary>
    ''' Allows an object to try to free resources 
    ''' and perform other cleanup operations before it is reclaimed by garbage collection.
    ''' </summary>
    Protected Overrides Sub Finalize()

        UnhookWindowsHookEx(MouseHook)
        MyBase.Finalize()

    End Sub

#End Region

#Region " Private Methods "

    ''' <summary>
    ''' Processes the mouse windows messages and raises it's corresponding events.
    ''' </summary>
    ''' <returns>System.Int32.</returns>
    Private Function MouseProc(ByVal nCode As Integer,
                               ByVal wParam As Integer,
                               ByRef lParam As MSLLHOOKSTRUCT
    ) As Integer

        If nCode = 0 Then

            Select Case wParam

                Case MouseWindowsMessages.WM_MOUSEMOVE
                    RaiseEvent MouseMove(lParam.pt)

                Case MouseWindowsMessages.WM_LBUTTONDOWN
                    RaiseEvent MouseLeftDown(lParam.pt)

                Case MouseWindowsMessages.WM_LBUTTONUP
                    RaiseEvent MouseLeftUp(lParam.pt)

                Case MouseWindowsMessages.WM_LBUTTONDBLCLK
                    RaiseEvent MouseLeftDoubleClick(lParam.pt)

                Case MouseWindowsMessages.WM_RBUTTONDOWN
                    RaiseEvent MouseRightDown(lParam.pt)

                Case MouseWindowsMessages.WM_RBUTTONUP
                    RaiseEvent MouseRightUp(lParam.pt)

                Case MouseWindowsMessages.WM_RBUTTONDBLCLK
                    RaiseEvent MouseRightDoubleClick(lParam.pt)

                Case MouseWindowsMessages.WM_MBUTTONDOWN
                    RaiseEvent MouseMiddleDown(lParam.pt)

                Case MouseWindowsMessages.WM_MBUTTONUP
                    RaiseEvent MouseMiddleUp(lParam.pt)

                Case MouseWindowsMessages.WM_MBUTTONDBLCLK
                    RaiseEvent MouseMiddleDoubleClick(lParam.pt)

                Case MouseWindowsMessages.WM_MOUSEWHEEL
                    Dim wDirection As WheelDirection
                    If lParam.mouseData < 0 Then
                        wDirection = WheelDirection.WheelDown
                    Else
                        wDirection = WheelDirection.WheelUp
                    End If
                    RaiseEvent MouseWheel(lParam.pt, wDirection)

            End Select

        End If

        Return CallNextHookEx(MouseHook, nCode, wParam, lParam)

    End Function

#End Region

End Class

使用示例:

Public Class Form1


Private WithEvents mHook As New MouseHook

Private Sub mHook_Mouse_Left_Down(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Left_Down
    MsgBox("Mouse Left Down At: (" & ptLocat.X & "," & ptLocat.Y & ")")
End Sub

Private Sub mHook_Mouse_Left_Up(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Left_Up
    MsgBox("Mouse Left Up At: (" & ptLocat.X & "," & ptLocat.Y & ")")
End Sub

Private Sub mHook_Mouse_Move(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Move
    'Will be called every time the mouse moves
End Sub

End Class