鼠标钩子代码内部的调用方法会导致访问冲突

时间:2015-10-09 15:59:02

标签: c++ firemonkey mouse-hook c++builder-xe8

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

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

但是,当我在GetHandle()中呼叫TMainForm时,我仍然会遇到访问冲突。此外,在尝试了更多的事情后,我意识到从MouseHook内部调用任何虚函数会导致访问冲突。

为什么我无法使用Platform::Win::WindowHandleToPlatform(this->Handle)->Wnd;内的MouseHook检索我的表单句柄?为什么在MouseHook内调用虚函数会导致访问冲突?

编辑:

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

1 个答案:

答案 0 :(得分:1)

您所描述的内容表明,在调用钩子时,您的全局MainForm指针未指向有效的Form对象。因此,对表单方法的任何调用(例如MouseHook())都将具有无效的this指针。您必须确保分配该指针。

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