Qt编程问题分析----你的键盘事件怎么失效了?

最近做一个游戏的辅助点击的软件,主要用Qt和opencv开发,挺简单的,主界面文件,各个独立的任务类文件,由于要频繁截图频繁点击游戏画面,所以需要游戏界面在前台,我的想法是利用键盘输入特定键来停止程序运行。

但是使用QKeyEvent事件函数后发现一直触发不了这个keyReleaseEvent函数,特别是我在截图程序里写了让游戏窗口置于前台,现在键盘又用不了,很难受,想不明白为什么?

于是我问了通义千问,他说可以用多线程,让工作线程去执行任务,好嘛,照着做了,结果没有用,

发现了Qt界面拿不到焦点,于是把设置游戏前台行给注释掉了,但是还是拿不到焦点,再问,说是可以设置焦点,好嘛,照着做了,甚至每次触发信号,来给主界面设置焦点,结果还是没用。

再问原来windows对焦点事件管控严格,很难设置,于是只能通过windows键调出Qt主界面使之处于前台,再按键盘,也可以触发键盘事件了!

有点不理解,其他软件的频繁点击是怎么做到键盘事件秒接收秒停止的?

其实要想实现随时通过键盘实现槽函数处理,我们需要使用操作系统级别的函数来获取事件,如下:

首先,在cpp文件中添加全局变量和全局回调函数,这是系统级别的,我是windows系统。

// 全局变量,用于存储钩子句柄
HHOOK g_hHook = NULL;
// 静态指针,指向 MainWindow 实例
static MainWindow *mainWindowInstance = nullptr;
// 全局键盘钩子回调函数
LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode < 0) {
        return CallNextHookEx(g_hHook, nCode, wParam, lParam);
    }

    KBDLLHOOKSTRUCT *pKeyboard = (KBDLLHOOKSTRUCT *)lParam;
    int keyCode = pKeyboard->vkCode;

    if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
    {
        std::cout << "Global key released: " << keyCode << std::endl;
        // 发送信号给 MainWindow
        if (mainWindowInstance)
            QMetaObject::invokeMethod(mainWindowInstance, "handleGlobalKeyRelease", Qt::QueuedConnection, Q_ARG(int, keyCode));
        else
            std::cout << "MainWindow not found" << std::endl;
    }

    return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

在构造函数中安装全局键盘钩子

 // 安装全局键盘钩子
    g_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProc, nullptr, 0);
    if (g_hHook == nullptr) {
        std::cerr << "Failed to install global keyboard hook" << std::endl;
    }
    // 保存 MainWindow 实例指针q
    mainWindowInstance = this;

在析构函数中卸载全局键盘钩子

 // 卸载全局键盘钩子
    if (g_hHook != nullptr)
    {
        UnhookWindowsHookEx(g_hHook);
    }

 添加槽函数

void handleGlobalKeyRelease(int keyCode) {
        std::cout << "Handling global key release: " << keyCode << std::endl;
        QKeyEvent fakeKeyEvent(QEvent::KeyRelease, keyCode, Qt::NoModifier, QKeySequence(keyCode).toString());
        keyReleaseEvent(&fakeKeyEvent);  // 使用 postEvent 将事件发送到事件队列
    }

 最后重写你的keyReleaseEvent即可,操作系统会识别所有的键盘事件,然后发给本类实例,触发回调函数,进行键盘事件处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值