由于 win 7 和 win 10 的 dpi 处理方式不同,导致我们写的客户端程序在 win 7 上运行正常,在 win 10(dpi:150%)上运行不正常了。

 

具体的描述,可参考:解决win10系统中截图异常放大的问题 ()

win 10 通过 DWM 虚拟化支持的 高DPI方式,这种方式的高DPI支持是通过DWM的缩放实现的, 具体过程是这样的, 比如我们当前系统的DPI是200%, 我们程序运行时,系统会告诉你当前DPI仍然是96(100%), 所以我们程序会仍然按照100%的方式进行绘画, 但是但是系统给我们的坐标是根据DPI缩小过后的(也就是我们对窗口调用GetWindowRect或是通过GetSystemMetrics(SM_CXSCREEN)得到的大小会比实际大小减半) , 当我们画完之后, DWM再对整个窗口进行200% 放大后画到屏幕上, 这样看起来我们的程序就自动支持高DPI了。

 

获取屏幕宽度和高度的代码:

int m_xScreen = GetSystemMetrics( SM_CXSCREEN );
int m_yScreen = GetSystemMetrics( SM_CYSCREEN );

 

win 10 当显示比例设置为100%时屏幕的宽度和高度就是当前系统设置的分辨率,当显示比例大于100%时,比如为N%,DWM虚拟化会将GetWindowRect等获取的像素尺寸缩小到分辨率的1/(N%),所以结合获取的桌面图片区域的比例情况,是不是可以考虑使用当前系统设置的分辨率宽度和高度来获取整张桌面图片,因为分辨率宽度和高度大于当前桌面的像素宽度和高度,所以在向内存中拷贝图片时,需要选用StretchBlt,将图片进行缩放,缩放到桌面的像素高度和宽度。经过试验,这样做确实是可行的,具体的做法是,先调用EnumDisplaySettings获取当前系统设置的分辨率,然后判断屏幕宽度是否小于分辨率,若小于就要换用StretchBlt进行缩放处理。

平时写的程序在 win 7不同的 dpi 下,都能正常运行,但在 win 10 不同的 dpi 上,表现就不同了。

因此,针对 win 10 系统, 判断是否在 dpi > 100% 环境下:

int m_xScreen = GetSystemMetrics(SM_CXSCREEN);

if (在 win 10 系统下)
{
    DEVMODE curDevMode;
        
    memset(&curDevMode, 0, sizeof(curDevMode));
        
    curDevMode.dmSize = sizeof(DEVMODE);
        
    BOOL bEnumRet = EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &curDevMode);
        
    if (bEnumRet && m_xScreen < curDevMode.dmPelsWidth)

    {
        //这里就是在 win 10 的 高 dpi 环境下。 dpi > 100%
    }
}