1

我有一组前段时间写的发送键函数。它在 32 位系统中工作。现在我再次测试它并意识到它不再适用于我的新win7 64位系统。我在网上找了几篇文章,按照他们的方法制作了Input32/64函数。但是,它似乎不起作用。

Dim result As Integer = SendInput(1, input, cbSize)

总是返回 0 并且没有模拟击键。你能看看吗?

(注:我只做了KEYBOARDINPUT64结构,没用,所以我没有做MOUSEINPUT64或HARDWAREINPUT64结构...)

''mouse functions

Private Shared Sub SendMouseInput(ByVal flags As MOUSEEVENTF, ByVal point As System.Drawing.Point)
    If Marshal.SizeOf(New IntPtr()) = 8 Then
        SendMouseInput64(flags, point)
    Else
        SendMouseInput32(flags, point)
    End If
End Sub
Private Shared Sub SendMouseInput64(ByVal flags As MOUSEEVENTF, ByVal point As System.Drawing.Point)
    Dim screen As Rectangle = My.Computer.Screen.Bounds
    Dim globalx As Integer = CInt((65535 * point.X) / screen.Width) ' x scale from 0 to 65535
    Dim globaly As Integer = CInt((65535 * point.Y) / screen.Height) ' y scale from 0 to 65535
    Dim input As New INPUT64
    input.dwType = InputType.Mouse
    input.mi.dx = globalx
    input.mi.dy = globaly
    input.mi.dwFlags = MOUSEEVENTF.ABSOLUTE Or flags
    input.mi.dwExtraInfo = IntPtr.Zero
    input.mi.mouseData = 0
    input.mi.time = 0
    SendInput(1, input, Marshal.SizeOf(input))
End Sub
Private Shared Sub SendMouseInput32(ByVal flags As MOUSEEVENTF, ByVal point As System.Drawing.Point)
    Dim screen As Rectangle = My.Computer.Screen.Bounds
    Dim globalx As Integer = CInt((65535 * point.X) / screen.Width) ' x scale from 0 to 65535
    Dim globaly As Integer = CInt((65535 * point.Y) / screen.Height) ' y scale from 0 to 65535
    Dim input As New INPUT32
    input.dwType = InputType.Mouse
    input.mi.dx = globalx
    input.mi.dy = globaly
    input.mi.dwFlags = MOUSEEVENTF.ABSOLUTE Or flags
    input.mi.dwExtraInfo = IntPtr.Zero
    input.mi.mouseData = 0
    input.mi.time = 0
    SendInput(1, input, Marshal.SizeOf(input))
End Sub

''keyboard functions
Private Shared Sub SendKeyInput(ByVal flags As KEYEVENTF, ByVal key As Int16)
    If Marshal.SizeOf(New IntPtr()) = 8 Then
        SendKeyInput64(flags, key)
    Else
        SendKeyInput32(flags, key)
    End If
End Sub
Private Shared Sub SendKeyInput64(ByVal flags As KEYEVENTF, ByVal key As Int16)
    Dim input As New INPUT64
    Dim ki As New KEYBDINPUT64
    input.dwType = InputType.Keyboard
    input.ki = ki
    input.ki.wVk = key
    input.ki.wScan = 0
    input.ki.time = 0
    input.ki.dwFlags = flags
    input.ki.dwExtraInfo = IntPtr.Zero
    Dim cbSize As Integer = Marshal.SizeOf(GetType(INPUT64))
    Dim result As Integer = SendInput(1, input, cbSize)
    If result = 0 Then Console.WriteLine("SendKeyInput:" & Marshal.GetLastWin32Error)
End Sub
Private Shared Sub SendKeyInput32(ByVal flags As KEYEVENTF, ByVal key As Int16)
    Dim input As New INPUT32
    Dim ki As New KEYBDINPUT32
    input.dwType = InputType.Keyboard
    input.ki = ki
    input.ki.wVk = key
    input.ki.wScan = 0
    input.ki.time = 0
    input.ki.dwFlags = flags
    input.ki.dwExtraInfo = IntPtr.Zero
    Dim cbSize As Integer = Marshal.SizeOf(GetType(INPUT32))
    Dim result As Integer = SendInput(1, input, cbSize)
    If result = 0 Then Messaging.Instance.ReportError("MouseKeyboard::SendKeyInput:" & Marshal.GetLastWin32Error)
End Sub

''lower level input functions
<DllImport("User32.dll", SetLastError:=True)> _
Private Shared Function SendInput(ByVal nInputs As Integer, ByRef pInputs As INPUT64, ByVal cbSize As Integer) As Integer
End Function

<DllImport("User32.dll", SetLastError:=True)> _
Private Shared Function SendInput(ByVal nInputs As Integer, ByRef pInputs As INPUT32, ByVal cbSize As Integer) As Integer
End Function

<DllImport("User32.dll")> _
Private Shared Function BlockInput(ByVal fBlockIt As Boolean) As Boolean
End Function

<StructLayout(LayoutKind.Explicit, pack:=1)> _
Private Structure INPUT64
    <FieldOffset(0)> Public dwType As InputType
    <FieldOffset(8)> Public mi As MOUSEINPUT
    <FieldOffset(8)> Public ki As KEYBDINPUT64
    <FieldOffset(8)> Public hi As HARDWAREINPUT
End Structure

<StructLayout(LayoutKind.Explicit, pack:=1)> _
Private Structure INPUT32
    <FieldOffset(0)> Public dwType As InputType
    <FieldOffset(4)> Public mi As MOUSEINPUT
    <FieldOffset(4)> Public ki As KEYBDINPUT32
    <FieldOffset(4)> Public hi As HARDWAREINPUT
End Structure

<StructLayout(LayoutKind.Sequential, pack:=1)> _
Private Structure MOUSEINPUT
    Public dx As Int32
    Public dy As Int32
    Public mouseData As Int32
    Public dwFlags As MOUSEEVENTF
    Public time As Int32
    Public dwExtraInfo As IntPtr
End Structure

<StructLayout(LayoutKind.Sequential, pack:=1)> _
Private Structure KEYBDINPUT64
    <FieldOffset(0)> Public wVk As Int16
    <FieldOffset(2)> Public wScan As Int16
    <FieldOffset(4)> Public dwFlags As KEYEVENTF
    <FieldOffset(12)> Public time As Int32
    <FieldOffset(16)> Public dwExtraInfo As IntPtr
End Structure

<StructLayout(LayoutKind.Sequential, pack:=1)> _
Private Structure KEYBDINPUT32
    Public wVk As Int16
    Public wScan As Int16
    Public dwFlags As KEYEVENTF
    Public time As Int32
    Public dwExtraInfo As IntPtr
End Structure

<StructLayout(LayoutKind.Sequential, pack:=1)> _
Private Structure HARDWAREINPUT
    Public uMsg As Int32
    Public wParamL As Int16
    Public wParamH As Int16
End Structure
Private Enum InputType As Integer
    Mouse = 0
    Keyboard = 1
    Hardware = 2
End Enum
<Flags()> _
Private Enum MOUSEEVENTF As Integer
    MOVE = &H1
    LEFTDOWN = &H2
    LEFTUP = &H4
    RIGHTDOWN = &H8
    RIGHTUP = &H10
    MIDDLEDOWN = &H20
    MIDDLEUP = &H40
    XDOWN = &H80
    XUP = &H100
    VIRTUALDESK = &H400
    WHEEL = &H800
    ABSOLUTE = &H8000
End Enum
<Flags()> _
Private Enum KEYEVENTF As Integer
    KEYDOWN = 0
    EXTENDEDKEY = 1
    KEYUP = 2
    [UNICODE] = 4
    SCANCODE = 8
End Enum
4

2 回答 2

2

与其说是解决问题的方法,不如说您尝试过 InputSimulator 库:https ://inputsimulator.codeplex.com/

我已经在两个 32/64 位版本的 Windows 上顺利使用它。

于 2013-02-14T13:19:05.933 回答
1

请看看这个。 C# PInvoking user32.dll 在 64 位系统上

我想这也适用于其他 user32.dll 调用......

  1. 使用 IntPtr 而不是 UIntrPtr:UIntPtr 类型不符合 CLS
  2. 切勿使用“int”或“integer”作为 lParam。您的代码将在 64 位 Windows 上崩溃。仅使用 IntPtr、“ref”结构或“out”结构。
  3. 切勿使用“bool”、“int”或“integer”作为返回值。您的核心将在 64 位 Windows 上崩溃。仅使用 IntPtr。使用 bool 是不安全的 - pInvoke 不能将 IntPtr 编组为布尔值。
  4. 使用“IntPtr”作为返回值,即使消息说它没有返回任何有用的信息。
  5. Microsoft 将 System.Windows.Forms.Message 结构的 Msg 成员定义为 System.Int32[1]。同时,SendMessage 原生 API 将消息定义为 UINT[2] 类型,这是一个 32 位无符号值。[3] 可以在此处找到常见消息代码的列表:http ://www.vbcode.com/Asp/showsn.asp?theID=11797
  6. 您可以安全地将“hWnd”键入为“IntPtr”而不是“HandleRef”,但请确保您了解自己在做什么。如果您在由非托管组件或外部应用程序提供的窗口句柄上进行操作,那么一切都会正常工作(并且当其他应用程序可以自己自由操作窗口时也可以保证)。但是,将 IntPtr 与托管窗体和控件一起使用可能会导致您的代码在竞争条件下崩溃,因为 .NET 可以并且将在调用期间处理您的窗口句柄。使用得当,GC.KeepAlive() 可以帮助解决这个问题。这些都与固定无关,这在这里无济于事。固定是为了防止数据四处移动;使用 HandleRef 或 GC.KeepAlive 是为了防止运行时破坏您的句柄。
  7. 将整数值传递给 lParam 和 wParam 时,请使用 IntPtr,因为它们默认获取属性。您应该避免将 IntPtr 和 Integer 作为参数类型混合使用。使用 IntPtr。
  8. wParam 和 lParam 参数分别定义为 WPARAM 和 LPARAM 类型 WPARAM 定义为 UINT_PTR LPARAM 定义为 LONG_PTR LONG_PTR 是“指针精度的有符号长类型”。并且是有符号的 32 位或有符号的 64 位,具体取决于平台。UINT_PTR 是“Unsigned INT_PTR”,是无符号 32 位或无符号 64 位,具体取决于平台。

来源http://www.pinvoke.net/default.aspx/user32.SendMessage

此外,如果您处于紧要关头... Win32 和 Win64 机器中的 SendInput 键

于 2013-02-14T14:21:49.027 回答