Qt获取键盘按键事件(Windows API)----StateReader系列

来源:互联网 发布:python网络编程 知乎 编辑:程序博客网 时间:2024/06/18 16:00

Qt对于系统底层,一直没有很好的支持,例如串口并口通信,还有我们经常都会用到的全局热键,等等。既然Qt可能出于某种原因,不对这些进行支持,我们就只能自己写代码,调用系统相关的API了。

需求:获取Caps Lock键的状态,并使程序在后台运行时能够及时得到Caps Lock键的状态。

方法有两种,一是注册全局热键(想法很好,可惜注册后这个键原先的功能就没了,不采用)。二是隔一段时间读取一次按键状态(很好用,而且CPU消耗也不大)

1. 使用RegisterHotKey函数 注册全局热键

BOOL RegisterHotKey( HWND hWnd, int id, UINT fsModifiers, UINT vk );

HWND类型是Windows中的窗口句柄类型,在Qt中,QWidget及其子类均可使用winId()函数得到。

在本文,第二个参数是”virtual key 虚拟键”相对应的数字。

后面两个参数,一个是修饰键,一个是普通按键。例如,假设我们想注册Ctrl+F4这个热键组合,则fsModifiers就是MOD_CONTROL,而vk就是VK_F4。

主要步骤为用RegisterHotKey向系统注册全局的快捷键,然后重载QApplication的winEventFilter函数,并响应msg为WM_HOTKEY时的消息,整个过程类似于在Windows下的OnMessage进行消息响应,只是这次是在Qt中。

//MyApp类 class MyAPP : public QApplication{    .......    virtual bool winEventFilter(MSG *msg, long *result);signals:    void getF10HotKey();    void getF11HotKey();};bool MyApp::winEventFilter(MSG *msg, long *result){    if(WM_HOTKEY == msg->message){        if(msg->wParam == VK_F10){            //qDebug("VK_F10 winEventFilter.");            emit getF10HotKey();        }        if(msg->wParam == VK_F11){            //qDebug("VK_F11 winEventFilter.");            emit getF11HotKey();        }        return true;    }    return false;}//QtTopic类class QtTopic : public QWidget{public:    void registerGlobalKey();private slots:    void hotKeyF10Received();    void hotKeyF11Received();};void QtTopic::registerGlobalKey(){ //注册全局键    if(RegisterHotKey(this->winId(), 0x79, 0, VK_F10)){//0x79 is VK_F10, wParam is 121        qDebug("F10 registered for QtTopic.");    }    if(RegisterHotKey(this->winId(), 0x7A, 0, VK_F11)){//wParam is 122        qDebug("F11 registered for QtTopic.");    }}void QtTopic::hotKeyF10Received(){ //F10被按下    qDebug("F10 received.");    if(box->isChecked()) box->setChecked(false);void QtTopic::hotKeyF11Received(){    qDebug("F11 received.");    if(!box->isChecked()) box->setChecked(true);}//Mainint main(int argc,  char *argv[]){    Q_INIT_RESOURCE(qttopic);    MyApp app(argc, argv);    QtTopic topic;    topic.show();    QObject::connect(&app, SIGNAL(getF10HotKey()), &topic, SLOT(hotKeyF10Received()));    QObject::connect(&app, SIGNAL(getF11HotKey()), &topic, SLOT(hotKeyF11Received()));    return app.exec();}

2.GetKeyState() 定时读取状态

函数原型 SHORT GetKeyState(int nVirtKey);
其中,形参是虚拟键;
GetKeyState可以返回不同的值来表示键是否被按下、键是否被触发,或者是关闭状态。

进入正题部分:
这里我们继续用Thread来读取按键状态:
基本思路是每隔1s读取一次键盘状态,通过发送信号,来使另一个类中的槽来读取键盘的状态。

#include "windows.h"  //需要加入的头文件
//QueryKeyThreadclass QueryKeyThread : public QThread{    Q_OBJECT    ...public:    void run();signals:    void QueryResult(bool cap, bool num);};void QueryKeyThread::run(){    while(!stopped)    {        bool caps = false, nums = false;        if(GetKeyState(VK_CAPITAL) & 0x0001)        {            caps = true;        }        if(LOBYTE(GetKeyState(VK_NUMLOCK)))        {            nums = true;        }        emit QueryResult(caps, nums);        msleep(1000);    }}
//StateReaderclass StateReader : public QDialog{    ...protected slots:    //Thread Back    void QueryResult(bool cap, bool num);    ...};StateReader::StateReader(QWidget *parent) :    QDialog(parent),    ui(new Ui::StateReader){    ...    QueryKeyThread *pThread_KeyPress = new QueryKeyThread();    connect(pThread_KeyPress, SIGNAL(QueryResult(bool,bool)),            this, SLOT(QueryResult(bool,bool)));    pThread_KeyPress->start();    ...}void StateReader::QueryResult(bool cap, bool num){    if(cap)    {        qDebug() << "Caps ON";        systemIcon->setIcon(QIcon(":/images/up3.ico"));        systemIcon->setToolTip("Caps On");        ui->checkBoxCap->setChecked(true);        ui->checkBoxCap->setDisabled(true);    }    else    {        qDebug() << "Caps OFF";        systemIcon->setIcon(QIcon(":/images/down3.ico"));        systemIcon->setToolTip("Caps OFF");        ui->checkBoxCap->setChecked(false);        ui->checkBoxCap->setDisabled(true);    }    if(num)    {        ui->checkBoxNum->setChecked(true);        ui->checkBoxNum->setDisabled(true);    }    else    {        ui->checkBoxNum->setChecked(false);        ui->checkBoxNum->setDisabled(true);    }}
0 0
原创粉丝点击