This is another question I have related to setWindowsHookEx
, I have written small Application to hook dll
into windows calculator applicatio
. Basically, exe
application inject the dll
into calculator
and it monitors all the mouse down events happening at the calculator application. And currently , I am able to disable all the mouse down events happening at the calculator. however, I want to get it done based on the location the mouse is pointing. Specifically, when the mouse button is clicking on specific menu bar item. I tried to get this done by using GetWindowText to retrieve the text where button is pointing, but most of the time it return the window text instead of the window item ( menu item
) it is pointing. Following is the code that I have written for this. Any idea on how to disable a particular window element on menu bar.
EXE code which call SetWindowsHookEx
// program.exe.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
#include <string>
#include <io.h>
using namespace std;
void Usage()
{
printf("Usage: InjectDLL pid path-to-dll [-privilege]");
}
int _tmain(int argc, char* argv[])
{
/*
* Load library in which we'll be hooking our functions.
*/
HMODULE dll = LoadLibrary(L"C:\\drivers\\dllinject.dll");
if (dll == NULL) {
printf("The DLL could not be found.\n");
getchar();
return -1;
}
/*
* Get the address of the function inside the DLL.
* _hookmethod@12 is used to hook into 32bit applications
*/
//HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, "_hookmethod@12");
HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, "hookmethod");
if (addr == NULL) {
printf("The function was not found.\n");
getchar();
return -1;
}
/*
* Hook the function.
*/
DWORD procID=0;
HWND targetWnd = FindWindowA("CalcFrame", "Calculator");
wchar_t msgBuf[1024] = L"";
wchar_t msgBuf2[1024] = L"";
wsprintf(msgBuf, L"the thread Id is : %d , process id is : %d ", threadID, procID);
OutputDebugString(msgBuf);
//
//WH_KEYBOARD_LL
HHOOK handle = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, threadID);
//HHOOK handle = SetWindowsHookEx(WH_CALLWNDPROC, addr, dll, threadID);
//HHOOK handle = SetWindowsHookEx(WH_MSGFILTER, addr, dll, threadID);
DWORD x = GetLastError();
wsprintf(msgBuf2, L"the last error is %d", x);
OutputDebugString(msgBuf2);
if (handle == NULL) {
printf("The KEYBOARD could not be hooked.\n");
}
else{
printf("Program successfully hooked.\nPress enter to unhook the function and stop the program.\n");
}
/*
* Unhook the function.
*/
getchar();
UnhookWindowsHookEx(handle);
return 0;
}
dll which is used to block the clicking of menu bar item.
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
static HWND s_hWndButton;
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
switch (Reason) {
case DLL_PROCESS_ATTACH:
OutputDebugString(L"DLL attach function called11.\n");
break;
case DLL_PROCESS_DETACH:
OutputDebugString(L"DLL detach function called.\n");
break;
case DLL_THREAD_ATTACH:
OutputDebugString(L"DLL thread attach function called.\n");
break;
case DLL_THREAD_DETACH:
OutputDebugString(L"DLL thread detach function called.\n");
break;
}
return TRUE;
}
extern "C" __declspec(dllexport) LRESULT __stdcall hookmethod(int code, WPARAM wParam, LPARAM lParam) {
TCHAR msgBuftext[65536];
TCHAR msgBufhandle[65536];
TCHAR msgBufhandletext[65536];
TCHAR msgBufwintext[2048];
if (code >= 0) {
MSG* cp = (MSG*)lParam;
int txtlen = GetWindowTextLengthW(cp->hwnd);
GetWindowText(cp->hwnd, msgBufhandletext, txtlen);
wsprintf(msgBufhandle, L"Handle %X", cp->hwnd);
wsprintf(msgBufwintext, L"Window Text %s", msgBufhandletext);
LPMSG msg = (LPMSG)lParam;
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(msgBufwintext);
msg->message = WM_NULL;
}
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
For those who are interested, I would like to post the answer that I was able to implement. Basically , instead of listening to WH_GETMESSAGE
, I changed the hook chain to WH_MSGFILTER
. Reason because, it allows me to find the menu item id when I move the mouse over menu item and when the button up event happens, I can check the menu item id and disable mouse click by changing the message to WM_NULL. following is the working code sample. It also enable u to block the event if user is navigat
dll code
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <Winuser.h>
#include <Lmcons.h>
#include "nxlrunner.h"
WORD wMenuItemID;
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
switch (Reason) {
case DLL_PROCESS_ATTACH:
OutputDebugString(L"DLL attach function called11.\n");
break;
case DLL_PROCESS_DETACH:
OutputDebugString(L"DLL detach function called.\n");
break;
case DLL_THREAD_ATTACH:
OutputDebugString(L"DLL thread attach function called.\n");
break;
case DLL_THREAD_DETACH:
OutputDebugString(L"DLL thread detach function called.\n");
break;
}
return TRUE;
}
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
switch (code)
{
case MSGF_MENU: // message is for a menu
{
MSG* pMSG = (MSG*)lParam;
switch (pMSG->message)
{
case WM_MENUSELECT:
{
wMenuItemID = LOWORD(pMSG->wParam);
break;
}
case WM_LBUTTONDOWN:
{
break;
}
case WM_LBUTTONUP:
{
if (wMenuItemID == 10353){
wchar_t usernamew[UNLEN];
DWORD username_len = UNLEN + 1;
GetUserNameW(usernamew, &username_len);
MessageBoxW(NULL, usernamew, L"Title", MB_OK);
pMSG->message = WM_NULL;
}
break;
}
case WM_LBUTTONDBLCLK:
{
if (wMenuItemID == 10353){
pMSG->message = WM_NULL;
}
break;
}
case WM_KEYDOWN:
{
switch (pMSG->wParam)
{
case VK_RETURN:
{
if (wMenuItemID == 10353){
MessageBoxW(NULL, L"Message to user", L"Title.", MB_OK);
pMSG->message = WM_NULL;
}
break;
}
}
break;
}
case WM_KEYUP:
{
switch (pMSG->wParam)
{
case VK_RETURN:
{
if (wMenuItemID == 10353){
MessageBoxW(NULL, L"Message to user", L"Title", MB_OK);
pMSG->message = WM_NULL;
}
break;
}
}
break;
}
}
break;
}
}
return false;
}