QT全局键盘检测(即失焦后依旧可以检测到键盘事件)

大家搜到这个博客,肯定是业务或者学习中需要该功能。我是在设计一个项目中,涉及到按下T进行语音说话时设计到的。qt自带的QKeyEvent事件,并不是全局有效,只有在鼠标点击该窗口后才会产生对应的鼠标事件。对此我特地查了很多CSDN和公司的论坛,总结出网上主要有四种方法。

1、就是使用grabKeyBoard(),经过测试,并不能达到预期的效果。这个实际效果是在多个窗口一起存在时,其中一个窗口需要一直获取键盘事件:可以在这个窗口中捕获键盘事件,即grabKeyboard(); 这样这个窗口可以一直获取键盘事件。即使这个窗口不在激活状态下依然可以获取键盘事件。同时激活状态的窗口是获取不到任何键盘事件的,直到捕获了键盘事件的窗口释放键盘事件releaseKeyboard(),才能获取键盘事件。

2、使用钩子,涉及到各种WINAPI,网上也有现有的demo,事实上,那几个并不能编译通过,可能是我环境的问题,不太涉及,不做过多评论;

3、注册热键,现在我们新建一个类GlobalApplication,继承QApplication,并重载notify函数,经测试,编译通过,不过也不能达到预期的效果,因为这个只能识别按下,不能识别键盘释放,不符合需求。

4、使用第三方库QHotKey,这个B站有视频教学,详细指导了怎么下载和怎么使用。不过和方法三类似,无法符合需求。

就在大家束手无策的时候,突然找到一个API,是windows下的,用来监测键盘的状态码的。
主角开始上场:
究竟是什么能满足这样的需求,失焦后按下触发、抬起释放呢!
getKeyState();

函数原型:
SHORT GetKeyState( int nVirtKey );
函数只有一个参数,即虚拟键码。返回值为SHORT类型,即短整型。GetKeyState函数是用来获取指定的虚拟键码的按键的状态。得到的状态表示按键是按下了还是弹起的,还是状态切换(大小写状态、数字键盘锁状态)。

一、判断按键是否被按下。通过高位来进行判断,高位为1表示按键按下,高位为0表示按键弹起。具体方法如下:

 方法1:如果高位为1表示按键按下,此时返回值为负数(<0);如果高位为0表示按键弹起,此时返回值为正数(>0)。所以可以通过返回值与0比较进行判断按键是否按下。

 方法2:如果高位为1表示按键按下,此时返回值为1xxx xxxx xxxx xxxx,与0x8000(二进制 形式:1000 0000 0000 0000)进行按位与操作,结果为1;反之,如果按键弹起,按位与后结果为0。

 也可定义如下宏:#define  IsKeyPressed(nVirtKey)     ((GetKeyState(nVirtKey) & (1<<(sizeof(SHORT)*8-1))) != 0);

IsKeyPressed(nVirtKey)函数返回值为TRUE,则表示按键按下;反之表示按键弹起。

经测试:该函数使用qDebug()打印后,会出现4种状态值,按下是-127,-128,释放是0,1。
为什么会这样设计,个人觉得应该是为了记录上一次的按键状态,至于具体为什么这样用在哪里,本人水平有限,没有做过多研究,希望有人评论讲解。

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt中可以通过重写QWidget或QMainWindow的keyPressEvent()函数来监听键盘事件。当用户在窗口中按下键盘上的任意键时,该函数将被调用。我们可以通过判断event->key()的键值来区分不同的按键,并根据需要进行相应的操作。 以下是一个简单的例子,演示如何在一个继承自QMainWindow的类中监听键盘事件: ```cpp class MyMainWindow : public QMainWindow { public: MyMainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { // 设置窗口的焦点策略,使其能够接收键盘事件 setFocusPolicy(Qt::StrongFocus); } protected: void keyPressEvent(QKeyEvent *event) override { // 判断按下的键值 switch (event->key()) { case Qt::Key_Escape: qDebug() << "Esc key pressed"; break; case Qt::Key_Enter: qDebug() << "Enter key pressed"; break; // 其他按键的处理 default: QMainWindow::keyPressEvent(event); break; } } }; ``` 在这个例子中,我们继承了QMainWindow类,并重写了其keyPressEvent()函数。在函数内部,我们使用switch语句来判断按下的键值。当按下Esc时,输出"Esc key pressed";当按下Enter时,输出"Enter key pressed"。其他按键的处理可以根据需求进行扩展。 需要注意的是,如果我们希望窗口能够接收键盘事件,我们需要在构造函数或初始化函数中设置窗口的焦点策略,例如通过setFocusPolicy(Qt::StrongFocus)来设置。这样,窗口将成为焦点项,并能够接收键盘事件。 以上就是使用Qt在后台监听键盘事件的方法,希望对你有所帮助。 ### 回答2: 在Qt中,我们可以通过继承QObject类并重新实现其eventFilter方法来实现对键盘事件的后台监听。具体步骤如下: 1. 创建一个新的类,继承自QObject类。 ```c++ class KeyEventListener : public QObject { Q_OBJECT public: explicit KeyEventListener(QObject *parent = nullptr) : QObject(parent) { } protected: bool eventFilter(QObject *obj, QEvent *event) override { if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); qDebug() << "Key Pressed: " << keyEvent->key(); // 在这里可以处理键盘事件,例如发送信号给其他对象进行相应操作 // 或者在此处进行特定的按键快捷操作 } // 始终返回false,以便将事件传递给被监听的对象 return false; } }; ``` 2. 在需要监听键盘事件的对象中,安装该事件过滤器。 ```c++ // 在需要监听键盘事件的地方,例如MainWindow的构造函数中 KeyEventListener *keyListener = new KeyEventListener(this); qApp->installEventFilter(keyListener); ``` 现在,当用户在应用程序中按下键盘时,键盘事件将被传递给keyListener对象的eventFilter方法进行处理。你可以根据自己的需要在eventFilter方法中添加适当的处理逻辑。 需要注意的是,keyListener对象需要在需要监听键盘事件的对象的生命周期内保持有效,因此通常将其分配为成员变量或全局对象。 另外,如果你希望对特定的窗口部件进行键盘事件监听,也可以直接将keyListener对象传递给该部件的installEventFilter方法。 ### 回答3: 在Qt中,我们可以通过重写QWidget的keyPressEvent()函数来监听键盘事件。当用户在程序窗口中按下键盘时,该函数就会被调用。 首先,我们需要创建一个继承自QWidget的自定义窗口类。在这个类中,我们重写keyPressEvent()函数,并在其中实现我们需要的逻辑。 在keyPressEvent()函数中,我们可以获取到用户按下的键盘事件的信息,包括按下的按键代码、按键字符等。我们可以根据这些信息来执行相应的操作,例如移动窗口、改变窗口大小、响应特定按键等。 除了重写keyPressEvent()函数,我们还可以重写其他相关的函数,例如keyReleaseEvent()函数,用于监听键盘松开事件。通过这些函数,我们可以完全控制程序窗口对键盘事件的响应。 在程序中,我们需要创建一个该自定义窗口类的实例,并将其设置为程序的主窗口。这样,整个程序就可以在后台监听用户的键盘事件了。 需要注意的是,当我们使用后台监听键盘事件时,可能会影响系统的其他键盘输入。因此,我们需要谨慎使用,并确保对用户的输入做出合适的响应,以提供良好的用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值