windows 如何在VBA中使用SendInput函数合并Chrome窗口的击键?

hi3rlvi2  于 2023-06-07  发布在  Windows
关注(0)|答案(2)|浏览(376)

我想在VBA中使用Windows API的Sendinput函数将按键组合发送到窗口,例如Ctrl H到Chrome。我选择sendinput()是因为sendmessage不允许我同时发送一个组合键,窗口将分别接收它们。另一方面,VBA中的SendKeys方法被认为是不可靠的。
所以在阅读了文档和谷歌搜索后,我找到了这段代码

Option Explicit
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
    (ByVal hWnd As LongPtr, ByVal hWndChild As LongPtr, _
    ByVal lpszClass As String, ByVal lpszWindow As String) As LongPtr

Private Declare PtrSafe Function ShowWindow Lib "user32" _
    (ByVal hWnd As LongPtr, ByVal nCmdShow As Long) As Boolean

Private Declare PtrSafe Function SetForegroundWindow Lib "user32" _
    (ByVal hWnd As LongPtr) As Boolean

Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" _
    (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr

Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrA" _
    (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr

Private Declare PtrSafe Function GetWindow Lib "user32" _
    (ByVal hWnd As LongPtr, ByVal wCmd As Long) As LongPtr

Private Declare PtrSafe Function EnumChildWindows Lib "user32" _
    (ByVal hWnd As LongPtr, ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long

Private Declare PtrSafe Function GetWindowText Lib "user32" Alias _
    "GetWindowTextA" (ByVal hWnd As LongPtr, ByVal lpWindowText As String, ByVal nMaxCount As LongPtr) As Long

Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As LongPtr

Private Declare PtrSafe Function GetWindowTextLength Lib "user32" Alias _
    "GetWindowTextLengthA" (ByVal hWnd As LongPtr) As Long

Public Declare PtrSafe Sub Sleep Lib "kernel32" _
    (ByVal dwMilliseconds As LongPtr)

Private Declare PtrSafe Function SendInput Lib "user32" ( _
         ByVal nInputs As LongPtr, _
         ByRef pInputs As Any, _
         ByVal cbSize As LongPtr) As Long

Private Const SW_SHOWNORMAL As Long = 1
Private Const WM_SETTEXT As Long = &HC
Private Const VK_RETURN As Integer = &HD
Private Const WM_CHAR As Long = &H102
Private Const WM_KEYDOWN As Long = &H100
Private Const WM_KEYUP As Long = &H101
Private Const WM_SYSKEYDOWN As Long = &H104
Private Const WM_SYSKEYUP As Long = &H105
Private Const VK_LBUTTON As Long = &H1
Private Const VK_RBUTTON As Long = &H2
Private Const VK_CANCEL As Long = &H3
Private Const VK_MBUTTON As Long = &H4
Private Const VK_XBUTTON1 As Long = &H5
Private Const VK_XBUTTON2 As Long = &H6
Private Const VK_BACKSPACE As Long = &H8
Private Const VK_TAB As Long = &H9 'TAB
Private Const VK_CLEAR As Long = &HC
Private Const VK_ENTER As Long = &HD
Private Const VK_SHIFT As Long = &H10
Private Const VK_CONTROL As Long = &H11 'CTRL
Private Const VK_MENU As Long = &H12
Private Const VK_PAUSE As Long = &H13
Private Const VK_CAPSLOCK As Long = &H14
Private Const VK_ESCAPE As Long = &H1B
Private Const VK_SPACE As Long = &H20
Private Const VK_PAGEUP As Long = &H21
Private Const VK_PAGEDOWN As Long = &H22
Private Const VK_END As Long = &H23
Private Const VK_HOME As Long = &H24
Private Const VK_LEFT As Long = &H25
Private Const VK_UP As Long = &H26
Private Const VK_RIGHT As Long = &H27
Private Const VK_DOWN As Long = &H28
Private Const VK_PRINTSCREEN As Long = &H2C
Private Const VK_INSERT As Long = &H2D
Private Const VK_DELETE As Long = &H2E
Private Const VK_0 As Long = &H30
Private Const VK_1 As Long = &H31
Private Const VK_2 As Long = &H32
Private Const VK_3 As Long = &H33
Private Const VK_4 As Long = &H34
Private Const VK_5 As Long = &H35
Private Const VK_6 As Long = &H36
Private Const VK_7 As Long = &H37
Private Const VK_8 As Long = &H38
Private Const VK_9 As Long = &H39
Private Const VK_A As Long = &H41
Private Const VK_B As Long = &H42
Private Const VK_C As Long = &H43
Private Const VK_D As Long = &H44
Private Const VK_E As Long = &H45
Private Const VK_F As Long = &H46
Private Const VK_G As Long = &H47
Private Const VK_H As Long = &H48
Private Const VK_I As Long = &H49
Private Const VK_J As Long = &H4A
Private Const VK_K As Long = &H4B
Private Const VK_L As Long = &H4C
Private Const VK_M As Long = &H4D
Private Const VK_N As Long = &H4E
Private Const VK_O As Long = &H4F
Private Const VK_P As Long = &H50
Private Const VK_Q As Long = &H51
Private Const VK_R As Long = &H52
Private Const VK_S As Long = &H53
Private Const VK_T As Long = &H54
Private Const VK_U As Long = &H55
Private Const VK_V As Long = &H56
Private Const VK_W As Long = &H57
Private Const VK_X As Long = &H58
Private Const VK_Y As Long = &H59
Private Const VK_Z As Long = &H5A
Private Const VK_F11 = &H7A
Private Const INPUT_KEYBOARD As Long = 1
Private Const KEYEVENTF_KEYUP As Long = 2

Const GW_CHILD = 5
Const GW_HWNDNEXT = 2

Dim keyInput()    As INPUT_
Dim sizeINPUT     As Long

Private Type INPUT_      '   typedef struct tagINPUT {
    dwType As Long                '     DWORD type;
    wVK As Integer                '     union {MOUSEINPUT mi;
    wScan As Integer              '               KEYBDINPUT ki;
    dwFlags As Long               '               HARDWAREINPUT hi;
    dwTime As LongPtr                '              };
    dwExtraInfo As LongPtr            '     }INPUT, *PINPUT;
    dwPadding As Currency         '   8 extra bytes, because mouses take more.
End Type

Sub main() ' {
    
    sizeINPUT = LenB(keyInput(0))
    Call SendKeystrokeFromExcel
    Call Sleep(100)
    Call Ctrl_H
    

End Sub ' }


Sub SendKeystrokeFromExcel()
    Dim hWnd As LongPtr
    ' Find the window by its title
    hWnd = 1378908 'Handle of Google Chrome
    ShowWindow hWnd, SW_SHOWNORMAL
    SetForegroundWindow hWnd
    Sleep (100)
    SendMessage hWnd, WM_KEYDOWN, VK_F11, 0

End Sub

Sub Ctrl_H() 

    ReDim keyInput(0 To 3)

    keyInput(0).dwType = INPUT_KEYBOARD
    keyInput(0).dwFlags = 0        ' Press key
    keyInput(0).wVK = VK_CONTROL

    keyInput(1).dwType = INPUT_KEYBOARD
    keyInput(1).dwFlags = 0        ' Press key
    keyInput(1).wVK = VK_H

    keyInput(2).dwType = INPUT_KEYBOARD
    keyInput(2).dwFlags = KEYEVENTF_KEYUP
    keyInput(2).wVK = VK_H

    keyInput(3).dwType = INPUT_KEYBOARD
    keyInput(3).dwFlags = KEYEVENTF_KEYUP
    keyInput(3).wVK = VK_CONTROL
    Call SendInput(4, keyInput(0), sizeINPUT)

End Sub

所以当我运行代码时,它很容易找到Chrome窗口。然而,当涉及到运行SUB Ctrl_H()时,它似乎无法运行,即使我投入的工作量很大。我在互联网上找到的所有代码,包括堆栈交换(SendInput VB Basic Example)都不能工作。如果有人有任何解决办法,我会非常aprreciate。

1zmg4dgp

1zmg4dgp1#

这些是我最近的一个项目中的声明和类型--它们可以工作,并且已经过测试。(如果你不知道你的声明是否有效,那么从CtrlH这样的东西开始是非常危险的。CtrlH不能产生你想要的结果有很多原因-我建议你从输入一个字符到记事本开始(为了测试声明是否工作)-在你调用sendinput之前设置一个睡眠计时器5秒,手动选择记事本,看看会发生什么(这样你就排除了可能是问题的其他因素)
也许是声明的问题,也许是窗口的激活,也许是CtrlH本身的问题,通过一次测试所有内容,您将无法真正看到哪些工作以及哪些可能导致问题。

Public Declare PtrSafe Function SendMouseInput Lib "user32.dll" Alias "SendInput" (ByVal cInputs As Long, ByRef pInputs As tagINPUT_mouse, ByVal cbSize As Integer) As Long
Public Declare PtrSafe Function SendKeybdInput Lib "user32.dll" Alias "SendInput" (ByVal cInputs As Long, ByRef pInputs As tagINPUT_keybd, ByVal cbSize As Integer) As Long

Type tagMOUSEINPUT
    dx As Long
    dy As Long
    mouseData As Long
    dwFlags As Long
    time As Long
    dwExtraInfo As LongPtr
End Type

Type tagKEYBDINPUT
    wVk As Integer
    wScan As Integer
    dwFlags As Long
    time As Long
    dwExtraInfo As LongPtr
    padding As Currency 'adding 8bytes to get to same size as MOUSEINPUT (2bytes difference per parameter of type Int, and 4bytes for 1 less parameter)
End Type

Type tagINPUT_mouse
    INPUTTYPE As Long
    mi As tagMOUSEINPUT
End Type

Type tagINPUT_keybd
    INPUTTYPE As Long
    ki As tagKEYBDINPUT
End Type
j2cgzkjk

j2cgzkjk2#

基于@Lord-JulianXLII代码,我成功地编写了一个向Windows发送输入的代码。这里是给任何关心的人的

Public Declare PtrSafe Function SendMouseInput Lib "user32.dll" Alias "SendInput" (ByVal cInputs As Long, ByRef pInputs As tagINPUT_mouse, ByVal cbSize As Integer) As Long
Public Declare PtrSafe Function SendKeybdInput Lib "user32.dll" Alias "SendInput" (ByVal cInputs As Long, ByRef pInputs As tagINPUT_keybd, ByVal cbSize As Integer) As Long

Type tagMOUSEINPUT
    dx As Long
    dy As Long
    mouseData As Long
    dwFlags As Long
    time As Long
    dwExtraInfo As LongPtr
End Type

Type tagKEYBDINPUT
    wVk As Integer
    wScan As Integer
    dwFlags As Long
    time As Long
    dwExtraInfo As LongPtr
    padding As Currency 'adding 8bytes to get to same size as MOUSEINPUT (2bytes difference per parameter of type Int, and 4bytes for 1 less parameter)
End Type

Type tagINPUT_mouse
    INPUTTYPE As Long
    mi As tagMOUSEINPUT
End Type

Type tagINPUT_keybd
    INPUTTYPE As Long
    ki As tagKEYBDINPUT
End Type

Sub Ctrl_H()

   Dim inputArray(1 To 2) As tagINPUT_keybd
    
    ' Set up the first input structure for "Ctrl" key press
    inputArray(1).INPUTTYPE = 1 ' INPUT_KEYBOARD
    inputArray(1).ki.wVk = VK_CONTROL
    inputArray(1).ki.dwFlags = 0 ' Key press
    
    ' Set up the second input structure for "H" key press
    inputArray(2).INPUTTYPE = 1 ' INPUT_KEYBOARD
    inputArray(2).ki.wVk = VK_H
    inputArray(2).ki.dwFlags = 0 ' Key press
    
    ' Send the keydown events
    Call SendKeybdInput(2, inputArray(1), LenB(inputArray(1)))
    
    ' Set up the first input structure for "Ctrl" key release
    inputArray(1).ki.dwFlags = KEYEVENTF_KEYUP ' Key release
    
    ' Set up the second input structure for "H" key release
    inputArray(2).ki.dwFlags = KEYEVENTF_KEYUP ' Key release
    
    ' Send the keyup events
    Call SendKeybdInput(2, inputArray(1), LenB(inputArray(1)))
End Sub

然而,最好从UI自动化开始,就像@IInspectable建议的那样。

相关问题