Blocking Keyboard Play/Pause Button in Win 8 - c++

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?

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?

Related

SetWindowsHookEx freezes on fast input or keyboard button hold

I'm having an issue with the keyboard logger. Every system tested until today is working fine, except a Windows 7 Embedded Standard 32 bit that apparently freaks out with the current build.
What I need to do is record keystrokes entered from the keyboard, until I get a certain number of them. When I do, I call a certain procedure.
I have a hook defined like this:
SetWindowsHookEx(WH_KEYBOARD_LL, keyboardProcedure, GetModuleHandle(NULL), 0);
and a keyboardProcedure callback:
LRESULT CALLBACK SystemKeyboardReadWrite::keyboardProcedure(int nCode, WPARAM wParam, LPARAM lParam)
{
...
}
I'm using Qt 5.2 for this application.
So, in more depth, the problem occurs when you enter the keys too fast or hold a certain key for a longer period of time, which will force the keyboard to send multiple keyboard events. When that happens, the hook will freeze and not send any more events to the callback. (not the entire application, the app will still continue running with the exception of the keylogger)
This problem occurs only on this OS, on no other Windows 7 OS, or Windows XP have I noticed the issue. I have 2 computers with the same setup and they both show the same problem, also I'm developing the app on a Windows 7 professional and it also seems fine.
I'm wondering if this is an issue with my application, or is it something outside of my control.
Thanks everyone for their help.
I don't know Windows Embedded, but I am familiar with Windows 7 and the LowLevel Hooks, both mouse and keyboard.
The symptom of getting kicked off the hook list can be reduced/modified with the LowLevelHooksTimeOut registry value. You have to reboot the system after it is modified. Basically that value says the number of milliseconds that hooks have to interact with the keys.
If you writing your file from inside the hook method, too, that could be the exact time when it times out, too.
For example, you get 100 key strokes, then you write it to a file. If they are holding down the keys across 100 to 101+, and you are taking longer than the maximum time with the hook, then Windows will blacklist your hook call back and kick you off the list of hooks.
The default time on Windows 7 (desktop) is 200 ms, I think. For embedded I wouldn't be surprised if it is less. Also when multiple programs are all hooking the keyboard, it can affect the timing of how long your hook is allowed to access it.
I also have only really used hooks that are established in a dll, and hold onto a global HHOOK handle. Watching all the return codes of your functions may also shed some light onto the situation.
More info on LowLevelHooksTimeout:
Low level Keyboard Hook works on one on Windows 7 x64 and not another

How do I stop Windows from blocking the program during a window drag or menu button being held down?

I am novice with Win32, and I have been pursuing a problem (if it can be called a problem at all) with Windows blocking your program's flow during the event when a user grabs the window title bar and moves it around the screen.
I have no legitimate reason to solve this problem, except that it bothers me. A few possibilities include removing the frame altogether, but it seems an inconvenient hack. Some games (single player) do not find this a problem at all. I have read however, that multiplayer games might experience problems when the program freezes as it expects continuous flow of information and can be overwhelmed after such a delay.
I have tried adding this to my WindowProc
switch (uMsg)
{
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE)
PostQuitMessage(0);
return 0;
...
...
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
And this seems a quick hack, except that when I mousedown over the close icon I can pull the mouse away and let go without closing the program, and during that time, when the close icon is held down, the program once again is blocked.
Furthermore, I do not know how to manually include the code necessary to move the window when the user clicks the titlebar and drags the mouse. For starters I do not know which uMsg's and wParam's to handle.
My question is then, how do I disallow blocking during the case when the user clicks down the exit button (or minimize/maximize buttons) while still handling the case when the mouse is clicked and released over the button, and how do I allow the user to move/drag the window without it blocking the program (or what message is sent when the title bar is clicked without it being a button or menu)?
I am creating the window with WS_SYSMENU | WS_MINIMIZEBOX.
I still want the program to respond to minimize, maximize, and exit commands.
If multi-threading can fix it, then that is interesting, but I wonder if I can get it to work on single-core processors. And I have read about hooks, but the MSDN page is still hard for me to interpret.
Why Is My App Freezing?—An Introduction to Message Loops & Threads
This phenomenon is not isolated to any particular message. It's a fundamental property of the Windows message loop: when one message is being processed, no other message can be processed at the same time. It's not exactly implemented this way, but you can think of it as a queue, where your app pulls the messages out of the queue to process in the reverse order that they are inserted.
Therefore, spending too long processing any message is going to suspend the processing of other messages, effectively freezing your application (because it cannot process any input). The only way to solve this problem is the obvious one: don't spend too long processing any one message.
Often that will mean delegating the processing to a background thread. You will still need to handle all messages on the main thread, and the background worker threads need to report back to the main method when they are finished. All interaction with the GUI needs to happen on a single thread, and that is almost always the main thread in your application (which is why it is often called the UI thread).
(And to answer an objection raised in your question, yes, you can operate multiple threads on single processor machines. You won't necessarily see any performance improvements, but it will make the UI more responsive. The logic here is that a thread can only do one thing at a time, but a processor can switch between threads extremely rapidly, effectively simulating doing more than one thing at a time.)
More useful information is available here in this MSDN article: Preventing Hangs in Windows Applications
Special Cases: Modal Event Processing Loops
Certain window operations on Windows are modal operations. Modal is a common word in computing that basically refers to locking the user into a particular mode where they cannot do anything else until they change (i.e. get out of that) modes. Whenever a modal operation is begun, a separate new message processing loop is spun up and message handling happens there (instead of your main message loop) for the duration of the mode. Common examples of these modal operations are drag-and-drop, window resizing, and message boxes.
Considering the example here of window resizing, your window receives a WM_NCLBUTTONDOWN message, which you pass to DefWindowProc for default processing. DefWindowProc figures out that the user intends to start a move or resize operation, and entered a moving/sizing message loop located somewhere deep in the bowels of Windows' own code. Thus, your application's message loop is no longer running because you've entered into a new moving/sizing mode.
Windows runs this moving/sizing loop as long as the user is interactively moving/sizing the window. It does this so that it can intercept mouse messages and process them accordingly. When the moving/sizing operation completes (e.g., when the user releases the mouse button or presses the Esc key), control will return to your application code.
It is worth pointing out that you are notified that this mode change has occurred via the WM_ENTERSIZEMOVE message; the corresponding WM_EXITSIZEMOVE message indicates that the modal event-processing loop has exited. That allows you to create a timer that will continue to generate WM_TIMER messages that your application can process. The actual details of how this is implemented are relatively unimportant, but the quick explanation is that DefWindowProc continues to dispatch WM_TIMER messages to your application inside of its own modal event processing loop. Use the SetTimer function to create a timer in response to the WM_ENTERSIZEMOVE message, and the KillTimer function to destroy it in response to the WM_EXITSIZEMOVE message.
I only point that out for completeness, though. In the majority of Windows apps that I've written, I've never needed to do that.
So, What Is Wrong With My Code?
Aside from all of that, the behavior you describe in the question are unusual. If you create a new, blank Win32 application using the Visual Studio template, I doubt you will be able to replicate this behavior. Without seeing the rest of your window procedure, I can't tell if you're blocking on any messages (as discussed above), but the part I can see in the question is wrong. You must always call DefWindowProc for messages that you do not explicitly process yourself.
In this case, you might be fooled into thinking that you're doing that, but WM_SYSCOMMAND can have lots of different values for its wParam. You only handle one of those, SC_CLOSE. All of the rest of them just get ignored because you return 0. That includes all of the window moving and resizing functionality (e.g. SC_MOVE, SC_SIZE, SC_MINIMIZE, SC_RESTORE, SC_MAXIMIZE, etc. etc.).
And there's really no good reason to handle WM_SYSCOMMAND yourself; just let DefWindowProc take care of it for you. The only time you need to handle WM_SYSCOMMAND is when you've added custom items to the window menu, and even then, you should pass every command that you do not recognize on to DefWindowProc.
A basic window procedure should look like this:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
It is also possible that your message loop is wrong. The idiomatic Win32 message loop (located near the bottom of your WinMain function) looks like this:
BOOL ret;
MSG msg;
while ((ret = GetMessage(&msg, nullptr, 0, 0)) != 0)
{
if (ret != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// An error occurred! Handle it and bail out.
MessageBox(nullptr, L"Unexpected Error", nullptr, MB_OK | MB_ICONERROR);
return 1;
}
}
You do not need hooks of any kind. The MSDN documentation on these is very good, but you're right: they're complicated. Stay away until you have a better understanding of the Win32 programming model. It is a rare case indeed where you need the functionality provided by a hook.
If multi-threading can fix it, then that is interesting but I wonder
if I can get it to work on single-core processors. And I have read
about hooks, but the MSDN page is still hard for me to interpret.
You can use multiple threads on a single-core processor. Performance would be better on multi-core systems, but that shouldn't prevent you from writing multithreaded applications. Anyway, go for it.
By printing all messages sent to WindowProc it appears WM_NCLBUTTONDOWN is sent last before the block occurs. You could check the mouse location after this event occurs, but it seems an inconvenient way to solve a simple problem.

Uninstalling keyboard hook when the user leaves the application

I am trying to detect when a user alt tabs out of my window. I have tried several messages (WM_ACTIVATE, WM_KILLFOCUS, WM_ACTIVATEAPP, WM_NCACTIVATE, WM_CANCELMODE, and WM_SYSCOMMAND checking for SC_MINIMIZE). But the same problem still occurs. The following happens.
My application is in focus, and I hold down alt and press tab.
The next window is brought forth.
I keep holding down alt and then press tab again, but this time, only tab is recognized and so I end up tabbing in the new window rather than alt tabbing again as is the usual behavior.
I am using a low level keyboard hook, and if I uninstall that this alt tabbing behavior described above works perfectly. I basically want to uninstall the keyboard hook as soon as the user leaves my window in this fashion. As soon as I release alt tab while in another window, my window receives several of the messages I look for and the hook is uninstalled. But when you hold the keys in this manner, it does not work as expected while the hook is installed.
why do you need to remove the keyboard hook? The SetWindowsHook is local to your application and not affect the other apps, therefore it already does nothing if your app doesn't have the focus.
Edit
make sure you call the next hook in your callback with CallNextHookEx to not screw up screen readers
I used the following code and it seems to be catching the focus changes, and I am not getting any problem with regard to holding down ALT or TAB in various combinations. But I didn't thoroughly test it yet.
EDIT: I read your post again and see that your problem is probably an interaction between the two different hooks. So I am also hooking the keyboard in my app, but I am using an Import Address Table hook of DispatchMessage. My hooks don't interact the way yours do, but my solution may not be appropriate for you.
bool AddHookToKeyboardFocusChanges()
{
HHOOK hhookFocusChange = NULL;
hhookFocusChange = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWindowProcHook, NULL, GetCurrentThreadId()); // the last parameter makes it a local, not global hook
if(hhookFocusChange == NULL)
return false;
return true;
}
///////////////////////////////////////////////////////////////////////////////
// This is the routine that we register to be called on every call to a
// WindowProc in our application; we use it to catch WM_SETFOCUS and
// WM_KILLFOCUS messages that indicate gaining or losing keyboard input focus.
// Unlike keyboard, mouse, paint, and timer messages, the focus messages are not
// posted to the message queue. Instead they are sent directly to WindowProc.
// We must hook them here.
//
LRESULT WINAPI CallWindowProcHook(int nCode, WPARAM wParam, LPARAM lParam)
{
UINT message = ((CWPSTRUCT*)lParam)->message;
switch(message)
{
case WM_ACTIVATE:
OutputDebugString(L"Window activated.\n");
break;
case WM_SETFOCUS:
OutputDebugString(L"Window focused.\n");
break;
case WM_KILLFOCUS:
OutputDebugString(L"Window focus lost.\n");
break;
default:
break;
}
// CallNextHookEx calls the next hook in the chain.
return CallNextHookEx(NULL, nCode, wParam, lParam);
}

How could I detect when my application is minimized?

I have a program with an option to enable minimizing to the taskbar's notification area. In order for this to work, I need a reliable way of detecting when the user has minimized the application.
How can I do that using the Windows API in a C++ application?
When the user minimizes the window (either using the box on the title bar, or by selecting the "Minimize" option from the system menu), your application will receive a WM_SYSCOMMAND message. The wParam parameter of that message will contain the value SC_MINIMIZE, which indicates the particular type of system command that is being requested. In this case, you don't care about the lParam.
So you need to set up a message map that listens for a WM_SYSCOMMAND message with the wParam set to SC_MINIMIZE. Upon receipt of such a message, you should execute your code to minimize your application to the taskbar notification area, and return 0 (indicating that you've processed the message).
I'm not sure what GUI framework you're using. The sample code could potentially look very different for different toolkits. Here's what you might use in a straight Win32 C application:
switch (message)
{
case WM_SYSCOMMAND:
if ((wParam & 0xFFF0) == SC_MINIMIZE)
{
// shrink the application to the notification area
// ...
return 0;
}
break;
}
I think you are looking for WM_SIZE. When you get this, check the wParam to get the specifics. Here is the MSDN page.
WM_SIZE
You can check the area size returned from GetClientRect - if zero it's minimised, works for me but may not work in all cases.
That's what IsIconic is supposed to determine, but it doesn't work consistently for me. (Oh, for a consistent way to determine this...)
For completeness, there's also GetWindowPlacement. The window state is revealed in the showCmd member of the WINDOWPLACEMENT structure, and if the window is minimized it has a value of 2, or SW_SHOWMINIMIZED.

Intercept mouse input

I was wondering if there is a way to intercept and modify mouse input before it gets to windows?
What I'm wanting to do is intercept mouse motion events, apply some custom scaling and acceleration to the values, and then continue passing them along. I'd need something that can do this before the inputs get to the raw input API or DirectInput.
In order to affect all mouse input, including DirectInput, during logon and the SAS screen, etc., you'll need to load a filter driver into the mouse driver stack.
Other people have done it, for example http://www.maf-soft.de/mafmouse/
There should be a moufiltr sample in the Windows DDK which you can use as a starting point. You will most likely want to use a virtual machine for development since errors in a driver on your development machine could be difficult to recover from.
Have you seen this method of intercepting mouse and keyboard input without having to make a filter driver or hook?
http://oblita.com/Interception.html
There is a LowLevelMouseProc hook procedure that you can use to get information on any mouse input entering the system, although I doubt if you can actually change this information (and the docs are silent on this).
If this fails, GetMsgProc is an alternative that lets you intercept all messages posted to any window. Though this hook does let you modify the message, it's probably too late to have any effect on APIs such as DirectInput.
You could try a windows hook - which are functions you set to receive windows messages before they get passed through to the rest of the system - a CBT hook (for computer based training) is what might get you best results.
I don't know Whether this will work with DirectInput or the other new stuff MS has added to break all the old internal consistency. Its easy to set up though, so try it and see.
As far as I know the best way is to hook to windows message loop, In your case you should pass HWND 0 (If I remember correctly this the HWND of the desktop) so all the messages will pass though your function first.
http://msdn.microsoft.com/en-us/library/ms633591%28VS.85%29.aspx
More on hooks : http://msdn.microsoft.com/en-us/library/ms644959%28VS.85%29.aspx
Use it as follows:
m_nOldWindowProc = ::SetWindowLong(0 /I think.../, GWL_WNDPROC, (LPARAM)(WNDPROC)WindowProcCallback);
and the callback:
LRESULT CALLBACK CStubWindow::WindowProcCallback(HWND hwnd,
UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_WINDOWPOSCHANGING:
((WINDOWPOS*)lParam)->cx = STATUS_BAR_WIDTH;
((WINDOWPOS*)lParam)->flags = SWP_NOOWNERZORDER | SWP_NOMOVE;
break;
default:
break;
}
return ::CallWindowProc(m_nOldWindowProc, hwnd, message, wParam, lParam);
}