Can't exit loops dynamically while using keyboard hook - c++

I'm having some issues about exiting "while" loops while using keyboard hook. Here is my code:
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT key = (PKBDLLHOOKSTRUCT)lParam;
if (wParam == WM_KEYDOWN && nCode == HC_ACTION)
{
}
if (wParam == WM_KEYUP)
{
if (key->vkCode == VK_CAPITAL) {
capslockState = GetKeyState(VK_CAPITAL) & 0x0001;
myLoop(capslockState);
}
}
return CallNextHookEx(keyboardHook, nCode, wParam, lParam);
}
And here is my function:
int myLoop(int a) {
while (a == 1) {
for (i = 0; i < n; i++) {
// do some stuff
}
if (a == 0) {
break;
return 0;
}
else {
i = 0;
}
}
}
I tried couple more ways to achieve my goal but I couldn't do it. My goal is: I want to open the program, doesn't matter if Caps Lock is on or off, if I hit Caps Lock, it'll start my loop and if I hit it again, it'll stop. I was, somehow, able to make it using lots of "while" loops and threads but it was using almost all my CPU power. How can I create a performance friendly, dynamic loop while using keyboard inputs?
Thank you.

My goal is: I want to open the program, doesn't matter if Caps Lock is
on or off, if I hit Caps Lock, it'll start my loop and if I hit it
again, it'll stop.
You can check the following code to see if it works.
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0) // do not process message
return CallNextHookEx(NULL, nCode,
wParam, lParam);
if (wParam == VK_CAPITAL) {
if(hThread == NULL)
hThread = CreateThread( NULL, 0, myLoop, NULL, 0, NULL);
if (capslockState)
capslockState = 0;
else
capslockState = 1;
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
DWORD WINAPI myLoop(LPVOID lpParam)
{
while (1) {
for (UINT16 i = 0; (i < n && capslockState == 1); i++) {
// do some stuff
}
Sleep(100);
}
return 0;
}
What I made main edits on your code:
To make main thread can response to messages and keep your for loop, you need create a new thread(CreateThread) for running your for loop.
Since you "doesn't matter if Caps Lock is on or off" so no need check if the capslock is on or off state.
To check the which key is hit use wParam to compare with virtual-key code.
Problems have pointed by others.
More reference "Using Hooks"

Related

expected a ";" on strange place

I have posted here entier code cuz myb I made bad struct or put some functions on wrong place . But It doesnt make sens for me why I am getting Error on LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) ,and it doesnt make sens to put ; after it. If someone have time to check code and give me advice how to fix this or realize this on easier way ,I will be very thankful.
error
int main()
{
int togler;
int g;
HHOOK MouseHook;
HHOOK hhkLowLevelKybd;
bool SupressMouseHook = false;
bool click = false;
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
BOOL eatMouseStroke2 = false;
if (!SupressMouseHook) {
BOOL eatMouseStroke = false;
if (togler == 1) {
if (wParam == WM_LBUTTONDOWN) {
click = true;
}
else if (wParam == WM_LBUTTONUP) {
click = false;
}
}
return(eatMouseStroke ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
else {
BOOL eatMouseStroke = false;
return(eatMouseStroke ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
return(eatMouseStroke2 ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, GetModuleHandle(NULL), 0);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)clicker, NULL, NULL, NULL);
}
You should move MouseHookProc definition outside of main. C++ does not allow function definitions inside of other functions.
Among other things, (LPTHREAD_START_ROUTINE)clicker is also wrong, there is no need to perform cast here, instead clicker function must have correct signature, void down(); is actually a function declaration, not invocation.

Control OS mouse clicks

I can't seem to find what I am looking for which is a way to alter the OS's mouse clicks. To specify this would be on Windows.
The goal is to limit the number of mouse clicks a user can register within a period of time.
I think the function that you are looking for is SetWindowsHookEx. Here is a quick example.
#include <windows.h>
const DWORD desireddelay = 10;
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
static DWORD previoustimestamp = 0;
if ((nCode == 0) && (wParam == WM_RBUTTONDOWN))
{
if ((((MSLLHOOKSTRUCT*)lParam)->time - previoustimestamp) < desireddelay)
{
return 1; //Non-Zero Swallows the keystroke. 0 Allows it. Always CallNextHookEx if you are not swallowing it.
}
else
{
previoustimestamp = ((MSLLHOOKSTRUCT*)lParam)->time;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int main()
{
HHOOK hook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), NULL);
MSG msg;
bool done = false;
while (GetMessage(&msg, NULL, NULL, NULL)) {}
UnhookWindowsHookEx(hook);
return 0;
}

Get Mouse Wheel movement data

I have wrote a window hook to retrieve the mouse events
_handle = SetWindowsHookEx(WH_MOUSE,
(HOOKPROC)KeyEvent,
nullptr,
GetCurrentThreadId());
static LRESULT WINAPI KeyEvent(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode >= 0)
{
MOUSEHOOKSTRUCT* mStruct = ( MOUSEHOOKSTRUCT*)lParam;
MSLLHOOKSTRUCT* mWheelDStruct = (MSLLHOOKSTRUCT*)lParam;
CMouseHookCom::_this->ReportEventW(mStruct->hwnd, wParam, mWheelDStruct);
}
return(CallNextHookEx(NULL, nCode, wParam, lParam));
}
case WM_MOUSEWHEEL:
OutputDebugString(L"CMouseHookCom-WM_MOUSEWHEEL");
strm = (MSLLHOOKSTRUCT*)extraData;
zDelta = (short)(HIWORD(((MSLLHOOKSTRUCT*)extraData)->mouseData));
_stprintf(buffer, L"CMouseHookCom - WM_MOUSEWHEEL delta %d %i", zDelta, short((strm->mouseData >> 16) & 0xffff));
OutputDebugString(buffer);
if (zDelta > 0)
{
OutputDebugString(L"CMouseHookCom-WM_MOUSEWHEEL UP");
Invoke_onScrollOut(componentId);
}
else
{
OutputDebugString(L"CMouseHookCom-WM_MOUSEWHEEL DOWN");
Invoke_onScrollIn(componentId);
}
break;
default:
_stprintf(buffer, L"CMouseHookCom - UnHandleled event %d", event);
OutputDebugString(buffer);
break;
}
no matter how I try I always get positive results of the wheel. Also I always get different value. What is the correct way to retrieve the data?
You should use Raw Input instead of a mouse hook. That is less overhead on the OS to monitor the mouse, and it gives you information that a hook would not.

GET_WHEEL_DELTA_WPARAM(wParam) in mouse hook returning 0

MSG msg;
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= 0) {
if (wParam == WM_MOUSEWHEEL) cout << GET_WHEEL_DELTA_WPARAM(wParam) << endl; //prints 0
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
bool get_state(){
if(GetMessage(&msg,GetActiveWindow(), 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
int main()
{
HHOOK mousehook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, NULL, 0);
while(true){
get_state();
}
UnhookWindowsHookEx(mousehook);
return 0;
}
I found a mouse hook in this thread, which works, but when I attempt to check the state of the mouse wheel (whether it is moving forwards or backwards), the function to get the movement always returns 0.
Am I calling the GET_WHEEL_DELTA_WPARAM(wParam) wrong? Or is the way I am using the hook not compatible with the GET_WHEEL_DELTA_WPARAM(wParam) function?
Another thread I found has code to get the mouseData (which may allow me to get the movement value I'm looking for) from a struct named MOUSEHOOKSTRUCTEX, but when I try to compile, I get the error "'MOUSEHOOKSTRUCTEX' was not declared in this scope".
Note that this code is stripped down to isolate the issue, so please forgive odd pieces such as the while loop running unhindered.
The fix is to get the movement using:
MSLLHOOKSTRUCT *pMhs = (MSLLHOOKSTRUCT *)lParam;
short zDelta = HIWORD(pMhs->mouseData);
In the MouseHookProc function.
Answer given by user chris

Trying to hook Notepad.exe

I'm trying to keyboard-hook Notepad.exe by using SetWindowsHookEx.
As you see, the working thread is sending its ASCII code, which is wParam, to the designated server.
UINT WINAPI SendToServer(LPVOID lpParam)
{
CSocket Client;
Client.Create();
Client.Connect("localhost", 6677);
Client.Send(lpParam, 2); // sending its ASICI code to Server
Client.Close();
return 0;
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
TCHAR szPath[MAX_PATH] = {0,};
TCHAR* p = nullptr;
if( nCode >= 0 )
{
// bit 31 : 0 => press, 1 => release
if( !(lParam & 0x80000000) )
{
GetModuleFileName(NULL, szPath, MAX_PATH);
p = strrchr(szPath, '\\');
if( !_stricmp(p + 1, "Notepad.exe") )
{
unsigned ThreadID;
g_hThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, SendToServer, &wParam, 0, &ThreadID)); // a new working thread
return 0;
}
}
}
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
The problem is, for some reason related to the new working thread, Notepad occurs a critical error(if I click the 'ignore' button several times, it kinda works though.)
I deleted this line below,
g_hThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, SendToServer, &wParam, 0, &ThreadID)); // a new working thread
Then no error occurs from Notepad.exe
Any help would be very appreciated.
Thanks in advance.
Will this work for you..? Hard coded paths are used only for test purposes
change the path to match where your NotePad.exe resides
LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
ofstream fout;
fout.open("c:\\NotePad.exe",ios::app);
if (nCode < 0 || nCode != HC_ACTION)
return CallNextHookEx(hkb, nCode, wParam, lParam);
if ( (((DWORD)lParam & 0x80000000) == 0) && (HC_ACTION == nCode))
{
if ((wParam==VK_SPACE)||(wParam==VK_RETURN)||((wParam>=0x2f ) &&(wParam<=0x100)))
{
if(GetAsyncKeyState(wParam) == -32767) //this solve it i got it on google but how ??
{
BYTE ks[256];
GetKeyboardState(ks);
WORD w;
UINT scan=0;
ToAscii(wParam,scan,ks,&w,0);
fout<<char(w);
}
}
}
fout.close();
return CallNextHookEx(hkb, nCode, wParam, lParam);
}