Virtual key code of ALT KEY - windows

I am making hooks and catching keyboard virtual key codes, according to MSDN, these are the key codes that exist.
Every key code works fine as i will give an example down below of my code.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
HHOOK altKey;
KBDLLHOOKSTRUCT kbdHK;
MSG message;
LRESULT CALLBACK kbdProc(int nCode, WPARAM wPar, LPARAM lPar);
int main(int argc, char *argv[]) {
altKey = SetWindowsHookEx(WH_KEYBOARD_LL, kbdProc, NULL, 0);
while(GetMessage(&message, NULL, 0, 0) > 0){
TranslateMessage(&message);
DispatchMessage(&message);
}
return 0;
}
LRESULT CALLBACK kbdProc(int nCode, WPARAM wPar, LPARAM lPar){
if(nCode >= 0){
if(wPar == 256){
kbdHK = *(KBDLLHOOKSTRUCT *)lPar;
if(kbdHK.vkCode == 0x20){
printf("spacebar pressed!!\n");
}
}
}
return CallNextHookEx(NULL, nCode, wPar, lPar);
}
But when I replace the virtual key code with 0x12 which is ALT KEY according to MSDN, I can't get a result back. What could be the problem?
Edit:
When I use this line of code, I can get the scanCode for every key but not for alt key again which is interesting.
printf("%d", kbd.scanCode);

I suggest hooking the WM_SYSKEYDOWN messages, and noting that the values correspond to constants that more often have identifiers (VK_MENU, in this case). After all, as programmers we're taught early on not to use magic numbers!
WM_SYSKEYDOWN message
Posted to the window with the keyboard focus when the user presses the F10 key (which activates the menu bar) or holds down the ALT key and then presses another key.
Another option, as pointed out in the comments, is to use GetAsyncKeyState. Your concerns that you won't be able to use vkCode seem strange, as GetAsyncKeyStates parameter is the virtual key code, after all, so the code you'd be using would be along the lines of:
short result = GetAsyncKeyState(VK_MENU);
if (!result) {
// no alt keystrokes since last call
}
This is the only way you'll be able to distinguish between left alt (VK_LMENU) and right alt (VK_RMENU) keys, but it's not the window-loop way. Now you have both.

Related

How does lparam and wparam work in this specific code example?

I'm reading at some coding examples from Microsoft. And get confused by this combined key part.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SYSKEYDOWN:
if (wParam == VK_RETURN && (lParam & 0x60000000) == 0x20000000)
{
//Do something
}
}
}
Here is what I don't understand, this code is about switching the application between fullscreen and windowed when pressing Alt+Enter. I get that WM_SYSKEYDOWN is holding Alt, and VK_RETURN is pressing Enter. So when they put together it means pressing Enter while holding Alt, but how do these two parameters work? Why Enter is in wParam and what does the lParam part on the right mean? What does the value of lParam represents? Please help.
I have another thing I'd like to ask.
Why it uses 0x60000000? It is a 31 bit start with 2 "1"s followed by 29 "0"s. From the document provided by tkausl, the 31th bit of WM_SYSKEYDOWN is always 0, so with a "&" operator, there should be no way the output will have a "1" at that bit, so why not just use 0x20000000 which should give the exactly same result?

Trouble catching WM_INPUT message for lParam, to collect Raw Mouse Input

For my college project I am developing a solution to distinguish between mouse user data from a person with Parkinson's compared to a healthy person. For which I need mouse data, ideally raw.
I presume I have misunderstood how to collect raw mouse input from the WM_INPUT message but I cannot figure it out.
I have been looking at the following thread: How to accurately measure mouse movement in inches or centimetres for a mouse with a known DPI
and Mouse input libraries on github all of which seem to easily catch a WM_INPUT message whose lParam is a handle to some RawInputData with something like this:
GetMessage(&msg, GetActiveWindow(), WM_INPUT, 0);
if (msg.message == WM_INPUT){ .....
And then retreiving the lParam from the message and collecting the data associated with that handle with:
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
However when I call GetMessage in my main loop, the function never exits!
Consequently there is no way (that i know of) for me to get a handle to the RawInputData. Especially since the MSDN page just assumes you have the lParam already.
In summary I need a method of getting an lParam to pass to the GetRawInputData function which will remain active whether the program is running in the active window of not.
I'm running this code in a blank C++ CLR project in Visual Studio with the "winuser.h" library.
#include "stdafx.h"
#include "Windows.h"
#include "winuser.h"
#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02)
#endif
int main(array<System::String ^> ^args)
{
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = 0; //ideally RIDEV_INPUTSINK but that prevents registration
Rid[0].hwndTarget = GetActiveWindow(); //ideally this would be Null to be independent of the active window
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
//registration failed. Call GetLastError for the cause of the error
Console::WriteLine("Registration Error");
}
MSG msg;
while (true) {
while (GetMessage(&msg, GetActiveWindow(), WM_INPUT, 0) != 0) { //this command is never completed
DispatchMessage(&msg); //this line is never ran
}
if (msg.message == WM_INPUT) {
Console::WriteLine("caught a message!!!");
}
}
}
Issue solved after much more research I found the winAPI walk through which I followed fixing the issue above by adding an:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE unused, PSTR cmd, int show) {.....}
Function to register devices and create a window then call GetMessage which calls LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {....} with the parameters occupied by the message ID,WParam and LParam corresponding the message event.
For anyone stuck with a similar issue follow this MSDN guide: https://msdn.microsoft.com/en-us/library/bb384843.aspx

How can I get the mouse cursor type in windows (default, hand, wait, resize etc)?

I would like to receive a notification when the mouse cursor change from arrow to hour glass etc.
Until now I managed to get notified for mouse position change events, but I can not figure out how to get the cursor type. It looks like the PCURSORINFO struct does not contain any information about the cursor type.
This is the code I have until now:
static LRESULT CALLBACK WinEventCallback(_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam)
{
PCURSORINFO curInfo;
curInfo->cbSize = sizeof(curInfo);
GetCursorInfo(curInfo);
}
void MouseCursorHook::setMouseCursorHook()
{
HHOOK evntHook = SetWindowsHookEx(WH_MOUSE_LL,
WinEventCallback,
GetModuleHandle(0),
0
);
}
First off, your call to GetCursorInfo() is wrong. You are passing it an uninitialized pointer. It should be like this instead:
CURSORINFO curInfo = {};
curInfo.cbSize = sizeof(curInfo);
GetCursorInfo(&curInfo);
Second, CURSORINFO has a hCursor field. You can compare that against the return value of LoadCursor()/LoadImage() to see if a standard cursor is being used or not. You will have to compare each standard cursor individually, though.

WINAPI keyboards detect other application hotkeys

Goal : I want to know that the user did or did't press on some hotkeys that i want to know it, like i want to know he/she press Ctrl + N on chrome
i try to detect the application hotkeys, like maybe chrome Ctrl + N is open new tab.
How winapi can detect this?
i have seen some article that said WM_KEYUP + WM_KEYDOWN, but the wParam one times can get one WM_KEYUP or WM_KEYDOWN, how implement it ?
int main(int argc, char *argv[])
{
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardHookProc, hInstance, 0);
hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, hInstance, 0);
while (GetMessage(&message,NULL,0,0)) {
TranslateMessage( &message );
DispatchMessage( &message );
}
UnhookWindowsHookEx(hHook);
UnhookWindowsHookEx(hMouseHook);}
KeyBoardHookProc(int nCode, WPARAM wParam, LPARAM lParam){
KBDLLHOOKSTRUCT cKey = *((KBDLLHOOKSTRUCT*)lParam);
.................
if(wParam == WM_KEYUP)
{
kp.HandlekeyboardInfo(lpszName, buffer);
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
Thanks for helping!!
There are a few different ways you can do this. The easiest is probably to register a hotkey within your application and let windows notify you when the key combination is pressed.
RegisterHotKey
Another method would be to register a keyboard hook. All keypresses will be passed to your application, but you'll have to determine what keys were pressed. If you go this route, make sure to call CallNextHookEx().
SetWindowsHookEx

KeyPress with multiple modifiers not working in QWidget

I have added an override for my main widget's keyPressEvent:
void MainWindow::keyPressEvent(QKeyEvent* e)
{
if (e->key() == Qt::Key_F11)
{
if (e->modifiers() & Qt::AltModifier && e->modifiers() & Qt::ControlModifier)
{
// do stuff
}
}
}
The problem is that it does not work. If I try the AltModifier or ControlModifier alone it works (while changing the second condition of course), but not for both of them. The key() won't equal to Qt::Key_F11 while I do press F11. I'm using windows.
Edit: checked with logging and the result is that Ctrl+Alt+F11 and Ctrl+Alt+F12 do not send a key event (while other Ctrl+Alt+Fxx keys do).
Oook, so I managed to solve it though I'm not exactly pleased with the solution. At least there is no mystery and it works :).
The reason why I didn't receive the hotkeys Ctrl+Alt+F11 and Ctrl+Alt+F12
They were registered as global hotkeys. I managed to find this out using the ActiveHotkeys program of the fellow stackoverflow member moodforaday (thanks a lot for it!). Apparently there is no documented way to find out which program registered a particular hotkey (and it didn't do anything on my system). See moodforaday's thread about the issue.
The solution
One of the answers in the aforementioned thread led me to another question. Efotinis' answer was absolutely perfect for me. I did not have experience with setting up low-level keyboard hooks, but it was not nearly as difficult as it sounds. For future's sake, here is how I did it in my Qt application:
In my mainwindow.h:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
// ... code
private:
void tryLogin();
friend LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wparam, LPARAM lparam);
};
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wparam, LPARAM lparam);
In my mainwindow.cpp:
// setting up the hook in the constructor
SetWindowsHookEx(WH_KEYBOARD_LL,
LowLevelKeyboardProc,
NULL,
0);
The hook code (mostly from efotinis' answer):
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wparam, LPARAM lparam)
{
KBDLLHOOKSTRUCT* kllhs = reinterpret_cast<KBDLLHOOKSTRUCT*>(lparam);
if (code == HC_ACTION)
{
if (wparam == WM_KEYDOWN && kllhs->vkCode == VK_F12 &&
(GetAsyncKeyState(VK_MENU) < 0 && GetAsyncKeyState(VK_CONTROL) < 0))
{
MainWindow* w = dynamic_cast<MainWindow*>(qApp->activeWindow());
if (NULL != w)
{
w->tryLogin(); // this should not be blocking!
return 1;
}
}
}
return CallNextHookEx(0, code, wparam, lparam);
}
As you can see, we get the pointer to the application window from the global QApplication object. We use dynamic_cast so in the active window happens to not be a MainWindow instance we would get a NULL pointer.
If you are wondering why the GetAsyncKeyState calls are checked for < 0, it's because this function returns with MSB set if the key is down. And when the MSB is set, the SHORT number is negative (on x86/x64 and compatible platforms). If windows ever gets ported to a platform where signed integers are represented differently, this code might break. The absolutely proper way would be to create a 16-bit mask and use that to check the MSB, but I'm lazy to do that. :)
One thing to note is that when you call a function from your hook, the Qt event loop has just begun processing. That means until you don't return from your function, it will block the UI (freezing it for a few seconds). If you wanted to show a dialog like I did, instead of exec(), call raise, activateWindow and show, while setting the window modality of the dialog to modal (in its constructor maybe).
You can unregister the hook with UnHookWindowsHookEx if you want to (which happens when the module containing the hook is unloaded). To do this, save the return value of the SetWindowsHookEx call.

Resources