Reputation:
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);
}
Upvotes: 1
Views: 1067
Reputation: 13644
I didn't run your code, so I'm not sure, but I have an idea.
printf_s
does console output. Clicking on your console window does this fancy stuff with selecting/copying your output and blocks functions like printf_s
, to avoid selection from running away. As your hooking function is blocked, mouse is blocked. Later on Windows may be able to remove your hook for this behavior of running hook procedure for too long.
Log to a file instead, or post your log to a queue and print from that queue.
Upvotes: 0