내 의견에 말했듯이 keybd_event()
은 (는) SendInput()
으로 대체되었습니다. 그러나 PInvokeStackImbalance
예외를받는 이유는 함수 선언에서 마지막 두 매개 변수가 잘못 되었기 때문입니다.
거의 모든 Declare...Lib
예는 VB6 이하로 설계되었습니다. 예를 들어 Long
은 VB.NET의 Long
데이터 유형과 동일하지 않습니다. 내가 조언을 항상DllImport
attribute을 사용하여 P/Invoke 발췌 문장을 찾습니다. VB.NET 버전을 찾을 수 없다면 대신 C# 코드 조각을 찾아서 온라인 변환기를 사용하여 변환 할 수 있습니다.
마지막 두 매개 변수는 UInteger
및 UIntPtr
이어야합니다. 내가 말했듯이
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
''선언
는 오늘 방법
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). –다음 예를 보겠습니다. 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
함수가 올바르게 선언 된 경우 오류가 전혀 없어야합니다. 예외가 처리 되더라도 응용 프로그램이 손상 될 수 있으므로 기본적으로 모든 예외에 대해 [Thrown] 확인란을 선택하지 않아야합니다. –