一、开发环境 VS + QT
二、问题背景
在Windows系统设置了不同的缩放比例(图1-缩放设置),导致控件乱了;在设置了缩放比例系数不同的情况下,QT程序运行起来后,控件大小没变,但字体被放大了,所以会感觉是控件乱了;或者在高清DPI下,同样的窗体大小显示效果差异比较大;
![](https://i-blog.csdnimg.cn/blog_migrate/08834d1d1945cec8e52fb473c5781867.png)
图1-缩放设置
三、
解决方案
关于设置了缩放比例系数不同的问题,一种解决方案是由系统接管,自动适应不同的缩放系数,当你放大的时候,所有窗体内的所有控件和字体都跟着放大,反之,亦然;但这会存在什么样的问题呢?就是当你设置的窗体是固定大小的时候(比方1400x800),如果你的屏幕的分辨率是1920x1080p,那么窗体有一部分就会被隐藏起来,即显示器无法把整个窗体全部显示出来;另一种解决方案是,我们使用Qt提供的解决方案,不对窗体进行缩放,但对所有的字体设置固定大小;关于第1种解决方案,我们需要使用到配置文件qt.conf,在文件里添加如下内容:
[Platforms]
WindowsArguments=dpiawareness=1
第1步,新建一个资源文件
第2步,在新建的资源文件里添加qt.conf,如图2所示:
![](https://i-blog.csdnimg.cn/blog_migrate/84d87bd41d2a0b02510af4a3d942ea12.png)
图2
最终,结果如图3所示:
![](https://i-blog.csdnimg.cn/blog_migrate/f04d36d21fec7919d69f31da43c173a7.png)
关于高清DPI的适配问题,这里提供两种解决方案供参考,一种解决方案是,我们同样也可以使用配置文件qt.conf的方式解决,如上所述,这里不再赘述;另一种解决方案是,我们针对不同的屏幕设置不同的缩放系数,具体的缩放系数根据自己的需求设定,这里提供一个示例供参考,如果找不到头文件,添加相应头文件即可:
static void HighDpiAdapt()
{
// 获取当前显示器的数目
int numbers = GetSystemMetrics(SM_CMONITORS);
string scale_name = "";
for (int i = 0; i < numbers; ++i)
{
DISPLAY_DEVICEW device;
device.cb = sizeof(device);
BOOL result = EnumDisplayDevicesW(NULL, i, &device, 0);
DEVMODEW device_mode;
device_mode.dmSize = sizeof(device_mode);
device_mode.dmDriverExtra = 0;
result = EnumDisplaySettingsExW(device.DeviceName, ENUM_CURRENT_SETTINGS, &device_mode, 0);
string screen_name = WStringToAnsiString(device.DeviceName);
scale_name += screen_name;
scale_name += (device_mode.dmPelsWidth > 1920) ? "=1.5;" : "=1;"; //设置不同的缩放比例系数
}
scale_name[scale_name.size() - 1] = '\0';
qputenv("QT_SCREEN_SCALE_FACTORS", scale_name.c_str());
//处理图像模糊问题
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
//禁止高缩放支持
//QGuiApplication::setAttribute(Qt::AA_DisableHighDpiScaling); //AA_EnableHighDpiScaling
//程序保持默认的尺寸,不缩放
QGuiApplication::setAttribute(Qt::AA_Use96Dpi);
}
在QApplication声明前调用该函数即可;
其他:
Windows枚举变量,详见Windows官方DPI,网址:
PROCESS_DPI_AWARENESS (shellscalingapi.h) - Win32 apps | Microsoft Docs