I have a application that always checks if a key like F12 is pressed. It doesn't need to have in focus of my main window of my app. I tried this code:
public int a = 1;
// DLL libraries used to manage hotkeys
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
const int MYACTION_HOTKEY_ID = 1;
public Form1()
{
InitializeComponent();
// Modifier keys codes: Alt = 1, Ctrl = 2, Shift = 4, Win = 8
// Compute the addition of each combination of the keys you want to be pressed
// ALT+CTRL = 1 + 2 = 3 , CTRL+SHIFT = 2 + 4 = 6...
RegisterHotKey(this.Handle, MYACTION_HOTKEY_ID, 0, (int) Keys.F12);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0312 && m.WParam.ToInt32() == MYACTION_HOTKEY_ID)
{
a++;
MessageBox.Show(a.ToString());
}
base.WndProc(ref m);
}
I put 0 to this line RegisterHotKey(this.Handle, MYACTION_HOTKEY_ID, 0, (int) Keys.F12);
so that only if F12 is pressed it will capture.
But it didn't work. How can I solve this?
Here I couldn't understand some lines like:
const int MYACTION_HOTKEY_ID = 1;
m.Msg == 0x0312 && m.WParam.ToInt32() == MYACTION_HOTKEY_ID
base.WndProc(ref m);
Can anyone help me to understand these lines?
To do a similar thing I implemented a low-level keyboard hook using
SetWindowsHookEx
. That will trap all keyboard messages going through Windows, and allow you to inspect them and if necessary, prevent them going any further.Take a look at my KeyboardHandling project in my RocketLauncher GitHub hobby project. You can take what you need directly from that. I'm going to make it a nuget package soon, too.
Your code has no wrong . But it doesn't work here because the F12 key is reserved you may try with another key like F10, F11 etc .
I don't know why, but I feel like this is related to this question... so I'm gonna try to explain it once more:
is where you save the integer that is used to identify the hotkey. If you need to register more than on hotkey, you will have to declare other integer fields identifying the other hotkeys:
Then,
is the condition that enables you to know which hotkey has been typed by the user.
0x0312
(also declared asWM_HOTKEY
in the documentation you can found here for instance) is to know if a registered hotkey has been pressed:According to the documentation, you cannot use the F12 hotkey:
What do you mean "it didn't work"? The code in your question looks correct to me.
The only reason it might not be working is because the
RegisterHotKey
function is returning an error and you're not checking for it. To make this work, you need to add theSetLastError
attribute to its declaration, which causes the runtime to cache the Win32 error code that it sets. Once this is done, you can check that error code (if the function returnsfalse
) by calling theGetLastWin32Error
function. I recommend using the result of this function to generate and throw aWin32Exception
.Modify your declaration of
RegisterHotKey
as follows:And your call to the function as follows:
Once that's done, I suspect you'll see an exception getting thrown with the error message:
Well, that makes debugging the problem much simpler, now doesn't it! Chances are you'll need to select a different hot key, since the
RegisterHotKey
function documentation tells us explicitly that:When I run the code and register F11 as a hotkey, it works just fine for me.
Sure:
The first line declares a constant value that uniquely identifies the hotkey that you installed using the
RegisterHotKey
function. More specifically, it corresponds to theid
parameter of the function. You passed it in on the initial call.This checks in the window procedure (
WndProc
) to see if the message (Msg
) that is being processed is theWM_HOTKEY
message. TheWM_HOTKEY
message is posted automatically to your window whenever the hot key you registered with theRegisterHotKey
function is pressed.You shouldn't really be using the magic number
0x0312
directly, though, because you're not the only one who is unsure what it means. Instead, define a constant and use that instead:The second part of that conditional test (the part after the
&&
) checks thewParam
field of the message to see if the hot key that was pressed was the one you registered. Remember thatMYACTION_HOTKEY_ID
is the unique ID of your hot key. TheWM_HOTKEY
message documentation tells us that checking thewParam
is how we determine which hot key was pressed.This calls the base class's window procedure. In other words, what you've done is overridden the virtual
WndProc
method, allowing you to add some additional code (your processing ofWM_HOTKEY
). When you're done with your additional logic, you want to continue with the logic of the base class, so you forward the message on.