Qt Windows 去掉标题栏后 最大化窗口时任务栏被窗口遮住问题

在写Qt窗口时,假如对窗口设置了 Qt::FramelessWindowHint 或者 Qt::CustomizeWindowHint 标志,会发现窗口在副屏上最大化会遮住任务栏。

假如自己实现最大化来解决这个问题,虽然能够解决,但窗口状态就需要自己维护
// 最大化窗口 将窗口大小设置为屏幕可用区域大小
this->setGeometry(QApplication::desktop()->availableGeometry());
在Windows中通过拦截窗口消息的方式可以更优雅的解决这个问题

在窗口类中重写 nativeEvent 函数来处理窗口消息:WM_GETMINMAXINFO
来自微软官方文档解释:

WM_GETMINMAXINFO
当窗口的大小或位置即将更改时,发送到窗口。 应用程序可以使用此消息替代窗口的默认最大化大小和位置,或者默认的最小或最大跟踪大小。
[https://learn.microsoft.com/zh-cn/windows/win32/winmsg/wm-getminmaxinfo?redirectedfrom=MSDN]

当窗口接收到最大化消息时会往窗口发送WM_GETMINMAXINFO消息,假如不处理此消息,窗口大小默认就是屏幕大小,那么我们可以拦截此消息去设置窗口大小

bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
#ifdef Q_OS_WIN
    MSG* msg = (MSG*)message;

    if (msg->message == WM_GETMINMAXINFO) {
        const auto flags = this->windowFlags();
        if (((flags & Qt::FramelessWindowHint) == Qt::FramelessWindowHint) || ((flags & Qt::CustomizeWindowHint) == Qt::CustomizeWindowHint)) {
            MINMAXINFO* mmi = (MINMAXINFO*)(msg->lParam);
            // 窗口所在屏幕的可用区域(去除任务栏的可用区域)
            const auto availableGeometry = QApplication::desktop()->availableGeometry(this->window());

            // 设置最大化的窗口大小
            mmi->ptMaxSize.y = availableGeometry.height();
            mmi->ptMaxSize.x = availableGeometry.width();

            return true;
        }
    }
#endif // Q_OS_WIN
    return MainWindow::parent_type::nativeEvent(eventType, message, result);
}

下面附上窗口类的完整示例:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    using parent_type = QMainWindow;

    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QApplication>
#include <QDesktopWidget>

#ifdef Q_OS_WIN
#include <Windows.h>
#endif // Q_OS_WIN

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::CustomizeWindowHint);

    // 最大化按钮
    connect(ui->pushButton, &QPushButton::clicked, this, [this]() {
        if (this->isMaximized()) this->showNormal();
        else this->showMaximized();
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
#ifdef Q_OS_WIN
    MSG* msg = (MSG*)message;

    if(msg->message == WM_GETMINMAXINFO) {
        const auto flags = this->windowFlags();
        if(((flags & Qt::FramelessWindowHint) == Qt::FramelessWindowHint) || ((flags & Qt::CustomizeWindowHint) == Qt::CustomizeWindowHint)) {
            MINMAXINFO* mmi = (MINMAXINFO*)(msg->lParam);
            const auto availableGeometry = QApplication::desktop()->availableGeometry(this->window());

            mmi->ptMaxSize.y = availableGeometry.height();
            mmi->ptMaxSize.x = availableGeometry.width();

            return true;
        }
    }
#endif // Q_OS_WIN
    return MainWindow::parent_type::nativeEvent(eventType, message, result);
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值