背景

  1. 在不同的分辨率和缩放份额下,对客户端的UI进行适配
  2. 使用qt版本5.15.3
  3. 使用qt画板.ui进行界面布局

适配计划

计划1

交由Windows进行处理

创建 qt.conf 文件,并增加到 .qrc 资源文件中

qt.conf 文件内容

[Platforms]
WindowsArguments = dpiawareness=0

计划2

由qt进行接收

需求5.14之后才支持

QCoreApplication::SetAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::SetAttribute(Qt::AA_UseHighDpiPixmaps);

会进行四舍五入,整数倍缩放。即

100% <= scale < 150% 按 100% 缩放

150% <= scale < 250% 按 200% 缩放

以此类推…

未能符合实践想要的根据屏幕设置的实践 scale 等比缩放

原因:存在默认的缩放战略 round 会对份额进行四舍五入

QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy:Round);

HighDpiScaleFactorRoundingPolicy 的枚举下有多中战略可以选择,其中 PassThrough 是根据实践屏幕设置的 scale 值进行等比缩放

留意点

  1. 上述高分屏适配代码需求增加到使用初始化之前
int main(int argc, char *argv[]) {
    // 高分屏适配
    ...
    QApplication application();
    ...
}

开发中遇到的问题和解决办法

修改桌面分辨率之后,不能同步刷新使用

解决计划:在所有屏幕增加DPI变动的信号槽

// 获取所有屏幕
QList<QScreen *> screens = QApplication::screens();
// 遍历屏幕目标增加信号槽
...
    connect(screen, &QScreen::logicalDotsPerInchChanged, this, &MainWindow::OnLogicalDotsPerInchChanged);
...
// 槽函数实现
void MainWindow::OnLogicalDotsPerInchChanged(qreal dpi) 
{
    // 获取当时使用方位
    QPoint point = QPoint(this->screen()->geometry().x(), this->screen()->geometry().x());
    // 遍历screen,获取使用所在方位screen进行使用刷新
    for (auto &screen : QApplication::screens()) {
        if (QApplication::screenAt(point)->name() == screen->name()) {
            update();
        }
    }
}

多个不同dpi的屏幕之间来回拖动,超越鸿沟时,可能会呈现异常放大

系统进行了DWM虚拟化处理,可能呈现计算错误的状况

解决计划:在 QApplication 初始化之前调用 windows 函数

SetProcessDPIAware();

参考Windows文档

setProcessDPIAware 函数 (winuser.h) – Win32 apps | Microsoft Learn

遗留问题

屏幕缩放份额在放大时,怎么实现使用缩放份额最大值的约束?
例如电脑屏幕缩放份额300%时,约束使用份额为250%