c++firemonkeymouse-hookc++builder-xe8

Calling method inside of mouse hook code causes access violation


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.


Solution

  • 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.