美文网首页
win32界面库duilib DPI的使用,及兼容win10

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

作者: 李里里Riss | 来源:发表于2017-03-19 04:12 被阅读0次

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>

相关文章

网友评论

      本文标题:win32界面库duilib DPI的使用,及兼容win10

      本文链接:https://www.haomeiwen.com/subject/ckfmnttx.html