我们知道,关于高DPI的支持, Windows XP时代就开始有了, 那时关于高DPI的支持比较简单, 但是从Vista/Win7 到现在Win8 /Win8.1, Windows关于高DPI的支持已经发生了很大的变化, 下面我们依次简单介绍下。
typedef enum _Process_DPI_Awareness { Process_DPI_Unaware = 0, Process_System_DPI_Aware = 1, Process_Per_Monitor_DPI_Aware = 2 } Process_DPI_Awareness;
下面我们依次讨论这3种方式:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
最后附上解决截图中窗口套索的思路:
1、禁止DWM缩放的飞秋
不管什么缩放比例,窗口大小始终不变,使用API Monitor可以探测到,飞秋在启动时调用了SetProcessDPIAware函数,告诉系统自己感知dpi,不需要系统进行DWM缩放。所以飞秋的窗口始终是100%显示比例时的窗口尺寸。
(1)飞秋套索系统窗口和QQ窗口是没问题的,后来通过API Monitor探测验证,系统窗口和QQ窗口都设置了DPIAware,即自己感知dpi,自己实现缩放,不需要系统进行DWM缩放。--》系统窗口和QQ窗口没有使用系统DWM缩放,使用GetWindowRect获取的他们的窗口坐标是当前看到的窗口原始坐标,即当前屏幕上看到的窗口大小,所以这些窗口套索没问题的。(自己禁用DWM缩放,不需要对禁用DWM缩放的程序窗口进行补偿)
(2)飞秋套索XX(我们的软件就叫XX吧)和imo窗口是有问题的,XX和imo窗口也有共同点,都没设置了DPIAware,即系统自动进行了DWM缩放。经观察,飞秋的套索框相对于XX和Imo窗口的实际大小要小。--》XX和imo窗口被系统进行了DWM缩放,对他们的窗口调用GetWindowRect比当前的显示比例下看到的窗口大小缩小了,所以要对XX和imo窗口的rect要进行放大补偿。(自己禁用DWM缩放,需要对使用了DWM缩放的程序窗口进行补偿)--》因为飞秋设置了DPAAware,指明不需要对飞秋的所有窗口进行DWM缩放,所以飞秋在截图模块绘制的套索窗口,没有进行放大,就是我们在屏幕上看到的大小。
2、禁止DWM缩放的QQ,在右键属性中勾选或者取消勾选“高DPI设置时禁用系统缩放”,对QQ没有任何影响,窗口都是放大的。使用API Monitor监测到,QQ在启动时也是调用了SetProcessDPIAware函数,将自己设置为自己感知DPI,不需要系统进行DWM缩放,QQ自己做了缩放。系统窗口也是类似的,也是自己做了对于DPI的缩放。
3、进行DWM缩放的XX
XX程序中没有做针对不同显示比例下的缩放,在显示比例大于100%时,由系统进行DWM索昂。经打印得知,在DWM缩放状态下,XX窗口中的WM_LBUTTONDOWN等消息中携带的光标坐标为当前缩放比下的DWM坐标,不是100%缩放比时的坐标。
(1)XX套索XX自己和imo,是没有问题的。XX和imo有个共同点,都是系统进行的DWM缩放,在调用GetWindowRect获取XX和imo窗口时,由于他们都进行了DWM缩放,所以获取的是DWM缩放后的坐标。我们在套索窗口时,使用Get来的坐标绘制(100%),系统会帮们放大2倍到200%显示到屏幕上(自己使用了DWM缩放,不需要对使用了DWM缩放的程序窗口进行补偿)
(2)XX套索QQ和系统窗口时有问题的,QQ和系统窗口有个共同点,都是自己实现缩放的,系统没有进行DWM缩放,所以在调用GetWindowRect获取QQ和系统窗口时,获取的是没有经过DWM缩放的原始坐标,是我们在屏幕上看到的窗口大小(已经放大后的大小)。用这个原始尺寸在我们的截图模块中去绘制套索窗口,因为我们XX的窗口使用了DWM缩放,会对绘制的进行DWM放大,相当于放大了2x2=4倍,所以补偿的方法是将目标窗口的坐标缩小1/2,这样经过系统DWM放大后,就是1倍的大小,就是我们看到的已经放大的窗口大小了。(自己使用了DWM缩放,需要对禁用了DWM缩放的程序窗口进行补偿)
4、最后发散一下,QQ为什么能做到完美兼容呢?(猜测其中的原因)
QQ是大厂商,估计是和微软有技术合作,对于win7以上系统的新的特性做了新的处理。QQ对windows的新的特性也不了解,应该是出现问题,告诉微软,让微软给出解决方案。比如通过API Monitor抓到QQ调用了DwmGetWindowAttribute函数,这个函数MSDN上都没有详细的说明,QQ是怎么知道这个函数的呢?当时探测时,将左边的所有函数都选上了,一部分一部分函数试,才知道QQ调用了DwmGetWindowAttribute函数。DwmGetWindowAttribute获取的是100%时的窗口尺寸,GetWindowRect获取的是经过DWM缩放后的窗口尺寸。
QQ是我们做im软件的标杆,正所谓一直被模仿,从未被超越!
有对比才有进步,有参考才有思路!