Разрешить глобальные горячие клавиши
Прежде всего, я не настоящий кодер, но я доволен тем, что я сделал до сих пор.
Я написал этот код ниже, который связан с робототехникой. Приведенный ниже код позволяет мне использовать сочетания клавиш при нажатии на форму. Однако мне нужны горячие клавиши, чтобы работать независимо от того, находится ли приложение в фокусе или даже не свернуто.
Я уже смотрел онлайн, но это не очень понятно.
Public Class MainForm
Private Sub MainForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If (e.KeyCode And Not Keys.Modifiers) = Keys.T AndAlso e.Modifiers = Keys.Control Then
DF1Com1.Write("O:1/0", "1") ' (O:9/0) (R)
End If
'If e.KeyCode = Keys.R Then
'DF1Com1.Write("O:1/0", "1") ' (O:9/0) (R)
'End If
End Sub
Private Sub MainForm_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
If (e.KeyCode And Not Keys.Modifiers) = Keys.T AndAlso e.Modifiers = Keys.Control Then
DF1Com1.Write("O:1/0", "0") ' (O:9/0) (R)
End If
'If e.KeyCode = Keys.R Then
'DF1Com1.Write("O:1/0", "0") ' (O:9/0) (R)
'End If
End Sub
Public Class MainForm
Private Sub MainForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If (e.KeyCode And Not Keys.Modifiers) = Keys.T AndAlso e.Modifiers = Keys.Control Then
DF1Com1.Write("O:1/0", "1") ' (O:9/0) (R)
End If
'If e.KeyCode = Keys.R Then
'DF1Com1.Write("O:1/0", "1") ' (O:9/0) (R)
'End If
End Sub
Private Sub MainForm_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
If (e.KeyCode And Not Keys.Modifiers) = Keys.T AndAlso e.Modifiers = Keys.Control Then
DF1Com1.Write("O:1/0", "0") ' (O:9/0) (R)
End If
'If e.KeyCode = Keys.R Then
'DF1Com1.Write("O:1/0", "0") ' (O:9/0) (R)
'End If
End Sub
End Class
Обновить:
Правильно. Я добавил класс, который позволяет GlobalKey быть зарегистрированным.
В моей основной форме у меня теперь есть этот ключ:
Public Class MainForm
Dim hkr As New HotKeyRegistryClass(Me.Handle)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
hkr.Register(HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.A).ToString()
hkr.Register(HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.S).ToString()
hkr.Register(HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.D).ToString()
hkr.Register(HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.F).ToString()
hkr.Register(HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.G).ToString()
hkr.Register(HotKeyRegistryClass.Modifiers.MOD_SHIFT Or HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.H).ToString()
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = HotKeyRegistryClass.Messages.WM_HOTKEY Then 'NOT THE ACTUAL WINDOWS NAMESPACE
Dim ID As String = m.WParam.ToString()
Select Case ID
Case 0 : If DF1Com1.Write("O:1/0", "1") Then DF1Com1.Write("O:1/0", "0")
Case 1 : MessageBox.Show("S")
Case 2 : MessageBox.Show("D")
Case 3 : MessageBox.Show("F")
Case 4 : MessageBox.Show("G")
Case 5 : MessageBox.Show("H")
End Select
End If
MyBase.WndProc(m)
End Sub
Если вы посмотрите на случай 0. Это работает, однако это не ставит ключ обратно. Это оставляет это нажатым все время. Мне нужно, когда клавиша нажата, это 'DF1Com1.Write("O:1/0", "0")'
Код класса
Public NotInheritable Class HotKeyRegistryClass
Private Declare Function RegisterHotKey Lib "user32.dll" (ByVal handle As IntPtr, ByVal id As Int32, ByVal fsModifier As Int32, ByVal vk As Int32) As Int32
Private Declare Function UnregisterHotKey Lib "user32.dll" (ByVal handle As IntPtr, ByVal id As Int32) As Int32
Private Handle As IntPtr = IntPtr.Zero
Private Registry As New System.Collections.Generic.List(Of Int32)
Public Enum Messages
[WM_HOTKEY] = &H312
End Enum
Public Enum Modifiers
[MOD_ALT] = &H1
[MOD_CTRL] = &H2
[MOD_SHIFT] = &H4
End Enum
Sub New(ByVal Handle As IntPtr)
Me.Handle = Handle
End Sub
Public Function Register(ByVal Modifier As Int32, ByVal Key As System.Windows.Forms.Keys) As Int32
Dim ret As Int32
ret = NextAvailableIndex()
Call RegisterHotKey(Me.Handle, ret, Modifier, Key)
Registry.Insert(ret, ret)
Return ret
End Function
Public Sub Unregister(ByVal ID As Int32)
Call UnregisterHotKey(Me.Handle, ID)
Registry.Remove(ID)
End Sub
Private Function NextAvailableIndex() As Int32
Dim ret As Int32 = 0
Dim n As Int32 = 0
For i As Int32 = 0 To Registry.Count - 1
If Registry(i) = n Then
n = n + 1
ElseIf n < Registry(i) Then
Return n
End If
Next
If n = Registry.Count Then
Return Registry.Count
End If
Return ret
End Function
End Class
2 ответа
К несчастью, RegisterHotkey
только говорит вам, когда комбинация клавиш была активирована. Кроме того, как вы уже поняли, KeyDown
а также KeyUp
Ваши события будут работать только тогда, когда ваше приложение сфокусировано.
Единственный способ получить действительно глобальный KeyDown
а также KeyUp
с помощью крючка клавиатуры низкого уровня. Поскольку я не хочу копировать весь свой ответ, я просто сделаю ссылку на него. По этой ссылке вы узнаете, как настроить клавиатуру.
Как отключить / переопределить Windows 10 горячих клавиш с помощью C#
Другая возможность - выполнить обе команды при активации горячей клавиши следующим образом...
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = HotKeyRegistryClass.Messages.WM_HOTKEY Then 'NOT THE ACTUAL WINDOWS NAMESPACE
Dim ID As String = m.WParam.ToString()
Select Case ID
Case 0 :
DF1Com1.Write("O:1/0", "1")
System.Threading.Thread.Sleep(2000)
DF1Com1.Write("O:1/0", "0")
Case 1 : MessageBox.Show("S")
Case 2 : MessageBox.Show("D")
Case 3 : MessageBox.Show("F")
Case 4 : MessageBox.Show("G")
Case 5 : MessageBox.Show("H")
End Select
End If
MyBase.WndProc(m)
End Sub
Другим вариантом для достижения этой цели может быть использование логического значения для отслеживания. Делая это, нажмите горячую клавишу, чтобы начать, затем нажмите еще раз, чтобы остановить.
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Static toggle As Boolean
If m.Msg = HotKeyRegistryClass.Messages.WM_HOTKEY Then 'NOT THE ACTUAL WINDOWS NAMESPACE
Dim ID As String = m.WParam.ToString()
Select Case ID
Case 0 :
If toggle Then
DF1Com1.Write("O:1/0", "0")
Else
DF1Com1.Write("O:1/0", "1")
End If
toggle = Not toggle
Case 1 : MessageBox.Show("S")
Case 2 : MessageBox.Show("D")
Case 3 : MessageBox.Show("F")
Case 4 : MessageBox.Show("G")
Case 5 : MessageBox.Show("H")
End Select
End If
MyBase.WndProc(m)
End Sub