来源: http://bbs.csdn.net/topics/370177760

我在win32 + c写的界面中解决办法,就是把字体的字号给固定了,这样做的结果就是,不管dpi是否有改变,界面中控件的文字的字号不变,就不会出现文字换行的情况。

但像菜单文字的字号就变大了,combobox(右三角),checkbox(选择框)变大一点点,显的有点不协调。

但至少不影响使用。

下面是判断当前系统的dpi,然后重置字体的字号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//高DPI下界面错乱的解决方法
        HWND hwnd_desktop = GetDesktopWindow();
        HDC hdc = GetWindowDC(hwnd_desktop);
        int dpi = GetDeviceCaps(hdc, LOGPIXELSX);
        //printf("hwnd_desktop:%ld, dpi:%d\n", hwnd_desktop, dpi);
        ReleaseDC(hwnd_desktop, hdc);
 
        int dpi_diff = dpi - 96; //开发平台默认的dpi: 96
        if(dpi_diff > 0)
        {           
 
            float zoom = dpi_diff * 1.041666 / 100 + 1;
             
 
            lgf.lfWidth =  lgf.lfWidth / zoom;
            lgf.lfHeight = lgf.lfHeight / zoom;
 
            //printf("width:%ld, height:%ld\n", lgf.lfWidth, lgf.lfHeight);
        }

一般很少或者不开发产品的朋友可能不会发现。你可以在标准96DPI(一般情况下都是)下,新建一个窗体,载入一个小图片,窗体大小调整为刚好能容纳下图片。生成EXE文件。修改DPI值为120(即125%缩放,XP下桌面-属性-高级里面找,WIN7>屏幕分辨率->放大或缩小其他项目->中等)。系统会要求注销,注销后再进入系统运行EXE程序。马上会看到恶心的结果:窗体被扩大,而图片大小依旧,造成多出来的窗体部分空白。丑陋。如果在加上几个其他空间,丑陋效果更明显:

【普及个知识:】

屏幕坐标计量单位,分为逻辑和物理坐标(单位),物理坐标为像素点、厘米等;逻辑坐标为缇、DPI等DPI是指单位面积内像素的多少。例如,在96默认DPI下1英寸屏幕有96点像素,如果在120DPI下1英寸有120个像素点。缇是VB6中默认的计量单位,96DPI下15缇等于1像素,120DPI下12缇等于1像素。因此,就造成了不同DPI下窗体控件大小会随着DPI值增加而放大,原本设计时就比较大的窗体在高DPI下甚至会超出屏幕边界,还有其他更多问题。

我在 DPI:120下,测试用vb写的界面,发现会窗口和控件会自动放大尺寸,展示效果没有受到DPI的影响,估计与使用的逻辑坐标(单位)有关。

【解决思路】

断断续续想了很久,经过研究,终于发现导致界面错乱的所有原理原因和解决办法。

1.原理原因:界面错乱的关键在于DPI变化后,系统会将程序可视化界面和控件按比例放大。那么使用逻辑坐标(计量单位)就变得不可靠,因为他们都是通过物理单位换算而成,均会受到DPI变化影响,特别是VB6计量单位--缇。完全就是于DPI有着直接的换算关系(96DPI下15缇等于1像素,120DPI下12缇等于1像素)。那么什么单位才可靠呢?答案是--像素、厘米、毫米!锁住界面大小不让缩放的最终就是要锁定三个东西:高度像素值、宽度像素值、控件所位于窗体内的坐标像素值

2.以上这三者被锁定固定大小,界面就将“稳定”不再受到系统DPI干扰。那么:缇(逻辑单位)--像素(物理单位)--DPI(逻辑单位) 这三者间又是怎么换算的?公式还是:96DPI下15缇等于1像素,120DPI下12缇等于1像素;DPI每增加1,就放大1.041666倍。(1440/DPI值=X,X缇=1像素;1.041666是1.014666666666667的约值,如何计算活动省略,知道即可)

3.不仅仅界面和控件放大了,连字体都给放大了!96DPI下的9磅(默认)字体,同比120DPI下的9磅字体小了很多很多。要固定到96DPI 9磅字体的大小,就要使用到这上面这句“DPI每增加1,就放大1.041666倍”。判断当前客户机DPI,减去标准的96,所得值乘以1.041666,所得值为倍数,单位(%)。如120DPI-96=24,24X1.041666%约等于25%,再加上1就是125%。即120DPI比96DPI放大了125%

【总结】

96DPI下获得窗体、控件高度宽度和坐标(left,top)的缇数。除以15便是其物理单位---像素值。之后到客户机上,立即获得其DPI值,获得值为X,将1440除以X获得一个值。这时,窗体、控件高度宽度坐标(LEFT,TOP)缇数就应该为:(原缇数/15)*(1440/现DPI值);(解释:)这样所得到的就是设计时窗体、控件高宽和所在坐标的物理值(像素),之后再根据客户机DPI将这个物理值计算成合适的新缇数。

2014-08-11

高DPI下界面错乱的解决方法和原理的更多相关文章

  1. android设计的布局在阿拉伯语下界面错乱的解决方法

    (1)正在AndroidManifest.xml声明文件的application元素中,增加” android:supportsRtl=true” (2)建] androidの设计的布局在阿拉伯语下界 ...

  2. 解决VS在高DPI下设计出的Winform程序界面变形问题

    在目前高分屏流行的情况下,windows缩放与布局仍然设置为100%就显得太小(特别是笔记本),通常会调整为125%或150%, VS在缩放与布局设置为非100%的时候,就会自动启动DPI感知模式,以 ...

  3. max-height,min-height在IE下不支持的解决方法

    max-height,min-height在IE下不支持的解决方法 max-width:160px; max-height:160px; _width:expression(this.width &g ...

  4. android keytool 不是内部命令或外部命令在 (win7下不能用的解决方法)

    android 关于MD5指纹中 keytool在win7下不能用的解决方法 只要在cmd中执行如下命令即可:注意C:\Users\Administrator\.android\debug.keyst ...

  5. CentOS7 下linux不能上网解决方法​,centos7 eth0 没有ip,IP突然丢失

    CentOS7 下linux不能上网解决方法​ 在CentOS VMware下安装好linux后,发现有时不能直接联网,特分享下总结出来的经验,希望对新手有用 工具/原料 XP系统 VMware.Wo ...

  6. IE6-7下margin-bottom不兼容解决方法(非原创,视频中看到的)

    在IE低版本下有很多不兼容,现在将看到的   IE6-7下margin-bottom不兼容解决方法   演示一下,方便日后自己查阅. <!DOCTYPE html> <html la ...

  7. VS2017无法进入安装界面问题的解决方法

    VS2017无法进入安装界面问题的解决方法 打开C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe也没有 ...

  8. canvas 1px 出现模糊解决方法及原理

    关于canvas绘制1像素出现模糊的原因及解决方法 canvas是html5中非常强大的功能,但是在绘制的时候如果出现1像素,例如画一条1像素的线可能出现模糊情况. 一.解决方法 网上比较常见的解决方 ...

  9. ubuntu下QT输出程序控制台界面难看的解决方法

    这几天在ubuntu下装了QT5,但输出程序界面后,简直无法入目 于是,随便乱找后,终于找到解决方法 打开选项 在终端那行改下就行

随机推荐

  1. VUE 处理文本框获焦点高亮

    先贴例子代码  这里又三个div对应的三个input输入框 <!-- 登录的表单 --> <div class="input_group" :class=&quo ...

  2. Laravel 出现 No application encryption key has been specified.

    若文件根目录下没有 .env 1..env.example 改名使用命令 copy 修改为 .env 2.使用命令 php artisan key:generate  获取密码,自动保存到 .env3 ...

  3. Golang的方法传递值应该注意的地方

    其实最近看了不少Golang接口以及方法的阐述都有一个地方没说得特别明白.就是在Golang编译隐式转换传递给方法使用的时候,和调用函数时的区别. 我们都知道,在我们为一个类型变量申明了一个方法的时候 ...

  4. umount -fl用法

    umount, 老是提示:device is busy, 服务又不能停止的.可以用"umount -fl"解决! 挂载: mount - mount a filesystem mo ...

  5. mysql参数优化记录

    服务器参数16G内存,4核CPUvim /etc/my.cnf 原: back_log=170 max_connections=600 max_user_connections=0 thread_co ...

  6. python之读取和写入csv文件

    写入csv文件源码: #输出数据写入CSV文件 import csv data = [ ("Mike", "male", 24), ("Lee&quo ...

  7. 如何强制关闭LODOP或c-lodop已经弹出的预览窗口

    该文介绍一下LODOP和C-LODOP关于窗口的弹出,和如何强制关闭已经打开的预览窗口. 同一个页面,只能弹出一个窗口,lodop是禁止点击动作,而c-lodop会提示已有窗口开的,请关闭之类的默认提 ...

  8. 学习 Spring (一) Spring 介绍

    Spring入门篇 学习笔记 Spring 是什么 Spring 是一个轻量级的 IoC (控制反转)和 AOP (面向切面)的容器框架 框架与类库的区别 框架一般是封装了逻辑.高内聚的,类库则是松散 ...

  9. python时间模块time

    时间模块 时间模块主要处理和时间相关的事件,我们可以通过模块获取不同数据类型的时间以便我们需求. 表现时间的三种方式: 在pythn中表现时间的方式主要有三种:时间戳(stamptime).元祖时间( ...

  10. 【题解】Hanoi

    题目描述 有三根柱A,B,C.在柱A上有N块盘片,所有盘片都是大的在下面,小片能放在大片上面.并依次编好序号,现要将A上的N块片移到C柱上,每次只能移动一片,而且在同一根柱子上必须保持上面的盘片比下面 ...