问题场景:近期项目中要解决元素坐标计算在桌面分辨率/缩放动态改变时有偏差的问题
测试猜想是动态改变分辨率/缩放之后坐标计算没有相应改变
之前计算dpi的方式为:
/// <summary>
/// 当前系统DPI_X 大小 一般为96
/// </summary>
public static int DpiX
{
get
{
IntPtr hdc = GetDC(IntPtr.Zero);
int DpiX = GetDeviceCaps(hdc, LOGPIXELSX);
ReleaseDC(IntPtr.Zero, hdc);
return DpiX;
}
}
该方式能得出屏幕dpi但是设置屏幕缩放改变之后,再次运行只会得到初始的dpi。即无法动态获取当前的dpi。
经过一番查找与跟同事交流得到两个可以动态获取dpi缩放的方式。
1.通过获取桌面的dpi,来确定为当前dpi。
/// <summary>
/// 获取动态的系统DPI_X 大小 防止分辨率改变后拿不到实际改变之后的dpi
/// </summary>
public static int DynamicDpiX
{
get
{
IntPtr hd1 = FindWindow("Progman", "Program Manager");
int DpiX = GetDpiForWindow(hd1);
return DpiX;
}
}
该方法获取桌面的句柄,然后调用API GetDpiForWindow 来获取当前桌面的dpi。经过测试,满足动态获取的要求。 但是需要注意一点,有的用户电脑,桌面的class Name可能不叫Progman, 而是WorkerW,所以可以加个对WorkerW的检测。
2.另外跟同事交流获取另外一种解决方式:
/// <summary>
/// 获取宽度缩放百分比
/// </summary>
public static float ScaleX
{
get
{
IntPtr hdc = GetDC(IntPtr.Zero);
int t = GetDeviceCaps(hdc, DESKTOPHORZRES);
int d = GetDeviceCaps(hdc, HORZRES);
float ScaleX = ((float)t) / d;
ReleaseDC(IntPtr.Zero, hdc);
return ScaleX;
}
}
这种是获取缩放系数,即dpi/96.
原理是用可视桌面的像素(DESKTOPHORZRES)除以真实像素(HORZRES)来获得比例。