I have a low level mouse hook which I am attempting to use to handle global left click events. I have defined the hook in a base main form class like so:
class TMainForm : public TForm
{
private:
HHOOK hMouseHook;
static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam);
void __fastcall MouseHook(int nCode, WPARAM wParam, LPARAM lParam);
};
extern PACKAGE TMainForm *MainForm;
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)
{
if (nCode >= 0 && wParam == WM_LBUTTONDOWN)
{
HWND__ * handle = Platform::Win::WindowHandleToPlatform(this->Handle)->Wnd;
RECT Rect;
GetWindowRect(handle, &Rect);
}
}
My mouse hook detects a left click just fine, however when I attempt to get the handle of my MainForm
I get an access violation.
I originally thought this could be because I was trying to retrieve the handle in the TMainForm
class, when in reality during run time, a form which inherits from TMainForm
would be active. So to do this, I wrote a virtual method called GetHandle()
.
This function is defined in the TMainForm
header like this:
virtual HWND__ * __fastcall GetHandle();
and in the inheriting class like this:
HWND__ * __fastcall TMainFormPass::GetHandle()
{
return Platform::Win::WindowHandleToPlatform(this->Handle)->Wnd;
}
However, when I call GetHandle()
in TMainForm
I still get an access violation. Additionally, after trying a few more things out, I realized that calling any virtual function at all from inside of MouseHook
causes an access violation.
Why am I not able to retrieve my forms handle using Platform::Win::WindowHandleToPlatform(this->Handle)->Wnd;
inside of MouseHook
? Why does calling a virtual function inside of MouseHook
cause an access violation?
Edit:
To test Remy's proposed answer of the MainForm pointer being invalid, I added a block of code to the TMainForm
constructor to test if the pointer was valid. Additionally, I added a block of code to the constructor of the class which inherits from TMainForm
and is loaded when starting my application, to test its global pointer. The global MainForm
pointer in my TMainForm
class was in fact invalid. However, the global pointer for the inheriting class was valid, being that it was the class actually being instantiated.
What you describe suggests that your global MainForm
pointer is not pointing at a valid Form object when the hook is called. Any call to a method of the form, such as MouseHook()
, will thus have an invalid this
pointer. You must make sure you are assigning that pointer.
You are using the SetWindowsHookEx()
example that I gave you in answer to another question. In that same answer, I had also given you an alternative solution that did not involve SetWindowsHookEx()
- handling the WM_INPUT
message from the RAW Input API. Your question did not mention that you are using FireMonkey instead of VCL. The example I had given you was for VCL. I have now updated that answer to include a FireMonkey example as well.