Get Mouse Wheel movement data - c++

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.

Related

Sensitivity drops when using SetWindowsHookEx

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);

Can't exit loops dynamically while using keyboard hook

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"

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;
}

Monitoring clipboard

I am writting dll with global hooks. One of the task is viewing clipboard and deleting all data from it when someone perform copy operation. Here is my callback function for window:
string test("my data");
LRESULT CALLBACK WndHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_CREATE:
nextClipboardViewer = SetClipboardViewer(windowHandler);
MessageBeep(MB_ICONINFORMATION);
break;
case WM_CHANGECBCHAIN:
if((HWND) wParam == nextClipboardViewer)
nextClipboardViewer == (HWND) lParam;
else if(nextClipboardViewer != NULL)
SendMessage(nextClipboardViewer, msg, wParam, lParam);
break;
case WM_DRAWCLIPBOARD:
if(OpenClipboard(windowHandler)) {
EmptyClipboard();
HGLOBAL hClipboardData;
hClipboardData = GlobalAlloc(GMEM_MOVEABLE, test.size() + 1);
char * pchData;
pchData = (char*)GlobalLock(hClipboardData);
memcpy(pchData, test.c_str(), test.size() + 1);
GlobalUnlock(hClipboardData);
SetClipboardData(CF_TEXT, hClipboardData);
CloseClipboard();
}
SendMessage(nextClipboardViewer, msg, wParam, lParam);
break;
case WM_DESTROY:
ChangeClipboardChain(windowHandler, nextClipboardViewer);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
break;
}
return 0;
}
I am just trying replace information in clipboard, but this code doesn't work.
Updated: Now i am using invisible window and SetClipboardViewer for monitoring changes. But data in clipboard doesn't change.
I doubt it's really safe to change the contents of the clipboard while processing a WM_DRAWCLIPBOARD message - at the very least I'm surprised you don't trigger an infinite loop (since your calls to EmptyClipboard() and SetClipboardData() could be triggering another WM_DRAWCLIPBOARD message). Possibly the system has protection against that - I've never tried to find out - but it still feels wrong :)
Try this version, which:
Moves the clipboard update to a separate message that the window posts to itself (moving it outside of the clipboard change the notification code)
Uses a global flag to ignore changes it makes itself.
Note: I think the actual bug with your code was that when you're processing WM_CREATE, windowHandler is not yet assigned. You are presumably setting that to the value CreateWindowEx returns, but when WM_CREATE is being processed CreateWindowEx hasn't actually returned yet. This means the clipboard viewer is never actually established correctly. I've changed the references to use hwnd to fix this.
string test("my data");
#define MSG_UPDATECLIPBOARD (WM_APP + 1)
static bool g_fIgnoreClipboardChange = false;
LRESULT CALLBACK WndHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_CREATE:
nextClipboardViewer = SetClipboardViewer(hwnd);
MessageBeep(MB_ICONINFORMATION);
break;
case WM_CHANGECBCHAIN:
if((HWND) wParam == nextClipboardViewer)
nextClipboardViewer = (HWND) lParam;
else if(nextClipboardViewer != NULL)
SendMessage(nextClipboardViewer, msg, wParam, lParam);
break;
case WM_DRAWCLIPBOARD:
if (!g_fIgnoreClipboardChange)
PostMessage(hwnd, MSG_UPDATECLIPBOARD, 0, 0);
if(nextClipboardViewer != NULL)
SendMessage(nextClipboardViewer, msg, wParam, lParam);
break;
case MSG_UPDATECLIPBOARD:
g_fIgnoreClipboardChange = true;
if(OpenClipboard(hwnd)) {
HGLOBAL hClipboardData;
hClipboardData = GlobalAlloc(GMEM_MOVEABLE, test.size() + 1);
char * pchData;
pchData = (char*)GlobalLock(hClipboardData);
memcpy(pchData, test.c_str(), test.size() + 1);
GlobalUnlock(hClipboardData);
SetClipboardData(CF_TEXT, hClipboardData);
CloseClipboard();
}
g_fIgnoreClipboardChange = false;
break;
case WM_DESTROY:
ChangeClipboardChain(hwnd, nextClipboardViewer);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
break;
}
return 0;
}

Hotkey with LowLevel Keyboard Hook

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.