I'm hooking windows WM_CHAR message. When I'm replacing (in hook) given char code to something simple like 'a', every character I type is turning into a. And that's ok. But when I'm trying to send unicode character, like ф ('ф'.charCodeAt(0) gives 1092, so I'm replacing 'a' to 1092 in my code), all letters are turned into D. Also, when I type Alt+1092 in every text editor I'm getting D. Why? And can I send unicode char using WM_CHAR? Documentation says "The WM_CHAR message uses Unicode Transformation Format (UTF)-16.".
LRESULT CALLBACK Proc(int code, WPARAM wParam, LPARAM lParam)
{
if(code >= HC_ACTION)
{
MSG* msg=(MSG *)lParam;
if(msg->message==WM_CHAR)
{
int charCode = msg->wParam;
if(IsCharLower(charCode))
{
charCode = 1092;
msg->wParam=(WPARAM)charCode;
}
}
}
return CallNextHookEx(hHook, code, wParam, lParam);
};
Related
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?
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.
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.
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
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.