1
votes

I am writing an application that needs to temporarily disable the Play/Pause button that appears on multimedia keyboards.

Normally, a key can be blocked quite easily by installing a low level keyboard hook (WH_KEYBOARD_LL) where the KeyboardProc intercepts the key (in this case VK_MEDIA_PLAY_PAUSE) and returns 1 instead of calling CallNextHookEx. I have tried this with other keys (including the Windows key VK_LWIN) and this works perfectly. I also have no problems with this method under Windows 7 where all keys, including VK_MEDIA_PLAY_PAUSE get blocked.

Windows 8 is a different story. When my application has input focus, everything works as expected, meaning the VK_MEDIA_PLAY_PAUSE key gets blocked and no other application responds to it. However, when my application loses focus, my hook procedure gets called (this was verified by sending out a OutputDebugString) but other applications respond to key even though I return 1. As soon as my app gets focus again, everything is block as it should.

After some investigation, I found that the multimedia keys not only generate keystrokes but also generate WM_APPCOMMAND messages so I added ShellProc (WH_SHELL) hook with the following hook procedure:

LRESULT __declspec(dllexport)__stdcall  CALLBACK ShellProc(int nCode,WPARAM wParam,LPARAM lParam)
{
// Do we have to handle this message?
if (nCode == HSHELL_APPCOMMAND)
{
    OutputDebugStringX(">>>>>    HSHELL_APPCOMMAND");
    // Process the hook if the hNotifyWnd window handle is valid
        short AppCommand = GET_APPCOMMAND_LPARAM(lParam);
        switch (AppCommand)
        {
        case APPCOMMAND_MEDIA_NEXTTRACK:
        case APPCOMMAND_MEDIA_PLAY_PAUSE:
        case APPCOMMAND_MEDIA_PREVIOUSTRACK:
        case APPCOMMAND_MEDIA_STOP:
            OutputDebugString(">>>>>ShellProc got a media command");
            return 1;

        }
}

// Call the next handler in the chain
return CallNextHookEx (hsh, nCode, wParam, lParam);
}

This procedure is only getting called when my app has input focus. Whenever I have input focus and return 1 the Play/Pause command gets blocked. As soon as I lose focus the procedure does not get called/hooked.

Anyone have any idea as to what is going on? As I have mentioned, the code works for other keys, just not the multimedia keys. Everything works fine in Windows 7.

Alternatively, can anyone suggest another way of blocking the multimedia keyboards Play/Pause button?

1
Show us how you're setting up the hook.Adrian McCarthy
To set up the hook I am calling: hsh=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,hins,0); which returns successfullyLisaF

1 Answers

0
votes

From the MSDN documentation for ShellProc:

HSHELL_APPCOMMAND: The user completed an input event (for example, pressed an application command button on the mouse or an application command key on the keyboard), and the application did not handle the WM_APPCOMMAND message generated by that input. [Emphasis added.]

The emphasized portion suggests that your hook callback only gets called after an application ignores the WM_APPCOMMAND. In other words, you're too late.

To catch the message in flight, I think you need a different type of hook. Perhaps WH_GETMESSAGE or WH_CALLWNDPROC.

But why are you trying to prevent the users from interacting with their applications as they choose?