2016-11-29 28 views
0

이것은 더 이상 해결책이 아닙니다. 나는 조이스틱 (DX 버튼을 보낸다)의 키를 누를 수있게 해주는 루틴을 코드화하고, 동시에 아래쪽 위치에있는 키를 누르고있는 것을 시뮬레이션 해왔다. 기본적으로 3 줄의 코드로 바뀌 었습니다.키를 누른 다음 놓기

10. Public Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long) 

    20. If (condition=true) then 
    30.  keybd_event(Keys.Scroll, 0, 0, 0) 
    40. Else 
    50.  keybd_event(Keys.Scroll, 0, 2, 0) 
    60. EndIf 

편의상 줄 번호가 추가되었습니다. 보시다시피, 20 번 줄은 SCROLL LOCK 키를 누르고 30 번 줄은 다시 해제합니다. 코드가 내 필요에 완벽하게 작동하지만 (1 시간 35 분의 세션에서 팔콘 BMS 4.33U2, IVC 클라이언트 및 FRAPS에서 아무런 문제가 발생하지 않음)이 기능을 사용하려면 디버그> 예외>를 사용하여 MDA를 비활성화해야했습니다. 관리 디버깅 도우미> PInvokeStackImbalance (Throw).

내 질문은 -이 프로그램을 "안전한"방법입니까, 다른 말로하면 내가 이것을 작동 시키도록 어딘가에 속였다는 것입니까? 그것이 "안전하지 않은 경우"같은 일을하는 적절한 방법이 있습니까?

+0

''선언


는 오늘 방법 SendInput() 권장 사용하려면, 당신은 내 InputHelper 클래스를 이용할 수있다. ..Lib'. 현재 키보드/마우스 이벤트를 보내는 방법은 [**'SendInput()'**] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310 (v = vs. 85) .aspx). 내 키보드 입력 래퍼 참조 [**이 대답 **] (http://stackoverflow.com/questions/39809095/why-do-some-applications-not-accept-some-sendkeys-at-some-times/39811061 # 39811061). –

+0

다음 예를 보겠습니다. https://msdn.microsoft.com/en-us/library/windows/desktop/ms646304(v=vs.85).aspx 이것은 numloc을위한 것이지만 info KEYEVENTF_EXTENDEDKEY를 사용해야합니다. 두 번째 : COndition 뒤에 무엇이 있습니까? 그것은 다음과 같습니다 : GetKeyboardState ((LPBYTE) & keyState); 예 : 현재 키 상태를 얻으려면? keybg_event가 대체되었으므로 keybg_event 대신 SetInput을 사용할 수 있습니다. – Kiko

+0

함수가 올바르게 선언 된 경우 오류가 전혀 없어야합니다. 예외가 처리 되더라도 응용 프로그램이 손상 될 수 있으므로 기본적으로 모든 예외에 대해 [Thrown] 확인란을 선택하지 않아야합니다. –

답변

0

내 의견에 말했듯이 keybd_event()은 (는) SendInput()으로 대체되었습니다. 그러나 PInvokeStackImbalance 예외를받는 이유는 함수 선언에서 마지막 두 매개 변수가 잘못 되었기 때문입니다.

거의 모든 Declare...Lib 예는 VB6 이하로 설계되었습니다. 예를 들어 Long은 VB.NET의 Long 데이터 유형과 동일하지 않습니다. 내가 조언을 항상DllImport attribute을 사용하여 P/Invoke 발췌 문장을 찾습니다. VB.NET 버전을 찾을 수 없다면 대신 C# 코드 조각을 찾아서 온라인 변환기를 사용하여 변환 할 수 있습니다.

마지막 두 매개 변수는 UIntegerUIntPtr이어야합니다. 내가 말했듯이

Public Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As UInteger, ByVal dwExtraInfo As UIntPtr) 

그러나, DllImport에 충실하는 것이 좋습니다 : 당신은/P에 대한 pinvoke.net을 확인 미리보기를 호출 할 수 있습니다

<DllImport("user32.dll")> _ 
Public Shared Sub keybd_event(bVk As Byte, bScan As Byte, dwFlags As UInteger, dwExtraInfo As UIntPtr) 
End Function 

. 예를 들어

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 

:

가되지 않는 등입니다 keybd_event`
If condition = True Then 
    InputHelper.SetKeyState(Keys.Scroll, False) 'Key down. 
Else 
    InputHelper.SetKeyState(Keys.Scroll, True) 'Key up. 
End If