欢迎访问mehome的博客

Tomorrow is another day.
Fork me on GitHub

Qt窗口置顶激活

一、环境及问题

系统环境: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
        }
    }
}
查看代码
posted @ 2021-12-31 01:00  mehome  阅读(1763)  评论(0编辑  收藏  举报