0

I'm working on a little tray application that runs an action when a numpad key is pressed while the Numlock is off - with the following conditions:

  1. The application listens to the key presses even when it's out of focus.
  2. The app MUST distinguish between numpad vs. non-numpad keys that have the same effect (e.g. Numpad7 acts like Home when Numlock is off vs. Dedicated Home button on the keyboard).

I used this answer to register my global hotkeys so that the app listens to the keypresses while out-of-focus. The app runs but both Numpad7 and Home return the same keycode.

I also looked at this answer which gave me some insight that m.LParam.ToInt32() >> 24 == 1 implies Numpad key press, which didn't work for all keys (only seems to work for Enter/Return).

I have found this excellent Javascript-run website that actually checks the location of the keypress, returning Numpad when any numpad key is pressed with Numlock both on or off.

Any idea how to get a similar Numpad Keypress check in C#?


UPDATE:

Experimenting with what @Jimi suggested on the comments below, I have noticed that when checking against m.MSG == WM_KEYDOWN, evaluating m.LParam >> 24 results in 0 for non-Numpad keys, and 1 for Numpad keys. However, my application is checking against WM_HOTKEY, in order to listen to keypresses when the application is out of focus.

Here's how my WNdProc method looks like:

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    // check if we got a hot key pressed.
    if (m.Msg == 0x0312) // check if WM_HOTKEY
    {
        // get the keys.
        Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);
        ModifierKeys modifier = (ModifierKeys)((int)m.LParam & 0xFFFF);
        
        // here m.LParam is identical for both numpad-home and non-numpad home
        bool isNumpad = ((int)m.LParam >> 24) == 0;

        // invoke the event to notify the parent.
        if (KeyPressed != null)
            KeyPressed(this, new KeyPressedEventArgs(modifier, key, isNumpad));
    }
}

There isn't any obvious way in the documentation of WM_HOTKEY to check if the hotkey pressed is part of extended keyboard.

Ahmed A
  • 1
  • 1
  • Have you read this? It may be helpful to check for this state in your handler. https://stackoverflow.com/a/6135211/8695782 – Alexandru Clonțea Apr 01 '22 at 23:33
  • Does this answer your question? [How can I find the state of NumLock, CapsLock and ScrollLock in .NET?](https://stackoverflow.com/questions/577411/how-can-i-find-the-state-of-numlock-capslock-and-scrolllock-in-net) – Adnan Apr 01 '22 at 23:59
  • My code already implements your suggestions as a way to ensure Numlock is indeed off before triggering the action. However, what I'm looking for is a way to distinguish (for example) NumpadHome (which is Numpad 7 when Numlock is off) from OEM Home keys, as they both return the same value (Keys.Home). – Ahmed A Apr 02 '22 at 00:16
  • If you trap `WM_KEYDOWN`, `wParam` shows the same key (e.g., `Keys.Home = 0x24`, but the value of `lParam` is not the same when the Numeric Pad is used) – Jimi Apr 02 '22 at 05:35
  • In case the Docs are not clear enough, test whether bit 24 is set. If it's not, it's your NumPad. – Jimi Apr 02 '22 at 05:45
  • @Jimi - you're absolutely right! I did some experimentation and indeed bit 24 is set to 1 on the Numpad as the documentation mentions. Turned out my issue was I'm checking for bit 24 while trapping `WM_HOTKEY`, which is what I need for my app to listen for hotkeys while the form is out of focus. When trapping `WM_HOTKEY`, `lParam` is identical for `Home` and `NumpadHome`. Any idea how to go about performing the same check when capturing `WM_HOTKEY` instead? – Ahmed A Apr 02 '22 at 16:06
  • @Jimi I've updated the question with sample code to clarify what I'm after. – Ahmed A Apr 02 '22 at 22:15

0 Answers0