Media keys in WndProc not firing

391 Views Asked by At

I am creating a media player in WinForms, C#. I want to respond to the user pressing the multimedia keys on the keyboard using the following code that can be found all over the internet:

public const int WM_APPCOMMAND = 0x0319;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_APPCOMMAND)
    {
        switch ((int)m.LParam)
        {
            case 14: // MediaPlayPause
                TogglePlayPause();
                break;
            default:
                break;
        }
    }
    base.WndProc(ref m);
}

But it won't work. It just never recieves the key command. Media keys work with every other application (and the TogglePlayPause() method works as well).

1

There are 1 best solutions below

2
On

The value reported by LParam is a composite one.

As specified in the Docs, about WM_APPCOMMAND, the value can be extracted using:

cmd  = GET_APPCOMMAND_LPARAM(lParam);
uDevice = GET_DEVICE_LPARAM(lParam);
dwKeys = GET_KEYSTATE_LPARAM(lParam);

You need the cmd value.

In C#, it can be coded as:

private const int WM_APPCOMMAND = 0x0319;
private const int APPCOMMAND_MEDIA_PLAY_PAUSE = 14;

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);
    switch (m.Msg)
    {
        case WM_APPCOMMAND:
            int cmd = (int)m.LParam >> 16 & 0xFF;
            switch (cmd)
            {
                case APPCOMMAND_MEDIA_PLAY_PAUSE:
                    TogglePlayPause();
                    break;
                default:
                    break;
            }
            m.Result = (IntPtr)1;
            break;
        default:
            break;
    }
}

Edit:
Some meaningful links about KeyBoard Hooks and registering HotKeys.

On SetWindowHookEx:
SetWindowsHookEx WH_KEYBOARD_LL not getting events
Low-Level Keyboard Hook in C#

On RegisterHotKey:
Capture a keyboard keypress in the background