win32界面库duilib DPI的使用,及兼容win10

duilib是win32一个不错的界面库,有人维护的版本也支持DPI

DPI是什么

先了解什么是DPI,DPI全名是Dots Per Inch 就是每英寸中像素点的个数。Windows中默认为96。
在以前,电脑的屏幕一般分辨率都不高(1366x768),随着屏幕技术进步,逐渐高分屏也多了起来,到目前新出产品最低都是1080p,也就是1920x1080的分辨率,将来可能最低配还得上升,参见iMac的分辨率。分辨率提高了,但是屏幕的尺寸却没变,所以看起来颗粒感减少,画面细腻,是个好事啊。

可是,1080p的普及,对于很多还停留在老分辨率的软件,如果放到1080p或者更高的显示器上,如果还使用原来的96DPI,界面会看起来很小,眼睛很累,所以win8以上都有调整DPI缩放的设置,推荐一档是125%,也就是缩放1.25倍,原来的程序界面就被系统放大到1.25倍。
Windows采用DWM(Desktop Window Manager)来负责窗口显示,当DPI较高时,而软件又没有自己处理,这时系统帮你适配,如前面设置的125%的缩放。类似放大图片,所以你的程序会看起来模糊,这就你的界面库要支持DPI的重要性。

所谓界面库支持DPI,就是根据当前的缩放比例,使用相对应的分辨率的资源(图片和文字等)。

科普太多。直接进入主题吧。

DPI在Duilib中使用

有两种方法,一种是函数实现,一种是清单文件设置

1、函数实现

直接在你的InitWindows()里调用,

m_pm.GetDPIObj()->SetDPIAwareness(PROCESS_PER_MONITOR_DPI_AWARE);

内部是调用WindowsAPI

 HRESULT WINAPI SetProcessDpiAwareness(_In_ PROCESS_DPI_AWARENESSvalue);
typedef enum _PROCESS_DPI_AWARENESS { 
  PROCESS_DPI_UNAWARE            = 0,
  PROCESS_SYSTEM_DPI_AWARE       = 1,
  PROCESS_PER_MONITOR_DPI_AWARE  = 2
} PROCESS_DPI_AWARENESS;

该函数告诉系统,要不要你帮我适配,就是前面讲的给我强行拉伸。

  • ** PROCESS_DPI_UNAWARE** 告诉系统改程序自己无法处理不同DPI,获取的数据都是被处理过的。
  • PROCESS_SYSTEM_DPI_AWARE 告诉系统该程序会在启动的显示器上自己支持不同的DPI,但是如果程序被拖动到了其他DPI不一样的显示器上时,需要DWM的帮助。
  • PROCESS_PER_MONITOR_DPI_AWARE 告诉系统任何时候该程序都能适应不同的DPI,不需要任何帮助。
    如果你的程序支持 PROCESS_PER_MONITOR_DPI_AWARE,当你的窗口移动到DPI不同的显示器上时,会收到 WM_DPICHANGED 消息。
    主要相关API:
    SetProcessDpiAwareness :设置当前进程的DPI感知等级。
    GetDpiForMonitor :查询显示的DPI。
    MonitorFromPoint :获取指定点的显示器的句柄。
    MonitorFromRect :获取与指定矩形相交面积最大的显示器句柄。
二、清单文件配置
    <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">  
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">  
            <dpiAware>true</dpiAware>  
        </asmv3:windowsSettings>  
    </asmv3:application> 

设置dpi感知为ture,即自己处理适配。
配置完成后,你的程序不会随着系统设置的缩放而被拉伸。
PS:刚发现清单文件配置的duilib不能动态设置DPI,why?暂时先使用第一种方法吧!-_-

动态设置DPI显示:
//m_pm为窗口管理类,有的维护库为m_pManager
m_pm.SetDPI(120);  //当前窗口
m_pm.SetAllDPI(120);//所有窗口

注意120是DPI,96x125%=120,duilib默认是96,就是不缩放。
一般跟随系统的缩放比例可以写成:

int sysDPI =  GetDeviceCaps(m_pm.GetPaintDC(), LOGPIXELSX);   //获取系统DPI
m_pm.SetAllDPI(sysDPI);                

LOGPIXELSX: Logical pixels/inch in X
LOGPIXELSY: Logical pixels/inch in Y

兼容win10

发现,duilib并不支持win10的DPI。方法一里的设置一直不成功,看了会源码发现,是SetDPIAwareness里调用IsWindows8Point1OrGreater()一直失败,该函数顾名思义就是判断系统版是否8.1及以上版本。
注意 win8.1及以上才支持DPI Aware,所以这里要判断。
发现函数是拷贝了win10SDK的VersionHelpers.h里的源码。
内部调用

VerifyVersionInfo(...)

MSDN关于这个解释了一波
Targeting your application for Windows
GetVersion, GetVersionEx, VerifyVersionInfo这些函数最高只能识别出Win8,IsWindowsVersionOrGreater系列函数只是VerifyVersionInfo的一个封装,所以也存在同样的问题。
MSDN里说需要在配置清单里说明程序兼容win10

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <!-- OSVersion -->   
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <application>
            <!-- Windows 10 -->
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
            <!-- Windows 8.1 -->
            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
            <!-- Windows Vista -->
            <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
            <!-- Windows 7 -->
            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
            <!-- Windows 8 -->
            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
        </application>
    </compatibility>
</assembly>

程序清单加入上述。

visual studio里配置清单文件。

上述代码拷贝进xml文件,建议软件名.xml

项目属性-清单工具-输入输出-附加清单文件,加入$(TargetName).xml。

可以选择是否嵌入清单选项,否的话,程序exe目录下还会生成响应的xxxx.manifest,软件运行需要带上它,是的话就不用。


附常用清单文件:
支持Windows 6.0界面库、支持管理员权限、兼容WIN8/WIN10下取系统版本、兼容DPI Aware

<?xml version="1.0" encoding="UTF-8"?>   
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <!-- Windows 6.0 Style -->  
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
        </dependentAssembly>
    </dependency>
    <!-- Administrator -->  
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
            <requestedPrivileges>
                <requestedExecutionLevel level="requireAdministrator"></requestedExecutionLevel>
            </requestedPrivileges>
        </security>
    </trustInfo>
    <!-- DPI Aware -->
    <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
            <dpiAware>true</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>
    <!-- OSVersion -->
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">   
        <application>   
            <!-- Windows 10 -->   
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>  
            <!-- Windows 8.1/Windows Blue/Server 2012 R2 -->  
            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>  
            <!-- Windows Vista/Server 2008 -->  
            <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>   
            <!-- Windows 7/Server 2008 R2 -->  
            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>  
            <!-- Windows 8/Server 2012 -->  
            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>  
        </application>   
    </compatibility>  
</assembly>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容