my program knows 2 states: A annd B, where A is the default state.
When you press ALT-# it should change it's state to B and when you release the combination it should go back to A.
This should work with a LowLevel Keyboard hook but it seems I am stuck somewhere.
#define VK_POUND 0xBF // 191 - the # key
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode == HC_ACTION) {
KBDLLHOOKSTRUCT* kbdStruct = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
switch (wParam) {
case WM_KEYDOWN: {
std::cout << kbdStruct->vkCode << "\n";
if (kbdStruct->vkCode == VK_POUND && kbdStruct->flags & LLKHF_ALTDOWN) {
MessageBox(NULL, "WE GOT IT", "", MB_OK);
}
} break;
case WM_KEYUP: {
} break;
}
}
return CallNextHookEx(g_HotKeyHook, nCode, wParam, lParam);
}
What confuses me: When I press the combination ALT and # there is no output in the console.
Related
When I put the hook on the mouse, I periodically lose sensitivity, it increases by ~0.3 seconds (approximately twice). How can I fix this?
My handler code:
LRESULT CALLBACK mouseProc(int Code, WPARAM wParam, LPARAM lParam){
MOUSEHOOKSTRUCT* pMouseStruct = (MOUSEHOOKSTRUCT*)lParam;
if (pMouseStruct != nullptr) {
switch (wParam) {
case WM_LBUTTONDOWN:
std::cout << "WM_LBUTTONDOWN";
break;
case WM_LBUTTONUP:
std::cout << "WM_LBUTTONUP";
break;
case WM_RBUTTONDOWN:
std::cout << "WM_RBUTTONDOWN";
break;
case WM_RBUTTONUP:
std::cout << "WM_RBUTTONUP";
break;
default:
break;
}
}
return CallNextHookEx(NULL, Code, wParam, lParam);}
I put the hook this way:
HHOOK hook = SetWindowsHookEx(WH_MOUSE_LL, mouseProc, NULL, 0);
MSG message;
while (GetMessage(&message, NULL, 0, 0) > 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
UnhookWindowsHookEx(hook);
You lose sensitivity in this code, because std::cout is very slow. You need a very quick response for this hooking or you obviously lose sensitivity.
If you really need to log in your hook, use something like spdlog and log everything asynchronously.
In addition, as Richard mentioned in comments, you need something like this at start of your hook:
if (nCode < 0) // do not process message
return CallNextHookEx(hhook, nCode, wParam, lParam);
I'm trying to use SetWindowsHookExA() with WH_MOUSE_LL to ready low level mouse clicks that are injected.
Here is my code for hooking.
DWORD dwThreadMain; // The process main thread. (Already have this)
HWND mainWindow; // Already have this pointer
MSG hMsg;
MouseHOOK = SetWindowsHookExA(WH_MOUSE_LL, MouseHookProc, NULL, dwThreadMain);
if (!MouseHOOK) {
// Cant't Hook
}
KeyBoardHOOK = SetWindowsHookExA(WH_KEYBOARD_LL, KeyBoardHookProc, NULL, dwThreadMain);
if (!KeyBoardHOOK) {
// Cant't HOOK
}
while (GetMessage(&hMsg, mainWindow, 0, 0)) {
TranslateMessage(&hMsg);
DispatchMessage(&hMsg);
}
This is my MouseHookProc and KeyBoardHookProc:
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION) {
if (wParam == WM_RBUTTONUP || wParam == WM_RBUTTONDOWN
|| wParam == WM_LBUTTONUP || wParam == WM_LBUTTONDOWN) {
MSLLHOOKSTRUCT* hookStruct = (MSLLHOOKSTRUCT*)lParam;
if ((hookStruct->flags & LLMHF_INJECTED) == LLMHF_INJECTED) {
MessageBoxA(NULL, "MOUSE INJECTED!", "POOR MOUSE", MB_OK);
return TRUE;
}
if ((hookStruct->flags & LLMHF_LOWER_IL_INJECTED) == LLMHF_LOWER_IL_INJECTED) {
MessageBoxA(NULL, "MOUSE INJECTED!", "POOR MOUSE", MB_OK);
return TRUE;
}
}
}
return CallNextHookEx(MouseHOOK, nCode, wParam, lParam);
}
LRESULT CALLBACK KeyBoardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION) {
if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) {
KBDLLHOOKSTRUCT* hookStruct = (KBDLLHOOKSTRUCT*)lParam;
if ((hookStruct->flags & LLKHF_INJECTED) == LLKHF_INJECTED) {
MessageBoxA(NULL, "KEYBOARD INJECTED!", "POOR KEYBOARD", MB_OK);
return TRUE;
}
if ((hookStruct->flags & LLKHF_LOWER_IL_INJECTED) == LLKHF_LOWER_IL_INJECTED) {
MessageBoxA(NULL, "KEYBOARD INJECTED!", "POOR KEYBOARD", MB_OK);
return TRUE;
}
}
}
return CallNextHookEx(KeyBoardHOOK, nCode, wParam, lParam);
}
The problem here is not on hooking, the message boxes are showing when the injected flag is there. The KeyBoard blocks the input. But only in mouse, the 'return TRUE' don't prevent the click to be processed.
I Think I've missed something... There is another way to do this?
The focus event on the combo box is generated twice.
this is the code for the Action Procedure of the Dialog box.
INT_PTR DialogBox::ActionProc(
HWND hwndDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case COMBOBOX:
{
if (CBN_SETFOCUS == HIWORD(wParam))
{
MessageBox(
hwndDlg,
CString("Test"),
CString("Test"),
(MB_ICONEXCLAMATION | MB_OK));
}
break;
}
default:
break;
}
break;
}
default:
break;
}
return INT_PTR(true);
}
the MessageBox Gets displayed twice(because the focus event is generated twice on the combo box). Is there a way to display it only once.
I have tried focussing to another element such as:
INT_PTR DialogBox::ActionProc(
HWND hwndDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case COMBOBOX:
{
if (CBN_SETFOCUS == HIWORD(wParam))
{
MessageBox(
hwndDlg,
CString("Test"),
CString("Test"),
(MB_ICONEXCLAMATION | MB_OK));
SendDlgItemMessage(
hwndDlg,
ANOTHER_CONTROL,
WM_SETFOCUS,
0,
0);
}
break;
}
default:
break;
}
break;
}
default:
break;
}
return INT_PTR(true);
}
Can some one tell me what i am doing wrong.
This is in Windows Desktop API.
Hi I need help with this hook I am learning about hooks and I am doing one easy example to learn more about setwindowshookex of microsoft.
The first thing I am trying to include different control keys like ctrl, enter, etc I have tried this code:
if( wParam == WM_SYSKEYDOWN ){
switch (wParam)
{
case VK_SHIFT:
qDebug() << "prueba";
break;
default:
break;
}
}
Obviously didnt work. So i can do comparing but i prefer to include some type to check control key separated. At the same i am trying to include something to separate when i using different applications like notepad for learning.
The normal way you check for modifier keys in a keyboard hook function is using GetKeyState, e.g.
LRESULT DLL_CALL KeyboardFunc (int nCode, WPARAM wParam, LPARAM lParam)
{
...
if (nCode < 0)
return (CallNextHookEx (hKeyHook, nCode, wParam, lParam));
if (nCode == HC_NOREMOVE)
return (CallNextHookEx (hKeyHook, nCode, wParam, lParam));
switch (wParam)
{
case VK_F12 :
// Check for modifier keys:
if ((GetKeyState (VK_CONTROL) & iHiOrder) && // ctrl key
(GetKeyState (VK_SHIFT) & iHiOrder) && // shift key
(GetKeyState (VK_MENU) & iHiOrder) // Alt key
{
}
where HiOrder is a const SHORT value with the high-order bit set.
I am doing a voice chat application which uses a push-to-talk key. I have done a hook so it will register push-to-talk outside application too.
HHOOK hHook = SetWindowsHookEx(WH_KEYBOARD_LL,(HOOKPROC)pushtotalk,0,0);
LRESULT CALLBACK pushtotalk(int key, WPARAM wParam,LPARAM lParam) {
if (key < 0) {
return (CallNextHookEx(hook,key,wParam,lParam));
}
else if (connected) {
KBDLLHOOKSTRUCT* kbdll = (KBDLLHOOKSTRUCT*)lParam;
if (kbdll ->vkCode == 75 && wParam == WM_KEYDOWN) {
MessageBox(mainhWnd,"KEYSTART","KEYSTART",0);
}
else if (kbdll ->vkCode == 75 && wParam == WM_KEYUP) {
MessageBox(mainhWnd,"KEYSTOP","KEYSTOP",0);
}
}
return (CallNextHookEx(hook,key,wParam,lParam));
}
Problems;
1) Sometimes, (for example the first execution of the proc in the application), the proc causes a 5 sec system freeze before continuing. Why?
2) The hook only works on process that were started before my application started, if I start a text program after starting my application, the hooks wont register. Is there a fix for this?
3) If I hold down the key for ~3 seconds, alot of MessageBoxes shows obviously, but after that, the proc will never register another key being pushed down, so I guess I somehow gets disconnected from the hook chain?
Cheers
EDIT: Here's the main message loop for the application
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case ID_MENU_EXIT:
SendMessage(hWnd,WM_CLOSE,0,0);
break;
case ID_MENU_PREFERENCES:
voiceManager->send((void*) "1");
break;
case ID_BUTTON_CONNECT:
onConnect(hWnd);
break;
case ID_BUTTON_DISCONNECT:
onDisconnect(hWnd);
break;
case ID_BUTTON_SEND:
onSendText(hWnd);
break;
default:
break;
}
break;
case SOCKET_TCP:
switch (lParam) {
case FD_READ:
{
// Disable repeated FD_READ call while we process message
WSAAsyncSelect(wParam,hWnd,SOCKET_TCP, FD_WRITE | FD_ACCEPT | FD_CLOSE);
// first four bytes is packet size
// second four bytes are used to identify type of msg
char* psize = (char*)malloc(5);
char* ptype = (char*)malloc(5);
psize[4] = '\0';
ptype[4] = '\0';
recv(wParam,psize,4,0);
recv(wParam,ptype,4,0);
// allocate memory for the buffer
int size_to_recv = atoi(psize);
char* textbuff = (char*)malloc(size_to_recv);
// receive
int i = size_to_recv;
while (i > 0) {
int read = recv(wParam,textbuff,i,0);
i = i - read;
}
// handle msg depending on type
switch(identifyMsg(ptype)) {
case 1:
// handle 'text' msg
onReadText(hWnd,textbuff);
break;
case 2:
// handle 'name' msg
onReadName(hWnd,textbuff);
break;
case 3:
// handle 'list' msg
onReadList(hWnd,textbuff);
break;
case 4:
// handle 'remv' msg
onReadRemv(hWnd,textbuff,size_to_recv);
break;
case 5:
// handle 'ipad' msg -- add ip
voiceManager->addParticipant(inet_addr(textbuff));
break;
case 6:
// handle 'iprm' msg -- remove ip
voiceManager->removeParticipant(inet_addr(textbuff));
break;
default:
break;
}
// re-enable FD_READ
WSAAsyncSelect(wParam,hWnd,SOCKET_TCP, FD_WRITE | FD_ACCEPT | FD_READ | FD_CLOSE);
// free resources
free(psize);
free(ptype);
free(textbuff);
break;
}
case FD_WRITE:
break;
case FD_CONNECT:
break;
case FD_CLOSE:
onDisconnect(hWnd);
break;
default:
break;
}
break;
case WM_PAINT:
paintText(hWnd);
break;
case WM_DESTROY:
shutdownConnection(hWnd);
// reset window procs
SetWindowLong(GetDlgItem(hWnd,ID_EDIT_SEND), GWL_WNDPROC,(LONG) OriginalEditProc);
SetWindowLong(GetDlgItem(hWnd,ID_EDIT_IP), GWL_WNDPROC,(LONG) OriginalEditProc);
PostQuitMessage(0);
return 0;
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
default:
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK sendEditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
if (message == WM_CHAR) {
if (wParam == VK_RETURN) {
onSendText(GetParent(hWnd));
return 0;
}
}
if (message == WM_KEYUP || message == WM_KEYDOWN) {
if (wParam == VK_RETURN) {
return 0;
}
}
return CallWindowProc(OriginalEditProc, hWnd, message, wParam,lParam);
}
Where sendEditProc is a sub/superclass designed to intercept 'enter' keys when inside an edit control 'send'
Does this help?
Here's the message loop; it's the standard so nothing fancy that could go wrong afaik :)
while (GetMessage(&msg, NULL,0,0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
You're calling CallNextHookEx one too many times. If key < 0 return CallNextHookEx, otherwise return 0.
The problem you're seeing has to do with keyboard repeats and the MessageBox or MessageBeep methods being very, very expensive calls. Try this test:
HHOOK hHook;
BOOL bTalkEnabled = FALSE;
LRESULT CALLBACK pushtotalk(int key, WPARAM wParam, LPARAM lParam)
{
if (key < 0)
return CallNextHookEx(hHook, key, wParam, lParam);
KBDLLHOOKSTRUCT* kbdll = (KBDLLHOOKSTRUCT*)lParam;
if (kbdll->vkCode == VK_F11)
{
BOOL bStarted = FALSE;
BOOL bStopped = FALSE;
if (wParam == WM_KEYDOWN)
{
if (!bTalkEnabled)
{
bStarted = TRUE;
bTalkEnabled = TRUE;
}
}
else if (wParam == WM_KEYUP)
{
if (bTalkEnabled)
{
bStopped = TRUE;
bTalkEnabled = FALSE;
}
}
if (bStarted)
OutputDebugString(L"Pushed\r\n");
if (bStopped)
OutputDebugString(L"Released\r\n");
}
return 0;
}
You can monitor the debug strings by running the app under the debugger (check the Output window), or you can get DebugView and watch that.
Notice that I do not check for connected as you did. You don't want to perform that check in the hook, do that outside the hook and only use the hook to determain if the key is pressed or not pressed.