为什么我对 SendInput 的调用不起作用

发布于 2024-07-27 05:44:05 字数 5475 浏览 2 评论 0原文

我正在使用 SendInput 将一些键盘命令发送到对话框。 当我调用 SendInput 时,它已经是活动的前台窗口。

我首先发送“Return”,然后发送一堆其他内容。 该对话框打开时默认选择一个按钮,当手动选择 Enter 时,单击对话框上的按钮将进入下一个屏幕,但我的 SendInput 调用不会前进该对话框。

这是我的代码。 首先是数据结构和 p/invoke

Imports System.Runtime.InteropServices
Imports System.Drawing

Public Class NativeMethods

Private Structure INPUT
    Dim dwType As Integer
    Dim mkhi As MOUSEKEYBDHARDWAREINPUT
End Structure

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

Private Structure HARDWAREINPUT
    Public uMsg As Integer
    Public wParamL As Short
    Public wParamH As Short
End Structure

<StructLayout(LayoutKind.Explicit)> _
Private Structure MOUSEKEYBDHARDWAREINPUT
    <FieldOffset(0)> Public mi As MOUSEINPUT
    <FieldOffset(0)> Public ki As KEYBDINPUT
    <FieldOffset(0)> Public hi As HARDWAREINPUT
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 Integer ' changed from IntPtr because of compiler error.
                                  ' I don't use this field '
End Structure

' Constants for SendInput '
Const INPUT_MOUSE As UInt32 = 0
Public Const INPUT_KEYBOARD As Integer = 1
Const INPUT_HARDWARE As Integer = 2
Public Const KEYEVENTF_EXTENDEDKEY As UInt32 = &H1
Public Const KEYEVENTF_KEYUP As UInt32 = &H2
Public Const KEYEVENTF_UNICODE As UInt32 = &H4
Public Const KEYEVENTF_SCANCODE As UInt32 = &H8
Const XBUTTON1 As UInt32 = &H1
Const XBUTTON2 As UInt32 = &H2
Const MOUSEEVENTF_MOVE As UInt32 = &H1
Const MOUSEEVENTF_LEFTDOWN As UInt32 = &H2
Const MOUSEEVENTF_LEFTUP As UInt32 = &H4
Const MOUSEEVENTF_RIGHTDOWN As UInt32 = &H8
Const MOUSEEVENTF_RIGHTUP As UInt32 = &H10
Const MOUSEEVENTF_MIDDLEDOWN As UInt32 = &H20
Const MOUSEEVENTF_MIDDLEUP As UInt32 = &H40
Const MOUSEEVENTF_XDOWN As UInt32 = &H80
Const MOUSEEVENTF_XUP As UInt32 = &H100
Const MOUSEEVENTF_WHEEL As UInt32 = &H800
Const MOUSEEVENTF_VIRTUALDESK As UInt32 = &H4000
Const MOUSEEVENTF_ABSOLUTE As UInt32 = &H8000

Public Const VK_TAB = &H9
Public Const VK_RETURN = &HD
Public Const VK_DOWN = &H28

<DllImport("user32.dll")> _
Private Shared Function SendInput(ByVal nInputs As Integer, ByRef pInputs As INPUT, ByVal cbSize As Integer) As Integer
End Function

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow( _
 ByVal lpClassName As String, _
 ByVal lpWindowName As String) As IntPtr
End Function

<DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindowByClass( _
     ByVal lpClassName As String, _
     ByVal zero As IntPtr) As IntPtr
End Function

<DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindowByCaption( _
     ByVal zero As IntPtr, _
     ByVal lpWindowName As String) As IntPtr
End Function

<DllImport("user32.dll")> _
Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As Boolean
End Function

<DllImport("user32.dll")> _
Private Shared Function SetFocus(ByVal hWnd As IntPtr) As IntPtr
End Function

' "As any" replacement seen here '
' when you see As Any in Pinvoke, replace with this ' 
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(<System.Runtime.InteropServices.MarshalAsAttribute( _
    System.Runtime.InteropServices.UnmanagedType.AsAny)> _
    ByVal pDst As Object, <System.Runtime.InteropServices.MarshalAsAttribute( _
    System.Runtime.InteropServices.UnmanagedType.AsAny)> _
    ByVal pSrc As Object, ByVal ByteLen As Long)

然后是我写入此对话框的代码

' constants for keys needed '
Public Const VK_TAB = &H9
Public Const VK_RETURN = &HD
Public Const VK_DOWN = &H28

Public Shared Sub SendRebuildKeys()
    ' Enter ' 
    SendKeyDownAndUp(VK_RETURN)
    ' Down x 10 ' 
    For i = 1 To 10
        SendKeyDownAndUp(VK_DOWN)
    Next
    ' Enter '
    SendKeyDownAndUp(VK_RETURN)
    ' T 84 ' 
    SendKeyDownAndUp(CShort(84))
    ' S 83 '
    SendKeyDownAndUp(CShort(83))
    ' T 84 '
    SendKeyDownAndUp(CShort(84))
    ' Tab '
    SendKeyDownAndUp(VK_TAB)
    ' Enter '
    SendKeyDownAndUp(VK_RETURN)
End Sub

Public Shared Sub SendKeyDownAndUp(ByVal keyCode As Short)
    Dim inputd = GetINPUTFromKeyCode(keyCode, True)
    Dim inputu = GetINPUTFromKeyCode(keyCode, False)
    Dim inputs(2) As INPUT
    inputs(0) = inputd
    inputs(1) = inputu

    SendInput(2, inputs(0), Len(inputd))
End Sub

Private Shared Function GetINPUTFromKeyCode(ByVal keyCode As Short, _
    ByVal isDown As  Boolean) As INPUT
    Dim input As New INPUT()
    Dim unall As New MOUSEKEYBDHARDWAREINPUT()
    Dim keyb As New KEYBDINPUT()

    input.dwType = INPUT_KEYBOARD
    keyb.wVk = keyCode

    If isDown = False Then
        keyb.dwFlags = KEYEVENTF_KEYUP
    Else
        keyb.dwFlags = 0
    End If

    ' copy keyb into unall.ki '
    CopyMemory(unall.ki, keyb, Len(keyb))
    ' copy unall into input.mkhi ' 
    CopyMemory(input.mkhi, unall, Len(unall))

    Return input
End Function

我在这里缺少什么

I am using SendInput to send some keyboard commands to a dialog box. It is already the active foreground window when I call SendInput.

I first send "Return" and then a bunch of other stuff. The dialog box opens with a button selected by default, and when manually selecting Enter, the button is clicked on the dialog progresses to the next screen, but my SendInput call doesn't advance the dialog.

Here is my code. First the data structures and p/invoke

Imports System.Runtime.InteropServices
Imports System.Drawing

Public Class NativeMethods

Private Structure INPUT
    Dim dwType As Integer
    Dim mkhi As MOUSEKEYBDHARDWAREINPUT
End Structure

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

Private Structure HARDWAREINPUT
    Public uMsg As Integer
    Public wParamL As Short
    Public wParamH As Short
End Structure

<StructLayout(LayoutKind.Explicit)> _
Private Structure MOUSEKEYBDHARDWAREINPUT
    <FieldOffset(0)> Public mi As MOUSEINPUT
    <FieldOffset(0)> Public ki As KEYBDINPUT
    <FieldOffset(0)> Public hi As HARDWAREINPUT
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 Integer ' changed from IntPtr because of compiler error.
                                  ' I don't use this field '
End Structure

' Constants for SendInput '
Const INPUT_MOUSE As UInt32 = 0
Public Const INPUT_KEYBOARD As Integer = 1
Const INPUT_HARDWARE As Integer = 2
Public Const KEYEVENTF_EXTENDEDKEY As UInt32 = &H1
Public Const KEYEVENTF_KEYUP As UInt32 = &H2
Public Const KEYEVENTF_UNICODE As UInt32 = &H4
Public Const KEYEVENTF_SCANCODE As UInt32 = &H8
Const XBUTTON1 As UInt32 = &H1
Const XBUTTON2 As UInt32 = &H2
Const MOUSEEVENTF_MOVE As UInt32 = &H1
Const MOUSEEVENTF_LEFTDOWN As UInt32 = &H2
Const MOUSEEVENTF_LEFTUP As UInt32 = &H4
Const MOUSEEVENTF_RIGHTDOWN As UInt32 = &H8
Const MOUSEEVENTF_RIGHTUP As UInt32 = &H10
Const MOUSEEVENTF_MIDDLEDOWN As UInt32 = &H20
Const MOUSEEVENTF_MIDDLEUP As UInt32 = &H40
Const MOUSEEVENTF_XDOWN As UInt32 = &H80
Const MOUSEEVENTF_XUP As UInt32 = &H100
Const MOUSEEVENTF_WHEEL As UInt32 = &H800
Const MOUSEEVENTF_VIRTUALDESK As UInt32 = &H4000
Const MOUSEEVENTF_ABSOLUTE As UInt32 = &H8000

Public Const VK_TAB = &H9
Public Const VK_RETURN = &HD
Public Const VK_DOWN = &H28

<DllImport("user32.dll")> _
Private Shared Function SendInput(ByVal nInputs As Integer, ByRef pInputs As INPUT, ByVal cbSize As Integer) As Integer
End Function

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow( _
 ByVal lpClassName As String, _
 ByVal lpWindowName As String) As IntPtr
End Function

<DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindowByClass( _
     ByVal lpClassName As String, _
     ByVal zero As IntPtr) As IntPtr
End Function

<DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindowByCaption( _
     ByVal zero As IntPtr, _
     ByVal lpWindowName As String) As IntPtr
End Function

<DllImport("user32.dll")> _
Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As Boolean
End Function

<DllImport("user32.dll")> _
Private Shared Function SetFocus(ByVal hWnd As IntPtr) As IntPtr
End Function

' "As any" replacement seen here '
' when you see As Any in Pinvoke, replace with this ' 
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(<System.Runtime.InteropServices.MarshalAsAttribute( _
    System.Runtime.InteropServices.UnmanagedType.AsAny)> _
    ByVal pDst As Object, <System.Runtime.InteropServices.MarshalAsAttribute( _
    System.Runtime.InteropServices.UnmanagedType.AsAny)> _
    ByVal pSrc As Object, ByVal ByteLen As Long)

Then my code to write to this dialog box

' constants for keys needed '
Public Const VK_TAB = &H9
Public Const VK_RETURN = &HD
Public Const VK_DOWN = &H28

Public Shared Sub SendRebuildKeys()
    ' Enter ' 
    SendKeyDownAndUp(VK_RETURN)
    ' Down x 10 ' 
    For i = 1 To 10
        SendKeyDownAndUp(VK_DOWN)
    Next
    ' Enter '
    SendKeyDownAndUp(VK_RETURN)
    ' T 84 ' 
    SendKeyDownAndUp(CShort(84))
    ' S 83 '
    SendKeyDownAndUp(CShort(83))
    ' T 84 '
    SendKeyDownAndUp(CShort(84))
    ' Tab '
    SendKeyDownAndUp(VK_TAB)
    ' Enter '
    SendKeyDownAndUp(VK_RETURN)
End Sub

Public Shared Sub SendKeyDownAndUp(ByVal keyCode As Short)
    Dim inputd = GetINPUTFromKeyCode(keyCode, True)
    Dim inputu = GetINPUTFromKeyCode(keyCode, False)
    Dim inputs(2) As INPUT
    inputs(0) = inputd
    inputs(1) = inputu

    SendInput(2, inputs(0), Len(inputd))
End Sub

Private Shared Function GetINPUTFromKeyCode(ByVal keyCode As Short, _
    ByVal isDown As  Boolean) As INPUT
    Dim input As New INPUT()
    Dim unall As New MOUSEKEYBDHARDWAREINPUT()
    Dim keyb As New KEYBDINPUT()

    input.dwType = INPUT_KEYBOARD
    keyb.wVk = keyCode

    If isDown = False Then
        keyb.dwFlags = KEYEVENTF_KEYUP
    Else
        keyb.dwFlags = 0
    End If

    ' copy keyb into unall.ki '
    CopyMemory(unall.ki, keyb, Len(keyb))
    ' copy unall into input.mkhi ' 
    CopyMemory(input.mkhi, unall, Len(unall))

    Return input
End Function

What am I missing here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我三岁 2024-08-03 05:44:05

问题可能在于编组您正在使用的数据结构。 你能发布那些吗? 另外,发布 P/Invoked 函数的声明。

您独立测试过SendInput函数吗? 有效吗? 如果您还没有这样做,我建议编写一个更简单的测试用例,以确保 P/Invoked 函数的声明以及您正在使用的数据结构没有问题。

The problem might be with marshalling the data structures you're using. Can you post those? Also, post the declarations of your P/Invoked functions.

Have you tested the SendInput function independently? Does it work? If you haven't done that yet, I would suggest coding a simpler test case to make sure there are no issues with your declarations of the P/Invoked functions and with the data structures you're using.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文