我正在嘗試使用 vb.net開發一個擊鍵宏程式,該程式將記錄諸如keydown和keyup 事件之類的擊鍵,然后在主程式在后臺運行時在任何地方播放。截至目前,我已成功捕獲擊鍵并存盤這些擊鍵。但是我面臨的問題是在播放那些存盤的擊鍵時。我無法 從任何外部程式觸發 KeyDown 和 KeyUp 事件。我也嘗試過SendKeys方法,但它無法分別區分 KeyDown 和 KeyUp。在這種情況下的幫助將不勝感激。
只能在父程式中訪問的 KeyDown 事件。
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
'MessageBox.Show(e.KeyCode)
'bla bla bla
End Sub
'使用 SendKeys 但無法區分 KeyDown 和 KeyUp
Private Function AutoSendKey(ByVal keystroke As String, ByVal delay As Integer)
System.Threading.Thread.Sleep(delay)
My.Computer.Keyboard.SendKeys(keystroke, True)
End Function
我需要一種從外部應用程式觸發 KeyDown 和 KeyUp 事件的方法。提前致謝
uj5u.com熱心網友回復:
我只是在尋找同樣的東西,發現很少的資源,然后設法將它整合到一個應用程式中:
基本上,除非您在驅動程式級別使用某種攔截,否則這將起作用,在這種情況下,攔截應用程式攔截的鍵盤對 Windows 不可見,因此該腳本無用。
除此之外,這是我的代碼。此代碼針對 .NET 5.0 進行了優化
首先創建KeyboardHook.vb類:
Imports System.Runtime.InteropServices
Public Class KeyboardHook
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
Private Overloads Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal HookProc As KBDLLHookProc, ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
End Function
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
Private Overloads Shared Function CallNextHookEx(ByVal idHook As Integer, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
Private Overloads Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Boolean
End Function
<StructLayout(LayoutKind.Sequential)>
Private Structure KBDLLHOOKSTRUCT
Public vkCode As UInt32
Public scanCode As UInt32
Public flags As KBDLLHOOKSTRUCTFlags
Public time As UInt32
Public dwExtraInfo As UIntPtr
End Structure
<Flags()>
Private Enum KBDLLHOOKSTRUCTFlags As UInt32
LLKHF_EXTENDED = &H1
LLKHF_INJECTED = &H10
LLKHF_ALTDOWN = &H20
LLKHF_UP = &H80
End Enum
Public Shared Event KeyDown(ByVal Key As Key)
Public Shared Event KeyUp(ByVal Key As Key)
Private Const WH_KEYBOARD_LL As Integer = 13
Private Const HC_ACTION As Integer = 0
Private Const WM_KEYDOWN = &H100
Private Const WM_KEYUP = &H101
Private Const WM_SYSKEYDOWN = &H104
Private Const WM_SYSKEYUP = &H105
Private Delegate Function KBDLLHookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
Private KBDLLHookProcDelegate As KBDLLHookProc = New KBDLLHookProc(AddressOf KeyboardProc)
Private HHookID As IntPtr = IntPtr.Zero
Private Function KeyboardProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
If (nCode = HC_ACTION) Then
Dim struct As KBDLLHOOKSTRUCT
Select Case wParam
Case WM_KEYDOWN, WM_SYSKEYDOWN
Dim aKey = KeyInterop.KeyFromVirtualKey(CType(Marshal.PtrToStructure(lParam, struct.GetType()), KBDLLHOOKSTRUCT).vkCode)
RaiseEvent KeyDown(aKey)
Case WM_KEYUP, WM_SYSKEYUP
Dim aKey = KeyInterop.KeyFromVirtualKey(CType(Marshal.PtrToStructure(lParam, struct.GetType()), KBDLLHOOKSTRUCT).vkCode)
RaiseEvent KeyUp(aKey)
End Select
End If
Return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam)
End Function
Public Sub New()
HHookID = SetWindowsHookEx(WH_KEYBOARD_LL, KBDLLHookProcDelegate, System.Diagnostics.Process.GetCurrentProcess().MainModule.BaseAddress, 0)
If HHookID = IntPtr.Zero Then
Throw New Exception("Could not set keyboard hook")
End If
End Sub
Protected Overrides Sub Finalize()
If Not HHookID = IntPtr.Zero Then
UnhookWindowsHookEx(HHookID)
End If
MyBase.Finalize()
End Sub
End Class
現在使用 KeyboardHook 事件處理程式創建您自己的類/用戶控制元件。
對我來說,這很簡單OnScreenKBView.xaml,文本塊的文本屬性系結到視圖模型類屬性,它顯示按下和釋放的鍵以及同時按下的鍵數:
<Grid>
<Border Background="Red" >
<StackPanel Orientation="Vertical">
<TextBlock Text="KeyDown:"/>
<TextBlock Text="{Binding keyDown, Converter={StaticResource KeyToStringVC}}"/>
<TextBlock Text="KeyUp:"/>
<TextBlock Text="{Binding keyUp, Converter={StaticResource KeyToStringVC}}"/>
<TextBlock Text="TotalKeysPressed at the same time:"/>
<TextBlock Text="{Binding keysPressed, Converter={StaticResource ListToCountVC}}"/>
<TextBlock Text="KeysPressed:"/>
<TextBlock Text="{Binding keysPressed, Converter={StaticResource ListToStringVC}}" TextWrapping="Wrap"/>
</StackPanel>
</Border>
</Grid>
請注意,我的值轉換器很少KeyToStringVC,ListToStringVC并且ListToCountVC.
KeyToStringVC:
Return value.ToString
ListToCountVC:
If Not value Is Nothing Then
Return value.count
Else
Return Nothing
End If
串列到字串VC:
Dim kl As ObservableCollection(Of Key) = value
Dim str As String = Nothing
If Not kl Is Nothing Then
For Each item In kl
str = item.ToString & "; "
Next
End If
Return str
如果您不知道如何使用/創造價值轉換器,您將不得不查找如何使用/創造價值轉換器。
OnScreenKBView.xaml 背后的 VB 代碼:
Imports System.Collections.ObjectModel
Public Class OnScreenKBView
Private WithEvents kbHook As New KeyboardHook
Private viewModel As OnScreenKBViewModel
Private Sub kbHook_KeyDown(ByVal Key As Key) Handles kbHook.KeyDown
viewModel.keyDown = Key
'check if list already has the key in it
Dim hasKey As Boolean = False
If Me.viewModel.keysPressed.Contains(Key) Then
hasKey = True
End If
If Not hasKey Then
Me.viewModel.keysPressed.Add(Key)
Dim localCol = Me.viewModel.keysPressed
Dim newCol = New ObservableCollection(Of Key)(From i In localCol Select i)
Me.viewModel.keysPressed = newCol
End If
End Sub
Private Sub kbHook_KeyUp(ByVal Key As Key) Handles kbHook.KeyUp
viewModel.keyUp = Key
Me.viewModel.keysPressed.Remove(Key)
Dim localCol = Me.viewModel.keysPressed
Dim newCol = New ObservableCollection(Of Key)(From i In localCol Select i)
Me.viewModel.keysPressed = newCol
End Sub
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.viewModel = Application.Current.MainWindow.DataContext
End Sub
End Class
這應該給你一些我希望的想法。如果你需要整個專案,我在 github 上有它,但它是私有的,我可以為你壓縮它。
Lil 演示: 此處為 GIF
uj5u.com熱心網友回復:
Imports System.Runtime.InteropServices
Imports System.Windows.Forms 'for the keys. enumeration
Public Module SendWinKey
Const KEYEVENTF_KEYDOWN As Integer = &H0
Const KEYEVENTF_KEYUP As Integer = &H2
Declare Sub keybd_event Lib "User32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As UInteger, ByVal dwExtraInfo As UInteger)
Public Sub Main()
keybd_event(CByte(Keys.LWin), 0, KEYEVENTF_KEYDOWN, 0) 'press the left Win key down
keybd_event(CByte(Keys.R), 0, KEYEVENTF_KEYDOWN, 0) 'press the R key down
keybd_event(CByte(Keys.R), 0, KEYEVENTF_KEYUP, 0) 'release the R key
keybd_event(CByte(Keys.LWin), 0, KEYEVENTF_KEYUP, 0) 'release the left Win key
End Sub
End Module
如您所見,這非常簡單。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/393721.html
標籤:网络
