I am trying to make a source code to work
extern "C" {
typedef LRESULT (__stdcall *NRI_PM_CALLBACK)(WPARAM, LPARAM);
}
LRESULT OnPaymentManagerMessage(WPARAM wParam, LPARAM lParam)
{
int type = (wParam >> 4) & 0x0F;
int device = wParam & 0x0F;
//cstr.Format("** Msg **[ %d %d %d ]", type, device, lParam);
//handle message here
return lParam;
}
NRI_PM_CALLBACK callback = &OnPaymentManagerMessage; //error on this line
Error:a value of type "LRESULT (*)(WPARAM wParam, LPARAM lParam)" cannot be used to initialized an entity of type "NRI_PM_CALLBACK"
I am running this in Visual Studio Express 2012
Any ideas why ?
Thanks
Make OnPaymentManagerMessage() a __stdcall function:
LRESULT __stdcall OnPaymentManagerMessage(WPARAM wParam, LPARAM lParam)
/* ... */
__cdecl is the default for the compiler (though a compiler option can change that).
Related
I'm currently hooking window activations with the following code:
extern "C" __declspec(dllexport) LRESULT CALLBACK CBTProc(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
if (nCode < 0) return CallNextHookEx(nullptr, nCode, wParam, lParam);
HWND hwnd = reinterpret_cast<HWND>(wParam);
switch (nCode)
{
case HCBT_ACTIVATE: // The system is about to activate a window.
{
return 0; // 0 - Allow 1 - Deny
}
}
return 0;
From the docs:
https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644977(v=vs.85)
lParam
Specifies a long pointer to a CBTACTIVATESTRUCT structure containing the handle to the active window and specifies whether the activation is changing because of a mouse click.
How I could interpret the value of lParam and distinguish it?
As the documentation says, for HCBT_ACTIVATE the lParam specifies a pointer to a CBTACTIVATESTRUCT, so simply typecast it accordingly, just like you are doing with the wParam, eg:
extern "C" __declspec(dllexport) LRESULT CALLBACK CBTProc(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
if (nCode < 0) return CallNextHookEx(nullptr, nCode, wParam, lParam);
switch (nCode)
{
case HCBT_ACTIVATE: // The system is about to activate a window.
{
HWND hwnd = reinterpret_cast<HWND>(wParam);
CBTACTIVATESTRUCT* cbt = reinterpret_cast<CBTACTIVATESTRUCT*>(lParam);
// use hwnd, cbt->fMouse, and cbt->hWndActive as needed...
return 0; // 0 - Allow 1 - Deny
}
}
return 0;
}
I'm trying to write a dll to intercept a window from being resized, but i cant understand how to correctly specify the lParam in this case.
From the docs:
HCBT_MOVESIZE: Specifies a long pointer to a RECT structure containing
the coordinates of the window. By changing the values in the
structure, a CBTProc hook procedure can set the final coordinates of
the window.
Current code:
#include "pch.h"
#include <Windows.h>
extern "C" __declspec(dllexport) LRESULT CALLBACK CBTProc(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
if (nCode < 0) return CallNextHookEx(nullptr, nCode, wParam, lParam);
switch(nCode)
{
case HCBT_MOVESIZE: // A window is about to be moved or sized.
/*
For operations corresponding to the following CBT hook codes, the return value must be 0 to allow the operation, or 1 to prevent it.
HCBT_ACTIVATE
HCBT_CREATEWND
HCBT_DESTROYWND
HCBT_MINMAX
HCBT_MOVESIZE
HCBT_SETFOCUS
HCBT_SYSCOMMAND
*/
/*
switch(LOWORD(lParam)) //
{
case EVENT_SYSTEM_MOVESIZESTART:
return 1; // Prevent
}
*/
}
return 0;
}
In the case of HCBT_MOVESIZE, the lParam contains the memory address of a RECT, so simply typecast the lParam to a RECT* pointer, eg:
extern "C" __declspec(dllexport) LRESULT CALLBACK CBTProc(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
if (nCode < 0) return CallNextHookEx(nullptr, nCode, wParam, lParam);
switch(nCode)
{
case HCBT_MOVESIZE: // A window is about to be moved or sized.
{
HWND hwnd = reinterpret_cast<HWND>(wParam);
RECT *rc = reinterpret_cast<RECT*>(lParam);
// use hwnd and *rc as needed...
if (should not resize)
return 1;
break;
}
...
}
return 0;
}
LPARAM is a pointer-sized value. It can hold any value that fits into a pointer. The meaning of the value commonly depends on context.
When handling a HCBT_MOVESIZE callback it designates
a long pointer to a RECT structure
To use it, client code needs to convert the value into a value of the respective type. In C++ this is done using a cast, e.g.
switch(nCode)
{
case HCBT_MOVESIZE: {
auto pRect{ reinterpret_cast<RECT*>(lParam) };
// Use `pRect` to read from or write to the rectangle
}
break;
// ...
}
I am attempting to add a low level mouse hook to a class. I am able to do so by placing this function in my CPP file:
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//my hook code here
return CallNextHookEx(0, nCode, wParam, lParam);
}
Then, I set up the hook in the class constructor like so:
HHOOK mousehook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, NULL, 0);
This works fine for intercepting mouse events, however since the callback function is not defined in my class, it does not have access to any of my class variables.
Therefore, I tried defining the callback function in my header file like so:
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam);
and in my CPP file like this (TMainForm being the class):
LRESULT CALLBACK TMainForm::MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//my hook code here
return CallNextHookEx(0, nCode, wParam, lParam);
}
However, when I attempt to compile like this, I get the following errors:
[bcc32 Error] MainFormU.cpp(67): E2034 Cannot convert 'long (__stdcall * (_closure )(int,unsigned int,long))(int,unsigned int,long)' to 'long (__stdcall *)(int,unsigned int,long)'
[bcc32 Error] MainFormU.cpp(67): E2342 Type mismatch in parameter 'lpfn' (wanted 'long (__stdcall *)(int,unsigned int,long)', got 'void')
What exactly am I doing wrong here? How is the method now different since I have made it a part of my TMainForm class?
You cannot use a non-static class methods as the callback. Non-static methods have a hidden this parameter, thus the signature of the callback does not match the signature that SetWindowsHookEx() is expecting. Even if the compiler allowed it (which can only be done with casting), the API would not be able to account for the this parameter anyway.
If you want to make the callback be a member of the class (so it can access private fields and such), it has to be declared as static to remove the this parameter, but then you will have to use the form's global pointer to reach it when needed, eg:
class TMainForm : public TForm
{
private:
HHOOK hMouseHook;
static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam);
void MouseHook(int nCode, WPARAM wParam, LPARAM lParam);
public:
__fastcall TMainForm(TComponent *Owner);
__fastcall ~TMainForm();
};
extern TMainForm *MainForm;
__fastcall TMainForm::TMainForm(TComponent *Owner)
: TForm(Owner)
{
hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, &MouseHookProc, NULL, 0);
}
__fastcall TMainForm::~TMainForm()
{
if (hMouseHook)
UnhookWindowsHookEx(hMouseHook);
}
LRESULT CALLBACK TMainForm::MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
MainForm->MouseHook(nCode, wParam, lParam);
return CallNextHookEx(0, nCode, wParam, lParam);
}
void TMainForm::MouseHook(int nCode, WPARAM wParam, LPARAM lParam)
{
// my hook code here
}
With that said, you should consider using the Raw Input API instead of SetWindowsHookEx(). The LowLevelMouseProc documentation even says so:
Note Debug hooks cannot track this type of low level mouse hooks. If the application must use low level hooks, it should run the hooks on a dedicated thread that passes the work off to a worker thread and then immediately returns. In most cases where the application needs to use low level hooks, it should monitor raw input instead. This is because raw input can asynchronously monitor mouse and keyboard messages that are targeted for other threads more effectively than low level hooks can. For more information on raw input, see Raw Input.
Using Raw Input, the mouse will send WM_INPUT messages directly to your window.
If you are using VCL, you can override the virtual WndProc() method to handle the WM_INPUT message, no static method needed:
class TMainForm : public TForm
{
protected:
virtual void __fastcall CreateWnd();
virtual void __fastcall WndProc(TMessage &Message);
};
void __fastcall TMainForm::CreateWnd()
{
TForm::CreateWnd();
RAWINPUTDEVICE Device = {0};
Device.usUsagePage = 0x01;
Device.usUsage = 0x02;
Device.dwFlags = RIDEV_INPUTSINK;
Device.hwndTarget = this->Handle;
RegisterRawInputDevices(&Device, 1, sizeof(RAWINPUTDEVICE));
}
void __fastcall TMainForm::WndProc(TMessage &Message)
{
if (Message.Msg == WM_INPUT)
{
HRAWINPUT hRawInput = (HRAWINPUT) Message.LParam;
UINT size = 0;
if (GetRawInputData(hRawInput, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)) == 0)
{
LPBYTE buf = new BYTE[size];
if (GetRawInputData(hRawInput, RID_INPUT, buf, &size, sizeof(RAWINPUTHEADER)) != 0)
{
RAWINPUT *input = (RAWINPUT*) buf;
// use input->data.mouse or input->data.hid as needed...
}
delete[] buf;
}
}
TForm::WndProc(Message);
}
If you are using FireMonkey, there is no WndProc() method for handling window messages (FireMonkey does not dispatch window messages to user code at all). However, you can subclass the window that FireMonkey creates internally so you can still receive the WM_INPUT message. A static method is needed, but you do not have to rely on a global pointer, the Form object can be passed as a parameter of the subclassing:
class TMainForm : public TForm
{
private:
static LRESULT CALLBACK SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
protected:
virtual void __fastcall CreateHandle();
};
void __fastcall TMainForm::CreateHandle()
{
TForm::CreateHandle();
HWND hWnd = Platform::Win::WindowHandleToPlatform(this->Handle)->Wnd;
SetWindowSubclass(hWnd, &SubclassProc, 1, (DWORD_PTR)this);
RAWINPUTDEVICE Device = {0};
Device.usUsagePage = 0x01;
Device.usUsage = 0x02;
Device.dwFlags = RIDEV_INPUTSINK;
Device.hwndTarget = hWnd;
RegisterRawInputDevices(&Device, 1, sizeof(RAWINPUTDEVICE));
}
LRESULT CALLBACK TMainForm::SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
TMainForm *pThis = (TMainForm*) dwRefData;
switch (uMsg)
{
case WM_INPUT:
{
// ...
break;
}
case WM_NCDESTROY:
{
RemoveWindowSubclass(hWnd, &SubclassProc, uIdSubclass);
break;
}
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
I came across the same issue and I found that the best method, for my particular case, was to create a static array of pointers to my class. Then inside the static hook method, I just iterate through my class pointers and call their hook functions.
kb_hook.h
typedef KBDLLHOOKSTRUCT khookstruct;
typedef LRESULT lresult;
typedef void (*h_func)(uint64_t key_message, khookstruct* kbdhook);
typedef std::vector<kb_hook*> h_array;
class kb_hook
{
public:
kb_hook();
virtual ~kb_hook();
h_func hook_func;
private:
static h_array hook_array;
static lresult static_hook(int code, uint64_t key_message, khookstruct* kbdhook);
};
kb_hook.cpp
kb_hook::kb_hook() : hook_func(NULL)
{
this->hook_array.push_back(this);
}
lresult kb_hook::static_hook(int code, uint64_t key_message, khookstruct* kbdhook)
{
if(code == HC_ACTION)
{
for(auto it=kb_hook::hook_array.begin();it!=kb_hook::hook_array.end();it++)
{
if((*it)->hook_func) std::thread((*it)->hook_func, key_message, kbdhook).detach();
}
}
return CallNextHookEx(NULL, code, key_message, reinterpret_cast<LPARAM>(kbdhook));
}
I know it's an old question but I just wanted to throw in my two cents. I hope this is helpful to someone.
I am currently facing issues when trying to compile my code that contains this WinProc function which is being used to process messages from our program. For example if a WM_DESTROY message is received via windows I want it to call PostQuitMessage(0) to signal Windows that the application has made a request to quit. Which will cause the WM_QUIT message to cause the WinMain to exit.
I have only been learning C++ a few weeks and don't have the experience or knowledge to fix this and would appreciate any help. I have looked around but so far I cannot find any solutions. I'm pretty new to this so I may have missed something really obvious.
LRESULT WINAPI WinProc (hWnd, msg, UNIT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY;
// Tell windows to kill the program
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hWnd, msg, wParam, lParam );
}
Below is the errors I experience wit the code that I have provided.
error: 'LRESULT WinProc' redeclared as different kind of symbol
error: previous declaration of 'LRESULT WinProc(HWND__*, UINT, WPARAM, LPARAM)'
error: 'hWnd' was not declared in this scope
error: 'msg' was not declared in this scope
error: 'UNIT' was not declared in this scope
Any help would be greatly appreciated.
Thanks
In the function declaration
LRESULT WINAPI WinProc (hWnd, msg, UNIT msg, WPARAM wParam, LPARAM lParam )
you forgot to set type specifiers for the first two parameters hWnd and msg
There must be
LRESULT WINAPI WinProc ( HWND hWnd, UNIT msg, WPARAM wParam, LPARAM lParam )
Also the label has to be followed by a colon while you placed a semicolon
case WM_DESTROY;
try using the callback calling convention instead of winapi
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633570(v=vs.85).aspx
also note the usage of " : " instead of " ; " on switch statement , also specify a type before the handle and message arguments
LRESULT CALLBACK WinProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch( msg )
{
case WM_DESTROY:
// Tell windows to kill the program
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hWnd, msg, wParam, lParam );
}
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM )
This should be the function declaration. Your case has a ";" semicolon instead of a ":" colon.
Besides this, I don't see any problems. Try this:
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
// Tell windows to kill the program
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hWnd, msg, wParam, lParam );
}
How can I access to the handle of a hook from his procedure ?
Example :
HHOOK hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)hookProc, GetModuleHandle(NULL), 0);
LRESULT CALLBACK hookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//I want my HHOOK here :O
}
You need to store the HHOOK variable in global memory. Don't declare it as a local variable of whatever function is calling SetWindowsHookEx().
Edit: Here is a class-based example for 32-bit CPUs:
class THookKeyboardLL
{
private:
HHOOK hHook;
void *pProxy;
static LRESULT CALLBACK ProxyStub(THookKeyboardLL *This, int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);
public:
THookKeyboardLL();
~THookKeyboardLL();
};
.
#include <pshpack1.h>
struct sProxy
{
unsigned char PopEax;
unsigned char Push;
void *ThisPtr;
unsigned char PushEax;
unsigned char Jmp;
int JmpOffset;
};
#include <poppack.h>
long CalcJmpOffset(void *Src, void *Dest)
{
return reinterpret_cast<long>(Dest) - (reinterpret_cast<long>(Src) + 5);
}
LRESULT CALLBACK THookKeyboardLL::ProxyStub(THookKeyboardLL *This, int nCode, WPARAM wParam, LPARAM lParam)
{
return This->HookProc(nCode, wParam, lParam);
}
THookKeyboardLL::THookKeyboardLL()
: hHook(NULL), pProxy(NULL)
{
sProxy *Proxy = (sProxy*) VirtualAlloc(NULL, sizeof(sProxy), MEM_COMMIT, PAGE_READWRITE);
Proxy->PopEax = 0x58;
Proxy->Push = 0x68;
Proxy->ThisPtr = this;
Proxy->PushEax = 0x50;
Proxy->Jmp = 0xE9;
Proxy->JmpOffset = CalcJmpOffset(&(Proxy->Jmp), &ProxyStub);
// Note: it is possible, but not in a portable manner, to
// get the memory address of THookKeyboardLL::HookProc()
// directly in some compilers. If you can get that address,
// then you can pass it to CalcJmpOffset() above and eliminate
// THookKeyboardLL::ProxyStub() completely. The important
// piece is that the Proxy code above injects this class
// instance's "this" pointer into the call stack before
// calling THookKeyboardLL::HookProc()...
DWORD dwOldProtect;
VirtualProtect(Proxy, sizeof(sProxy), PAGE_EXECUTE, &dwOldProtect);
FlushInstructionCache(GetCurrentProcess(), Proxy, sizeof(sProxy));
pProxy = Proxy;
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)pProxy, GetModuleHandle(NULL), 0);
}
THookKeyboardLL::~THookKeyboardLL()
{
if (hHook != NULL)
UnhookWindowsHookEx(hHook);
if (pProxy)
VirtualFree(pProxy, 0, MEM_RELEASE);
}
LRESULT CALLBACK THookKeyboardLL::HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// ...
return CallNextHookEx(hHook, nCode, wParam, lParam);
// when this method exits, it will automatically jump
// back to the code that originally called the Proxy.
// The Proxy massaged the call stack to ensure that...
}
If you look at the documentation for CallNextHookEx you see that the HHOOK parameter is optional on Windows NT, if you need to support Windows 9x then you need to store the HHOOK in a global variable.
Your example code shows that you are creating a global hook, global hooks are expensive so if you want to register more than one callback function you should abstract this so that your application only sets one hook and the callback function you register there calls your real functions (in a linked list etc).