How do I detect keyPress while not focused?
Solution 1
Yes you can, it's called "System hooks", take a look at Global System Hooks in .NET.
Solution 2
Well, if you had problems with System hooks, here is ready-made solution (based on http://www.dreamincode.net/forums/topic/180436-global-hotkeys/):
Define static class in your project:
public static class Constants
{
//windows message id for hotkey
public const int WM_HOTKEY_MSG_ID = 0x0312;
}
Define class in your project:
public class KeyHandler
{
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
private int key;
private IntPtr hWnd;
private int id;
public KeyHandler(Keys key, Form form)
{
this.key = (int)key;
this.hWnd = form.Handle;
id = this.GetHashCode();
}
public override int GetHashCode()
{
return key ^ hWnd.ToInt32();
}
public bool Register()
{
return RegisterHotKey(hWnd, id, 0, key);
}
public bool Unregiser()
{
return UnregisterHotKey(hWnd, id);
}
}
add usings:
using System.Windows.Forms;
using System.Runtime.InteropServices;
now, in your Form, add field:
private KeyHandler ghk;
and in Form constructor:
ghk = new KeyHandler(Keys.PrintScreen, this);
ghk.Register();
Add those 2 methods to your form:
private void HandleHotkey()
{
// Do stuff...
}
protected override void WndProc(ref Message m)
{
if (m.Msg == Constants.WM_HOTKEY_MSG_ID)
HandleHotkey();
base.WndProc(ref m);
}
HandleHotkey is your button press handler. You can change the button by passing different parameter here: ghk = new KeyHandler(Keys.PrintScreen, this);
Now your program reacts for buton input even if not focused.
Solution 3
The API GetAsyncKeyState()
may be a perfectly acceptable alternative to setting up Windows Hook.
This depends on how you desire to receive the input. If you prefer event-driven notifications, then a hook is the way to go; however, if you prefer polling the keyboard for state changes, you can use the API above.
Here is a simple demonstration of how to use GetAsyncKeyState
:
Derived from Pinvoke.NET
[DllImport("User32.dll")]
private static extern short GetAsyncKeyState(int vKey);
private static readonly int VK_SNAPSHOT = 0x2C; //This is the print-screen key.
//Assume the timer is setup with Interval = 16 (corresponds to ~60FPS).
private System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
private void timer1_Tick(object sender, EventArgs e)
{
short keyState = GetAsyncKeyState(VK_SNAPSHOT);
//Check if the MSB is set. If so, then the key is pressed.
bool prntScrnIsPressed = ((keyState >> 15) & 0x0001) == 0x0001;
//Check if the LSB is set. If so, then the key was pressed since
//the last call to GetAsyncKeyState
bool unprocessedPress = ((keyState >> 0) & 0x0001) == 0x0001;
if (prntScrnIsPressed)
{
//TODO Execute client code...
}
if (unprocessedPress)
{
//TODO Execute client code...
}
}
Related videos on Youtube
James Holland
Updated on April 21, 2020Comments
-
James Holland about 4 years
I am trying to detect the
Print Screen
button press while the form is not the current active application.How to do that, if possible?
-
Surfbutler almost 11 yearsLooks like it might help: social.msdn.microsoft.com/Forums/en-US/…
-
-
user1696947 almost 9 yearsHow to edit this code, if i wanted 2 different hotkeys with two different functionality? Can i check somehow in "WndProc" or "HandleHotkey" which key was pressed?
-
Hue Man about 7 yearsCould this be adapted to handle key combinations? Such as CTRL-N
-
Michael about 6 yearsshouldn't the
if (prntScrnIs-->p<--ressed)
beif (prntScrnIs-->P<--ressed)
? -
Gaspa79 about 4 yearsI can't believe I'm the first one to upvote this. It's better if you want reliability due to the binding hotkey limitations. In my case f12 was bound to Skype but Skype wasn't doing anything with it. Monitoring raw input was the way to go. Thanks so much Nicholas!
-
arana over 3 yearsYes this is from my point of view the best solution, as you can use it to detect key combinations and even distinguish from left and right , shift/alt etc
-
Hugo Scott-Slade over 3 yearsYou can compare the message.wParam with the GetHashCode of the KeyHandler. They will match.