Reputation: 674
First of all, I am not a true coder however I am happy with what I have done thus far.
I have written this code below which is to do with robotics. The code below allows me to user keyboard shortcuts when you click on the form. However, I need the hotkeys to work whether the application is or is not in focus or even minimized.
I have looked already online but it is not very clear.
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
Update:
Right. I have added a class now which allow GlobalKey to be registered.
In my main form I now have this key:
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
If you have a look at Case 0. It works however it does not put the key back up. It leaves it pressed down all the time. I need it when the key is depressed it 'DF1Com1.Write("O:1/0", "0")'
Class Code
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
Upvotes: 1
Views: 1607
Reputation: 1473
Another option for accomplishing this could be to use boolean to keep track. Doing this means, press the hotkey to start then press again to stop.
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
Upvotes: 0
Reputation: 1473
Unfortunately, RegisterHotkey
only tells you when a key combination has been activated. Also, as you already realize, the KeyDown
and KeyUp
events you have will only work when your app has focus.
The only way you can get truly global KeyDown
and KeyUp
is by using a low level keyboard hook. Since I don't want to copy my entire answer I will simply link to it. The link will provide you some direction in setting up a keyboard hook.
How to disable/override Windows 10 Hotkeys with C#
Another possibility is to execute both commands on the hotkey activation like this...
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
Upvotes: 1