zoukankan      html  css  js  c++  java
  • 高DPI下界面错乱的解决方法和原理

    来源: 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 ", 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("%ld, height:%ld ", 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

  • 相关阅读:
    Python3爬虫之爬取某一路径的所有html文件
    python获取数据网页数据并创建文件夹保存(基于python3.6)
    Python 爬取单个网页所需要加载的地址和CSS、JS文件地址
    java的关闭钩子(Shutdown Hook)
    如何形象的解释 webhook 这个词
    Webhook
    什么是webhook
    瞎折腾之Webhooks
    Java-马士兵设计模式学习笔记-观察者模式-读取properties文件,动态增加观察者
    怎么解决重装系统后“我的文档”拒绝访问(更改权限就可以了)
  • 原文地址:https://www.cnblogs.com/personnel/p/4585046.html
Copyright © 2011-2022 走看看