在鼠标钩子代码中调用方法会导致访问冲突



我有一个低级鼠标钩子,我试图用它来处理全局左键点击事件。我已经在一个基本的主表单类中定义了钩子,如下所示:

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);
    }
}

我的鼠标钩子检测到左键点击很好,但是当我试图获得我的MainForm的句柄时,我得到了访问违规。

我最初认为这可能是因为我试图检索TMainForm类中的句柄,而实际上在运行时,从TMainForm继承的形式将是活跃的。为此,我编写了一个名为GetHandle()的虚方法。

这个函数在TMainForm头文件中定义如下:

virtual HWND__ * __fastcall GetHandle();

和在继承类中:

HWND__ * __fastcall TMainFormPass::GetHandle()
{
   return Platform::Win::WindowHandleToPlatform(this->Handle)->Wnd;
}

然而,当我在TMainForm中调用GetHandle()时,我仍然得到访问冲突。此外,在尝试了更多的东西之后,我意识到从MouseHook内部调用任何虚函数都会导致访问冲突。

为什么我不能检索我的窗体处理使用Platform::Win::WindowHandleToPlatform(this->Handle)->Wnd; MouseHook内部?为什么在MouseHook内部调用虚函数会导致访问冲突?

编辑:

为了测试Remy提出的MainForm指针无效的答案,我在TMainForm构造函数中添加了一段代码来测试指针是否有效。此外,我在类的构造函数中添加了一个代码块,该构造函数继承自TMainForm,并在启动应用程序时加载,以测试其全局指针。我的TMainForm类中的全局MainForm指针实际上是无效的。但是,继承类的全局指针是有效的,因为它是实际实例化的类。

你所描述的表明,当钩子被调用时,你的全局MainForm指针没有指向一个有效的Form对象。任何对这种形式的方法的调用,比如MouseHook(),都会有一个无效的this指针。你必须确保你正在赋值那个指针。

你正在使用SetWindowsHookEx()的例子,我给你在回答另一个问题。在同样的回答中,我还给了您一个不涉及SetWindowsHookEx()的替代解决方案-处理来自RAW Input API的WM_INPUT消息。你的问题没有提到你正在使用FireMonkey而不是VCL。我给你的例子是VCL。我现在已经更新了答案,包括一个FireMonkey的例子,以及

最新更新