一、环境及问题
系统环境:windows10 64位企业版
开发环境:vs2017+qt5.9.9+vsaddin2.7.2.2
问题:qt界面程序主界面置顶,并一直获取焦点使qt主窗口一直处于激活状态。
思路:定时器或者相关事件重载。
二、置顶和窗口右上角工具栏
2.1置顶
通过函数setWindowFlags设置属性:Qt::WindowStaysOnTopHint即可(setWindowFlags(Qt::CustomizeWindowHint);//窗口位置为普通)。
具体设置方法:通过main函数主窗体对象调用。
例如:
w.setWindowFlags(Qt::WindowStaysOnTopHint);
2.2右上角最小化/最大化/关闭按钮
只显示关闭按钮:
1 //右上角只有一个关闭按钮,和原始窗口关闭按钮一致 2 this->setWindowFlags(Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint); 3 4 //右上角只有一个关闭按钮,和原始窗口关闭按钮样式不一致,小一些 5 this->setWindowFlags(Qt::Tool); 6 7 //右上角显示“?”帮助按钮 8 this->setWindowFlags(Qt::WindowContextHelpButtonHint); 9 10 //右上角显示“最小化”按钮,关闭和最大化也同时显示 11 this->setWindowFlags(Qt::WindowMinimizeButtonHint); 12 13 //右上角显示“最大化”按钮,关闭和最小化也同时显示 14 this->setWindowFlags(Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint); 15 16 //最大化、最小化、关闭按钮这一行工具栏不显示 17 this->setWindowFlags(Qt::FramelessWindowHint);
三、激活方法
3.1定时器方法
在程序运行主题部分设置定时器,然后启动定时器,构造连接槽使定时器和激活窗口的相关操作相关联。
本示例把定时器放在qt程序的main函数内部,具体main函数如下:
#include <QtWidgets/QApplication> #include <QTimer> int main(int argc, char *argv[]) { QApplication a(argc, argv); GetMouseRGB w; w.setWindowFlags(Qt::WindowStaysOnTopHint); w.show(); QTimer *t = new QTimer; /* 定时两秒 */ t->start(200); QObject::connect(t, &QTimer::timeout, [&w]() { /* 提升该窗口到父窗口堆栈的顶部 */ w.raise(); /* 显示窗口 */ w.show(); /* 激活窗口 */ w.activateWindow(); }); return a.exec(); }
缺点:定时重复激活主窗口,即使不需要重新激活窗口也会重复激活,浪费计算资源。
3.2事件重载-休眠唤醒激活方法(推荐)
重载主窗体类的changeEvent函数,然后在这个重载函数内部激活qt窗口。
主窗体头文件(*.h)需要添加重载声明,如下:
protected: //重载事件 void changeEvent(QEvent *event);
主窗体实现文件(*.cpp)需要添加相应实现,如下:
void GetMouseRGB::changeEvent(QEvent *event) { QWidget::changeEvent(event); if (event->type() == QEvent::ActivationChange) { if (this->isActiveWindow()) { // widget is now active return; } else { //休眠10毫秒 QThread::msleep(10); //主窗体显示堆栈置顶 this->raise(); //显示窗体 this->show(); //激活主窗体 this->activateWindow(); // widget is now inactive } } }
注意:changeEvent重载函数激活窗口前需要msleep,否则不能重新激活窗口。
3.3事件重载-重置窗口位置方法(推荐)
和上面方法类似,只是置顶使用函数不一样,样例如下(头文件不再赘述):
void GetMouseRGB::changeEvent(QEvent *event) { QWidget::changeEvent(event); if (event->type() == QEvent::ActivationChange) { if (this->isActiveWindow()) { // widget is now active return; } else { setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); ::SetWindowPos((HWND)winId(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); ////休眠10毫秒 //QThread::msleep(10); ////主窗体显示堆栈置顶 //this->raise(); ////显示窗体 //this->show(); ////激活主窗体 //this->activateWindow(); //// widget is now inactive } } }
3.4事件重载-最小化窗口然后重新显示
具体代码如下:
void GetMouseRGB::changeEvent(QEvent *event) { QWidget::changeEvent(event); if (event->type() == QEvent::ActivationChange) { if (this->isActiveWindow()) { // widget is now active return; } else { activateWindow(); setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); raise();//必须加,不然X11会不起作用 #ifdef Q_OS_WIN32 //windows必须加这个,不然windows10 会不起作用,具体参看activateWindow 函数的文档 HWND hForgroundWnd = GetForegroundWindow(); DWORD dwForeID = ::GetWindowThreadProcessId(hForgroundWnd, NULL); DWORD dwCurID = ::GetCurrentThreadId(); ::AttachThreadInput(dwCurID, dwForeID, TRUE); ::SetForegroundWindow((HWND)winId()); ::AttachThreadInput(dwCurID, dwForeID, FALSE); #endif // MAC_OS //setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); //::SetWindowPos((HWND)winId(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); ////休眠10毫秒 //QThread::msleep(10); ////主窗体显示堆栈置顶 //this->raise(); ////显示窗体 //this->show(); ////激活主窗体 //this->activateWindow(); //// widget is now inactive } } }