3

C#でマウスとキーボードのイベントを検出して読み取る方法を探しています(カーソル位置+キーストローク)。私は多くの「キーボードフック」のものを読みましたが、私の問題は、これらのイベントをキャプチャしてから「中和」したいということです。それを言う方法がわかりません。

Virtual Boxの動作に似たもの: マウスとキーボードをインターセプトし、それらをホスト システムに「伝播」しないため、たとえば、 を押しCTRL+TABてインターセプトし、ウィンドウの切り替えダイアログがポップアップするのを防ぐことができます...

明らかに、フックを停止できる特別なキー(RCTRLたとえば)を定義します。他の場所では、ホストに制御を戻すことはありません:)

4

1 に答える 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);

必要に応じて、カーソルを非表示にすることもできます。

于 2012-06-16T18:28:26.380 に答える