zoukankan      html  css  js  c++  java
  • 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
            }
        }
    }
    查看代码
  • 相关阅读:
    软考过后
    最近
    软考复习初体验
    再看提高班
    C语言深入学习系列 字节对齐&内存管理
    C++ 阶段一(已完成)
    小弟,开博学习了!!
    [学习心得] 我总结的进制转换
    《深入浅出设计模式》一书学习(.net版—简单工厂)
    安装mysql 获得 mysql.h 建立C接口
  • 原文地址:https://www.cnblogs.com/mehome/p/15751146.html
Copyright © 2011-2022 走看看