Detect hotkeys from fullscreen game - vb.net

I've made an overlay extension for a fullscreen game. I want to activate different commands using hotkeys while in the game. I used to use GetAsyncKeyState and then use a timer to constantly check if the KeyState has changed. I then switched to using a RegisterHotKey function like the one shown below:
Imports System.Runtime.InteropServices
Public Class Form1
Public Const MOD_ALT As Integer = &H1 'Alt key
Public Const MOD_CONTROL As Integer = &H2 'CTRL key
Public Const MOD_SHIFT As Integer = &H4 'Shift key
Public Const MOD_NOREPEAT As Integer = &H4000 'NoRepeat
Public Const MOD_WIN As Integer = &H8 'Windows key
Public Const WM_HOTKEY As Integer = &H312
<DllImport("User32.dll")>
Public Shared Function RegisterHotKey(ByVal hwnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Integer
End Function
<DllImport("User32.dll")>
Public Shared Function UnregisterHotKey(ByVal hwnd As IntPtr, ByVal id As Integer) As Integer
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
RegisterHotKey(Me.Handle, 1, MOD_CONTROL + MOD_ALT + MOD_NOREPEAT, Keys.D)
RegisterHotKey(Me.Handle, 2, MOD_ALT, Keys.C)
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_HOTKEY Then
Dim id As IntPtr = m.WParam
Select Case (id.ToString)
Case "1"
MessageBox.Show("You pressed CTRL+ALT+D key combination")
Case "2"
MessageBox.Show("You pressed ALT+C key combination")
End Select
End If
MyBase.WndProc(m)
End Sub
Private Sub Form1_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
UnregisterHotKey(Me.Handle, 1)
UnregisterHotKey(Me.Handle, 2)
End Sub
End Class
This works perfect, and I'm able to use the noRepeat to only fire the function once even if i hold down the hotkeys, which is something i struggled with while using the GetAsyncKeyState and a timer. My problem is that the form wont registrer the keys being pressed when I'm inside the game. When I'm in any other program which isnt running in fullscreen it detects the hotkeys just fine. Should i go back to the GetAsyncKeyState or is there another way of detecting hotkeys even when inside a full screen game?

Related

vb.net hotkey registration with 2 modifiers

I’m working on a project that I need to register a hot key for, any I’m running into a wall trying to figure out how to add another letter modifier to the hotkey registrar. For example, CTRL+SHIFT, A+B. As of right now the code that I’m running works, but it only accepts one letter modifier. Can anyone show me where I’m going wrong? I was hoping it was as simple as adding the ‘And’ operant or ‘+’ to concatenate it as a string. Here’s an example of what I have that works.
Imports System.Runtime.InteropServices
Public Class Form1
Public Const MOD_ALT As Integer = &H1
Public Const MOD_SHIFT As Integer = &H4
Public Const MOD_CTRL As Integer = &H2
Public Const MOD_WIN As Integer = &H8
Public Const WM_HOTKEY As Integer = &H312
<DllImport("User32.dll")>
Public Shared Function RegisterHotKey(ByVal hwnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Integer
End Function
<DllImport("User32.dll")>
Public Shared Function UnregisterHotKey(ByVal hwnd As IntPtr, ByVal id As Integer) As Integer
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
RegisterHotKey(Me.Handle, 100, MOD_ALT Or MOD_SHIFT, Keys.A)'alt+shift,A
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_HOTKEY Then
Dim id As IntPtr = m.WParam
Select Case (id.ToString)
Case "100"
MessageBox.Show("You pressed alt+shift, A", "Hello", MessageBoxButtons.OK, MessageBoxIcon.Warning)
End Select
End If
MyBase.WndProc(m)
End Sub
Private Sub Form1_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
UnregisterHotKey(Me.Handle, 100)
End Sub
End Class
Like I said, this works so far, CTRL+SHIFT, A. What I’d like to do is modify it to accept an additional modifier key like, CTRL+SHIFT, A+B. Thank you in advance for your help!

VB.Net Hidden Program Hotkeys

Is there a way to register hotkeys to toggle a form from an invisible(hidden) program? I’ve tired normal methods and they only work when the form is either visible, or the active window. Thank you in advance for any help!
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.KeyPreview = True
Me.ShowInTaskbar = False
Me.ShowIcon = False
Me.Visible = False
End Sub
This is the code that hides the program.
You want to use Global Hotkeys. Just make sure you unregister when the program closes.
From a MSDN article that helped me in the past:
Firstly, you need to know the Virtual-Key Codes.
http://msdn2.microsoft.com/en-us/library/ms927178.aspx You can then
P/Invoke RegisterHotKey/UnregisterHotKey APIs to register/Unregister
the hotkey. Code sample: Register multiple hotkeys such as Alt+D,
Alt+C, etc.
Imports System.Runtime.InteropServices
Public Class Form1
Public Const MOD_ALT As Integer = &H1 'Alt key
Public Const WM_HOTKEY As Integer = &H312
<DllImport("User32.dll")> _
Public Shared Function RegisterHotKey(ByVal hwnd As IntPtr, _
ByVal id As Integer, ByVal fsModifiers As Integer, _
ByVal vk As Integer) As Integer
End Function
<DllImport("User32.dll")> _
Public Shared Function UnregisterHotKey(ByVal hwnd As IntPtr, _
ByVal id As Integer) As Integer
End Function
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
RegisterHotKey(Me.Handle, 100, MOD_ALT, Keys.D)
RegisterHotKey(Me.Handle, 200, MOD_ALT, Keys.C)
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_HOTKEY Then
Dim id As IntPtr = m.WParam
Select Case (id.ToString)
Case "100"
MessageBox.Show("You pressed ALT+D key combination")
Case "200"
MessageBox.Show("You pressed ALT+C key combination")
End Select
End If
MyBase.WndProc(m)
End Sub
Private Sub Form1_FormClosing(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.FormClosingEventArgs) _
Handles MyBase.FormClosing
UnregisterHotKey(Me.Handle, 100)
UnregisterHotKey(Me.Handle, 200)
End Sub
End Class

Keys overlapping on vb.net [a macro project on external program]

I'm making a VB Macro that uses F1~F12, and shift + F1~F12, and ctrl + F1~F12,
which must be working in an external program, such as browsers,
here comes the problem, the Shift + F1~F12 part are overlapping,
it's not working (on firefox), it overlaps with the HotKey/ShortCut of firefox,
(because it ended up as Shift+F1+ctrl+v)
any idea to fix this? :(
I'm using visual studio 2013.
Public Const MOD_CONTRO As Integer = &H2
Public Const MOD_SHIFT As Integer = &H4
Public Const WM_HOTKEY As Integer = &H312
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_HOTKEY Then
Dim id As IntPtr = m.WParam
Select Case (id.ToString)
Case "101"
Clipboard.SetText(System.IO.File.ReadAllText(Application.StartupPath & "\SF1.txt"))
SendKeys.Send("^" & "v")
'^This is the problem part,
End Select
End If
MyBase.WndProc(m)
End Sub
Private Sub Form1_FormClosing(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
UnregisterHotKey(Me.Handle, 101)
End Sub
Private Sub Home_Load(sender As Object, e As EventArgs) Handles MyBase.Load
RegisterHotKey(Me.Handle, 101, &H4, Keys.F1)
End Sub
Doing this fixed the problem,
as part of codes I learned from Joiner from here!
shift pressed, and automatically up?(to avoid long press and hold)
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)
Case "101"
Clipboard.SetText(System.IO.File.ReadAllText(Application.StartupPath & "\SF1.txt"))
keybd_event(&H10, 0, &H2, 0)
SendKeys.SendWait("^" & "v")

record pressed keys and amount of time they were pressed vb.net

It's a bit tricky, but how do I record the amount of time a key was pressed? My objective is to record the keys I pressed and the amount of time I pressed those keys, then be able to programatically use that recording whenever I want.
Your question is not too specific and thus there are many alternatives fitting there. If what you want is a rough introduction to the way in which this problem should be addressed, here you have some help:
Public Class Form1
Dim allStartTimes(50) As Date
Dim allElapsedTimes(50) As TimeSpan
Dim allKeys(50) As Keys
Dim curIndex As Integer = 0
Dim totKeys As Integer = 50
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Dim count As Integer = 0
Do
count = count + 1
If (e.KeyCode = allKeys(count)) Then
If (curIndex <> count) Then
If (curIndex > 0) Then
allElapsedTimes(curIndex) = Now.Subtract(allStartTimes(curIndex))
End If
allStartTimes(count) = Now
curIndex = count
Exit Do
End If
End If
Loop While (count < totKeys)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
allKeys(1) = Windows.Forms.Keys.A
allKeys(2) = Windows.Forms.Keys.B
'.....
End Sub
End Class
This code shows the basic algorithm and one alternative to get the keys: KeyDown/KeyUp events for a given object (in this case it is the main form; bear in mind that only works when the main form is selected). I haven't included the KeyUp part because of requiring some work to synchronise both events and to get it working properly (what you should be doing). This code does not store the time when the given key stops being pressed, but when a different one is pressed.
One alternative to events are hooks. They work everywhere (don't need to select a specific object) but also have their drawbacks. Here you have a working code:
Public Class Form1
Private Const WM_HOTKEY As Integer = &H312
Private Declare Function RegisterHotKey Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal id As Integer, ByVal fsModifier As Integer, ByVal vk As Integer) As Integer
Private Declare Function UnregisterHotKey Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal id As Integer) As Boolean
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
RegisterHotKey(Me.Handle, 0, Nothing, Keys.A)
RegisterHotKey(Me.Handle, 0, Nothing, Keys.B)
'.....
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If (m.Msg = WM_HOTKEY AndAlso m.WParam = CType(0, IntPtr)) Then
If (m.LParam = CType(4259840, IntPtr)) Then
'A
ElseIf (m.LParam = CType(4325376, IntPtr)) Then
'B
End If
'.....
End If
MyBase.WndProc(m)
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
UnregisterHotKey(Me.Handle, 0)
End Sub
End Class
List of parameters for all the keys to run the hook above. The shown A & B integer values represent just a quick solution for illustrative purposes.
Even there are further alternatives like relying on WPF: an example of a C# implementation.
These are the basic ideas. If you want a proper and reliable code you would have to do some research and testing to account for all the possible eventualities.

Registering 3 hotkeys? Possible?

Hello I am trying to use RegisterHeyKeys in VB.NET however I got it to work with 2 hotkeys I tried just adding in the third and it's giving a too many arguments. This is probably something really simple and I'm also a nub so go easy. lol. Any help would be greatly appreciated.
Here is the code so far:
Public Const MOD_CONTROL As Integer = &H11
Public Const MOD_SHIFT As Integer = &H10
Public Const WM_HOTKEY As Integer = &H312
<DllImport("User32.dll")> _
Public Shared Function RegisterHotKey(ByVal hwnd As IntPtr, _
ByVal id As Integer, ByVal fsModifiers As Integer, _
ByVal vk As Integer) As Integer
End Function
<DllImport("User32.dll")> _
Public Shared Function UnregisterHotKey(ByVal hwnd As IntPtr, _
ByVal id As Integer) As Integer
End Function
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
RegisterHotKey(Me.Handle, 100, MOD_CONTROL, MOD_SHIFT, Keys.D2)
RegisterHotKey(Me.Handle, 200, MOD_CONTROL, MOD_SHIFT, Keys.D3)
RegisterHotKey(Me.Handle, 300, MOD_CONTROL, MOD_SHIFT, Keys.D4)
End Sub
The problem as I see it is you have added two modifiers MOD_CONTROL and MOD_SHIFT and seperated them with a comma saying that you have five parameters to the function even though it only takes four. Try Oring together your Modifers like this. You also should verify your modifier keys with the Documentation they appear to not be correct.
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
RegisterHotKey(Me.Handle, 100, MOD_CONTROL Or MOD_SHIFT, Keys.D2)
RegisterHotKey(Me.Handle, 200, MOD_CONTROL Or MOD_SHIFT, Keys.D3)
RegisterHotKey(Me.Handle, 300, MOD_CONTROL Or MOD_SHIFT, Keys.D4)
End Sub
From the documentation it states(emphasis mine):
fsModifiers [in]
Type: UINT
The keys that must be pressed in combination with the key specified by the uVirtKey parameter in order to generate the WM_HOTKEY message. The fsModifiers parameter can be a combination of the following values.
Value Meaning
MOD_ALT 0x0001 Either ALT key must be held down.
MOD_CONTROL 0x0002 Either CTRL key must be held down.
MOD_NOREPEAT 0x4000 Changes the hotkey behavior so that the keyboard auto-repeat does not yield multiple hotkey notifications.
Windows Vista and Windows XP/2000: This flag is not supported.
MOD_SHIFT 0x0004 Either SHIFT key must be held down.
MOD_WIN 0x0008 Either WINDOWS key was held down. These keys are labeled with the Windows logo. Keyboard shortcuts
that involve the WINDOWS key are reserved for use by the operating system
Here is a Working example of your program.
Public Const MOD_CONTROL As Integer = &H2
Public Const MOD_SHIFT As Integer = &H4
Public Const WM_HOTKEY As Integer = &H312
<DllImport("User32.dll")> _
Public Shared Function RegisterHotKey(ByVal hwnd As IntPtr, _
ByVal id As Integer, ByVal fsModifiers As Integer, _
ByVal vk As Integer) As Integer
End Function
<DllImport("User32.dll")> _
Public Shared Function UnregisterHotKey(ByVal hwnd As IntPtr, _
ByVal id As Integer) As Integer
End Function
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
RegisterHotKey(Me.Handle, 100, MOD_CONTROL Or MOD_SHIFT, Keys.D2)
RegisterHotKey(Me.Handle, 200, MOD_CONTROL Or MOD_SHIFT, Keys.D3)
RegisterHotKey(Me.Handle, 300, MOD_CONTROL Or MOD_SHIFT, Keys.D4)
End Sub
Protected Overrides Sub DefWndProc(ByRef m As System.Windows.Forms.Message)
MyBase.DefWndProc(m)
If m.Msg = WM_HOTKEY Then
Select Case CType(m.WParam, Integer)
Case 100
NotifyIcon1.Text = "Hello"
NotifyIcon1.ShowBalloonTip(2000, "", NotifyIcon1.Text, ToolTipIcon.Info)
Case 200
NotifyIcon1.Text = "World"
NotifyIcon1.ShowBalloonTip(2000, "", NotifyIcon1.Text, ToolTipIcon.Info)
Case 300
NotifyIcon1.Visible = False
If Not Visible Then Visible = True
End Select
End If
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Me.Hide()
NotifyIcon1.Icon = Me.Icon
NotifyIcon1.Visible = True
End Sub