본문 바로가기

자료

[C# / VB.net] InputHelper.PressKey /하드웨어 키입력

728x90

 

블로그 인기글

● 메이플스토리 신규 룬패치/자동해제 프로그램 [링크 이동]

● 메이플스토리 거짓말탐지기 알림 프로그램 [링크 이동]

C#에서 TensorFlow 사용하는법 [링크 이동]


 가상 키 코드 대신 하드웨어 스캔 코드 를 보내는 것입니다 .

하드웨어 스캔 코드 동안, 키를 누를 때, 실제 키보드에 의해 전송 된 코드로 나타나는 가상 키 코드 키 인 검사 코드 (시스템에서 해석 참조 ).

그래서 몇 가지 WinAPI 함수를 사용하여 Zandronum (전체 화면 및 창 모두)에 키 입력을 보낼 수있었습니다.

  • SendInput() 실제 키보드 입력을 보내는 데 사용됩니다.
  • MapVirtualKeyEx() 키 코드를 스캔 코드로 변환하거나 그 반대로 변환하는 데 사용됩니다.
  • GetKeyboardLayout() 사용자의 현재 키보드 레이아웃을 얻는 데 사용됩니다 (예 : 스웨덴어 키보드가 있음).

내가 작성한 아래의 도우미 클래스 (또는 더 정확하게 : 래퍼)를 사용하면 이제 SendKeys.Send()포함 된 것보다 더 다양한 키를 사용하여 간단한 방식으로 키 입력 (하드웨어 여부)을 보낼 수 있습니다. System.Windows.Forms.Keys열거 형에 키를 사용할 수 있습니다 .

InputHelper.PressKey(Keys.Escape, True) 'True = Send key as hardware scan code.


 

Imports System.Runtime.InteropServices

Public NotInheritable Class InputHelper
    Private Sub New()
    End Sub

#Region "Methods"
#Region "PressKey()"
    ''' <summary>
    ''' Virtually presses a key.
    ''' </summary>
    ''' <param name="Key">The key to press.</param>
    ''' <param name="HardwareKey">Whether or not to press the key using its hardware scan code.</param>
    ''' <remarks></remarks>
    Public Shared Sub PressKey(ByVal Key As Keys, Optional ByVal HardwareKey As Boolean = False)
        If HardwareKey = False Then
            InputHelper.SetKeyState(Key, False)
            InputHelper.SetKeyState(Key, True)
        Else
            InputHelper.SetHardwareKeyState(Key, False)
            InputHelper.SetHardwareKeyState(Key, True)
        End If
    End Sub
#End Region

#Region "SetKeyState()"
    ''' <summary>
    ''' Virtually sends a key event.
    ''' </summary>
    ''' <param name="Key">The key of the event to send.</param>
    ''' <param name="KeyUp">Whether to push down or release the key.</param>
    ''' <remarks></remarks>
    Public Shared Sub SetKeyState(ByVal Key As Keys, ByVal KeyUp As Boolean)
        Key = ReplaceBadKeys(Key)

        Dim KeyboardInput As New KEYBDINPUT With {
            .wVk = Key,
            .wScan = 0,
            .time = 0,
            .dwFlags = If(KeyUp, KEYEVENTF.KEYUP, 0),
            .dwExtraInfo = IntPtr.Zero
        }

        Dim Union As New INPUTUNION With {.ki = KeyboardInput}
        Dim Input As New INPUT With {
            .type = INPUTTYPE.KEYBOARD,
            .U = Union
        }

        SendInput(1, New INPUT() {Input}, Marshal.SizeOf(GetType(INPUT)))
    End Sub
#End Region

#Region "SetHardwareKeyState()"
    ''' <summary>
    ''' Virtually sends a key event using the key's scan code.
    ''' </summary>
    ''' <param name="Key">The key of the event to send.</param>
    ''' <param name="KeyUp">Whether to push down or release the key.</param>
    ''' <remarks></remarks>
    Public Shared Sub SetHardwareKeyState(ByVal Key As Keys, ByVal KeyUp As Boolean)
        Key = ReplaceBadKeys(Key)

        Dim KeyboardInput As New KEYBDINPUT With {
            .wVk = 0,
            .wScan = MapVirtualKeyEx(CUInt(Key), 0, GetKeyboardLayout(0)),
            .time = 0,
            .dwFlags = KEYEVENTF.SCANCODE Or If(KeyUp, KEYEVENTF.KEYUP, 0),
            .dwExtraInfo = IntPtr.Zero
        }

        Dim Union As New INPUTUNION With {.ki = KeyboardInput}
        Dim Input As New INPUT With {
            .type = INPUTTYPE.KEYBOARD,
            .U = Union
        }

        SendInput(1, New INPUT() {Input}, Marshal.SizeOf(GetType(INPUT)))
    End Sub
#End Region

#Region "ReplaceBadKeys()"
    ''' <summary>
    ''' Replaces bad keys with their corresponding VK_* value.
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared Function ReplaceBadKeys(ByVal Key As Keys) As Keys
        Dim ReturnValue As Keys = Key

        If ReturnValue.HasFlag(Keys.Control) Then
            ReturnValue = (ReturnValue And Not Keys.Control) Or Keys.ControlKey 'Replace Keys.Control with Keys.ControlKey.
        End If

        If ReturnValue.HasFlag(Keys.Shift) Then
            ReturnValue = (ReturnValue And Not Keys.Shift) Or Keys.ShiftKey 'Replace Keys.Shift with Keys.ShiftKey.
        End If

        If ReturnValue.HasFlag(Keys.Alt) Then
            ReturnValue = (ReturnValue And Not Keys.Alt) Or Keys.Menu 'Replace Keys.Alt with Keys.Menu.
        End If

        Return ReturnValue
    End Function
#End Region
#End Region

#Region "WinAPI P/Invokes"
    <DllImport("user32.dll", SetLastError:=True)>
    Private Shared Function SendInput(ByVal nInputs As UInteger, <MarshalAs(UnmanagedType.LPArray)> ByVal pInputs() As INPUT, ByVal cbSize As Integer) As UInteger
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function MapVirtualKeyEx(uCode As UInteger, uMapType As UInteger, dwhkl As IntPtr) As UInteger
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function GetKeyboardLayout(idThread As UInteger) As IntPtr
    End Function

#Region "Enumerations"
    Private Enum INPUTTYPE As UInteger
        MOUSE = 0
        KEYBOARD = 1
        HARDWARE = 2
    End Enum

    <Flags()> _
    Private Enum KEYEVENTF As UInteger
        EXTENDEDKEY = &H1
        KEYUP = &H2
        SCANCODE = &H8
        UNICODE = &H4
    End Enum
#End Region

#Region "Structures"
    <StructLayout(LayoutKind.Explicit)> _
    Private Structure INPUTUNION
        <FieldOffset(0)> Public mi As MOUSEINPUT
        <FieldOffset(0)> Public ki As KEYBDINPUT
        <FieldOffset(0)> Public hi As HARDWAREINPUT
    End Structure

    Private Structure INPUT
        Public type As Integer
        Public U As INPUTUNION
    End Structure

    Private Structure MOUSEINPUT
        Public dx As Integer
        Public dy As Integer
        Public mouseData As Integer
        Public dwFlags As Integer
        Public time As Integer
        Public dwExtraInfo As IntPtr
    End Structure

    Private Structure KEYBDINPUT
        Public wVk As UShort
        Public wScan As Short
        Public dwFlags As UInteger
        Public time As Integer
        Public dwExtraInfo As IntPtr
    End Structure

    Private Structure HARDWAREINPUT
        Public uMsg As Integer
        Public wParamL As Short
        Public wParamH As Short
    End Structure
#End Region
#End Region
End Class

 

MSDN에서 스캔 코드 목록을 찾을수 있습니다. https://msdn.microsoft.com/en-us/library/aa299374(v=vs.60).aspx

 

 

728x90