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 :获取与指定矩形相交面积最大的显示器句柄。
二、清单文件配置
      
          
            true  
          
     

设置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



       
    
        
            
            
            
            
            
            
            
            
            
            
        
    

程序清单加入上述。

visual studio里配置清单文件。

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

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

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


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

   

      
    
        
            
        
    
      
    
        
            
                
            
        
    
    
    
        
            true
        
    
    
       
           
               
              
              
              
              
               
              
              
              
              
           
      

你可能感兴趣的:(win32界面库duilib DPI的使用,及兼容win10)