首页 文章

捕获鼠标和键盘事件以及在C#中“阻止系统传播”

提问于
浏览
3

我正在寻找 detect mouse and keyboards events in C# 的方法并读取它们(光标位置键击) . 我读了很多"keyboard hook"的东西,但我的问题是我要 grab 这些事件和 then "neutralize" them ,我不知道怎么说 .

与Virtual Box类似的东西:它拦截鼠标和键盘而不是它们到主机系统,所以,例如,我可以按 CTRL+TAB ,拦截它并防止窗口切换对话框弹出...

显然我会定义一个特殊的键(例如 RCTRL )让我停止钩子,在其他地方我永远无法控制回主机:)

1 回答

  • 1

    这是我在VB.NET中使用的模块(我会尽可能地翻译它,但是有一个在线工具可以自动完成):

    Imports System.Runtime.InteropServices
    
    Public Module KeyboardHook
        <DllImport("user32.dll")>
        Public Function SetWindowsHookEx(ByVal idHook As Integer, ByVal HookProc As KBDLLHookProc, ByVal hInstance As IntPtr, ByVal wParam As Integer) As IntPtr
    
        End Function
    
        <DllImport("user32.dll")>
        Public Function CallNextHookEx(ByVal idHook As IntPtr, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    
        End Function
    
        <DllImport("user32.dll")>
        Public Function UnhookWindowsHookEx(ByVal idHook As IntPtr) As Boolean
    
        End Function
    
        <StructLayout(LayoutKind.Sequential)>
        Public Structure KBDLLHOOKSTRUCT
            Public vkCode As UInteger
            Public scanCode As UInteger
            Public flags As KBDLLHOOKSTRUCTFlags
            Public time As UInteger
            Public dwExtraInfo As UIntPtr
        End Structure
    
        <Flags()>
        Public Enum KBDLLHOOKSTRUCTFlags As UInteger
            LLKHF_EXTENDED = &H1
            LLKHF_INJECTED = &H10
            LLKHF_ALTDOWN = &H20
            LLKHF_UP = &H80
        End Enum
    
        Public Const WH_KEYBOARD_LL As Integer = 13
        Public Const HC_ACTION As Integer = 0
        Public Const WM_KEYDOWN As Integer = &H100
        Public Const WM_KEYUP As Integer = &H101
        Public Const WM_SYSKEYDOWN As Integer = &H104
        Public Const WM_SYSKEYUP As Integer = &H105
    
        Public Delegate Function KBDLLHookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    End Module
    

    以下是如何使用它来取消每个按键:

    Private hook As IntPtr
    Private isVisible As Boolean = False
    Private keyHookDelegate As New KBDLLHookProc(AddressOf Me.KeyHook)
    
    Private Sub Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'Set the key hook:
        hook = SetWindowsHookEx(KeyboardHook.WH_KEYBOARD_LL, Me.keyHookDelegate, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()(0)), 0)
    
        If hook = IntPtr.Zero Then
            MessageBox.Show("Failed to set global key hook.", "Key Hook Set Failiure", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Throw New ApplicationException("Failed to set key hook.")
        End If
    End Sub
    
    Private Function KeyHook(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
        If nCode = KeyboardHook.HC_ACTION Then
            Dim p As Integer = wParam.ToInt32()
    
            If p = WM_KEYDOWN OrElse p = WM_SYSKEYDOWN Then
                Dim keyCode As Keys = CType(CType(Marshal.PtrToStructure(lParam, GetType(KBDLLHOOKSTRUCT)), KBDLLHOOKSTRUCT).vkCode, Keys) ' This gets the key that was pressed.
    
                'Cancel it!
                Return 1
            End If
        End If
    
        Return KeyboardHook.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam)
    End Function
    
    Protected Overrides Sub Finalize()
        Try
            'Remove the key hook:
            If hook <> IntPtr.Zero Then KeyboardHook.UnhookWindowsHookEx(hook)
        Finally
            MyBase.Finalize()
        End Try
    End Sub
    

    至于鼠标部分,VirtualBox实际上并没有取消所有鼠标交互 . 它使用鼠标集成,它允许你像往常一样使用鼠标(你不必在这里做一件事),或者它将捕获的鼠标限制在某个区域 . 您可以通过设置鼠标边界在.NET中完成此操作:

    System.Windows.Forms.Cursor.Clip = new Rectangle(this.PointToScreen(Point.Empty), this.ClientSize);
    

    根据您的需要,您可能还想隐藏光标 .

相关问题