I have a problem when I try hooking mouse events. It works if I click outside of my application window. But when I click inside my app window, it doesn't detect the WM_LBUTTONUP event. For few seconds mouse movement is very slow. And from this time it doesn't detect any events. Even if I click outside of my app window.
So my app runs indefinitely. I wonder if this is something related to threads or something. Maybe if I want to track something globally, in all threads in my computer (for example tracking mouse movement) then I can do nothing in my app thread? But this is very strange to me.
Here is code for mouse hooking. main.cpp
#include <windows.h>
#include <iostream>
#include "MyHook.h"
using namespace std;
int main()
{
MyHook::Instance().InstallHook();
return MyHook::Instance().Messsages();
}
MyHook.h
#pragma once
#include <Windows.h>
class MyHook
{
public:
//single ton
static MyHook& Instance()
{
static MyHook myHook;
return myHook;
}
// function to install our mouseHook
void InstallHook();
// function to uninstall our mouseHook
void UninstallHook();
// function to "deal" with our messages
int Messsages();
public:
HHOOK mouseHook; // handle to the mouse hook
HHOOK windowHook; // handle to the window hook
MSG msg; // struct with information about all messages in our queue
};
LRESULT CALLBACK MyMouseCallback(int nCode, WPARAM wParam, LPARAM lParam);
MyHook.cpp
#include "MyHook.h"
#include <stdio.h>
void MyHook::InstallHook()
{
/*
SetWindowHookEx(
WM_MOUSE_LL = mouse low level mouseHook type,
MyMouseCallback = our callback function that will deal with system messages about mouse
NULL, 0);
c++ note: we can check the return SetWindowsHookEx like this because:
If it return NULL, a NULL value is 0 and 0 is false.
*/
if (!(mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MyMouseCallback, NULL, 0)))
{
printf_s("Error: %x \n", GetLastError());
}
}
// function to uninstall our mouseHook
void MyHook::UninstallHook()
{
UnhookWindowsHookEx(mouseHook);
}
MSG msg; // struct with information about all messages in our queue
// function to "deal" with our messages
int MyHook::Messsages()
{
// while we do not close our application
while (msg.message != WM_QUIT)
{
if (GetMessage(&msg, NULL, 0, 0/*, PM_REMOVE*/))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(1);
}
UninstallHook(); // if we close, let's uninstall our mouseHook
return (int)msg.wParam; // return the messages
}
LRESULT CALLBACK MyMouseCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
MSLLHOOKSTRUCT* pMouseStruct = (MSLLHOOKSTRUCT*)lParam; // WH_MOUSE_LL struct
/*
nCode, this parameters will determine how to process a message
This callback in this case only have information when it is 0 (HC_ACTION): wParam and lParam contain info
wParam is about WINDOWS MESSAGE, in this case MOUSE messages.
lParam is information contained in the structure MSLLHOOKSTRUCT
*/
// we have information in wParam/lParam ? If yes, let's check it:
if (nCode == 0)
{
// Mouse struct contain information?
// if (pMouseStruct != NULL)
// {
// printf_s("Mouse Coordinates: x = %i | y = %i \n", pMouseStruct->pt.x, pMouseStruct->pt.y);
// }
switch (wParam)
{
case WM_LBUTTONDOWN:
{
printf_s("LEFT CLICK DOWN\n");
}
break;
case WM_LBUTTONUP:
{
printf_s("LEFT CLICK UP\n");
}
break;
}
}
/*
Every time that the nCode is less than 0 we need to CallNextHookEx:
-> Pass to the next mouseHook
MSDN: Calling CallNextHookEx is optional, but it is highly recommended;
otherwise, other applications that have installed hooks will not receive mouseHook notifications and may behave incorrectly as a result.
*/
return CallNextHookEx(MyHook::Instance().mouseHook, nCode, wParam, lParam);
}