I have a procedure that when a user press Ctrl button and right click it will show a message box to screen. But it has a loop, I only press Ctrl button and right click once time but it shows a sequence of message box. How to fix this?
https://youtu.be/LzI9M_zEEKQ
This is my MouseProc procedure
#define EXPORT __declspec(dllexport)
unsigned char KeyState[256];
LRESULT EXPORT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0)
return CallNextHookEx(hHook, nCode, wParam, lParam);
GetKeyboardState(KeyState);
if (nCode == HC_ACTION)
{
if ((wParam == WM_RBUTTONUP) && (KeyState[VK_CONTROL] & 0x80))
{
MessageBox(NULL, L"Ctrl + Right Click", L"Mouse hook", MB_OK);
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
Thanks for reading.
You shall not use MessageBox() in message hooks as it breaks normal message hook flow - MessageBox() runs its own modal loop.
If you need exactly MessageBox there then you should use PostMessage with custom message and handler. In this case MessageBox will be invoked after CallNextHookEx(hHook, nCode, wParam, lParam);
Related
I want to learn something about Windows Hooks. Right now, I'm only interested in "catching" messages.
So I did the following, but it doesn't work.
I want to catch the message in the same thread I'm using. I don't want to catch another thread's messages.
Can somebody explain to me what I'm doing wrong?
I install the hook as follows:
myhookdata.nType = WH_GETMESSAGE;
myhookdata.hkprc = GetMsgProc;
myhookdata.hhook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
Then in the hook procedure I do this, just for testing. But the "WM_LBUTTONDOWN" never get catched!!
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
LPCWPSTRUCT message = (LPCWPSTRUCT)lParam;
if (nCode < 0)
return CallNextHookEx(myhookdata.hhook, nCode,
wParam, lParam);
switch (nCode)
{
case HC_ACTION:
if (wParam)
if (message->message == WM_LBUTTONDOWN)
Sleep(0);
break;
default:
break;
}
return CallNextHookEx(myhookdata.hhook, nCode, wParam, lParam);
}
According to the documentation:
lParam [in]
Type: LPARAM
A pointer to an MSG structure that contains details about the message.
So you only need to change the code:
PMSG message = (PMSG)lParam;
Then it works for me.
I have written an application to hook some procedure onto a new process to monitor mouse down events and to disable mouse down events on the new process. As of now, I am able to capture to mouse down events coming to this process and I am trying to disable all mouse down events as a POC. This is what I am doing currently in the hook procedure.
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
return false;
}
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
When I perform mouse down event, I am getting the log message that I have written. But I also expect that click event to be blocked since I am returning false. but it does not happen so and click event proceed as a normal click. How could I disable mouse down event. Thanks in advance for any help on this
This is how I call setWindowsHookEx
HHOOK handle = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, threadID);
The reason you are supposed to call CallNextHookEx during your hook routine is so that the message can be passed on to any other hooks that might be installed. Failing to do so does not prevent the message from being seen by the application that received it.
The documentation for WM_NULL explains how to block the message:
For example, if an application has installed a WH_GETMESSAGE hook and wants to prevent a message from being processed, the GetMsgProc callback function can change the message number to WM_NULL so the recipient will ignore it.
The corrected code should therefore look something like this:
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
msg->message = WM_NULL;
return false;
}
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
However, this may cause inconsistent behaviour if other hooks are present, because whether another hook sees WM_LBUTTONDOWN or WM_NULL will depend on the order of the hook chain, which is unpredictable. It might be preferable to try something like this:
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
int result = CallNextHookEx(NULL, code, wParam, lParam);
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
msg->message = WM_NULL;
}
return result;
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
I'm using C++ and DirectD3D9 to draw a menu.
I wish to navigate the menu with the mouse.
I can get the mouse position, however, checking if the left button is clicked is proving tricky.
I am able to check if it is being held down, but not clicked.
bool LBUTTONDOWN = false;
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode == HC_ACTION && (wParam == WM_LBUTTONUP || wParam == WM_LBUTTONDOWN)) {
LBUTTONDOWN = wParam == WM_LBUTTONDOWN;
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
How can I add a check to see if I clicked the left button?
You need to use a timing trick. Create a variable named something like 'nTime',
Set the zero for it when the LButton is up. Increase the variable value using a '+=' operator when the LButton is down and check the variable against a value something like that -
bool LBUTTONDOWN = false;
int nTime = 0;
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION && (wParam == WM_LBUTTONUP || wParam == WM_LBUTTONDOWN))
{
LBUTTONDOWN = wParam == WM_LBUTTONDOWN;
if ( LBUTTONDOWN )
{
nTime += 1;
if ( nTime > 1000 /*( this value depends on you )*/ )
{
nTime = 0;
// Here is your hold event code.
}
}
else
nTime = 0;
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
There is no DoubleClick message for LowLevelMouseProc. However, I suppose you can have a work around:
Record the time interval between LBUTTONDOWN and LBUTTONUP, then to check whether it is quick enough to be a click event. And because the mouse acts very fast, it is better to set a timer for the mouse capturing.
For the mouse capturing, you can still call LowLevelMouseProc. However, the DirectInput is more convenient for processing mouse movements.
In DirectX SDK samples, there is a DirectInput sample named "CustomFormat". It shows how to set up a timer to capture mouse input.
I hope this helps.
I have been having trouble with my program trying to gray out ( and disable ) a sub menu item.
What I'm looking for is that the "run" item be disabled unless the required .ini entry is not empty.
My code
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HMENU hmenu = GetMenu(hWnd);
// Reading in ini
if (0 == strcmp(webLocation, "")){
EnableMenuItem(hmenu,ID_WEBSERVICES_RUN,MF_DISABLED | MF_GRAYED);
WritePrivateProfileString(_T("WEBSERVICES"), _T("Location"), _T("Tool Not Found"), WpathStr);
}
I am unsure as to whether I am getting the HMENU correctly and why this code is not working for the desired effect.
Any help with this would be greatly appreciated.
You can't just put this in the WndProc at the top level. WndProc process events, whether the window has been constructed or not. It'll be called many times for many different reasons.
Your WndProc will almost certainly look like a big switch on message. The one you want here is WM_INITDIALOG:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
// jump to a new function that reads the .ini
// and disables the control etc.
return OnInitDialog(hWnd, wParam, lParam);
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
I'm trying to send a duplicate message to an editbox window in this code:
extern "C" HOOK_DLL_API LRESULT CALLBACK GetMsgHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0)
{
CallNextHookEx(gMsgHook, nCode, wParam, lParam);
}
KBDLLHOOKSTRUCT *lpk = (KBDLLHOOKSTRUCT*) lParam;
ghServerWnd; // ghServerWnd == Edit1. that defined..
if (wParam == WM_KEYDOWN)
{
// case1: this code working.. but, unicode(IME character) no sent;;
SendMessageW(ghServerWnd, WM_CHAR, (WPARAM)lpk->vkCode, 0);
// case2: this code - not working.. T_T
SendMessageW(ghServerWnd, wParam, lParam, 0);
}
return CallNextHookEx(gMsgHook, nCode, wParam, lParam);
}
I need help with "case2" as marked in the code.
Thanks for reading.
Well i'm not surprised case 2 does not work. You are sending KBDLLHOOKSTRUCT as the wParam.
I would have thought.
SendMessage( ghServerWnd, wParam, (WPARAM)lpk->vkCode, (LPARAM)lpk->scanCode );
Would work better (Though I'm not 100% convinced my LPARAM is complete).