I am using a voice chat application that uses the push-to-talk key. I made a hook so that it will register an external push-to-talk 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 proc in an application), a process causes a system shutdown 5 seconds before continuing. Why?
2) The hook only works with the process that was started before the launch of my application, if I started the text program after the application started, the interceptors will not be registered. Is there a fix for this?
3) If I hold the key for ~ 3 seconds, many of the MessageBox messages show, obviously, but after that proc never registers the other key pressed, so I suppose I somehow disconnected from the hook chain?
Greetings
EDIT: here is 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 the 'enter' keys when inside the edit control 'send' Does this help?
Here's the message loop; this is the standard, so thereβs nothing fancy that can go wrong, afik :)
while (GetMessage(&msg, NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); }