Files
HandyControl/src/Shared/HandyControl_Shared/Tools/Helper/DpiHelper.cs
T
2020-06-22 00:08:26 +08:00

104 lines
3.6 KiB
C#

using System;
using System.Windows;
using System.Windows.Media;
using HandyControl.Expression.Drawing;
using HandyControl.Tools.Interop;
namespace HandyControl.Tools
{
internal static class DpiHelper
{
private const double LogicalDpi = 96.0;
[ThreadStatic]
private static Matrix _transformToDip;
static DpiHelper()
{
var dC = InteropMethods.GetDC(IntPtr.Zero);
if (dC != IntPtr.Zero)
{
// 沿着屏幕宽度每逻辑英寸的像素数。在具有多个显示器的系统中,这个值对所有显示器都是相同的
const int logicPixelsX = 88;
// 沿着屏幕高度每逻辑英寸的像素数
const int logicPixelsY = 90;
DeviceDpiX = InteropMethods.GetDeviceCaps(dC, logicPixelsX);
DeviceDpiY = InteropMethods.GetDeviceCaps(dC, logicPixelsY);
InteropMethods.ReleaseDC(IntPtr.Zero, dC);
}
else
{
DeviceDpiX = LogicalDpi;
DeviceDpiY = LogicalDpi;
}
var identity = Matrix.Identity;
var identity2 = Matrix.Identity;
identity.Scale(DeviceDpiX / LogicalDpi, DeviceDpiY / LogicalDpi);
identity2.Scale(LogicalDpi / DeviceDpiX, LogicalDpi / DeviceDpiY);
TransformFromDevice = new MatrixTransform(identity2);
TransformFromDevice.Freeze();
TransformToDevice = new MatrixTransform(identity);
TransformToDevice.Freeze();
}
public static MatrixTransform TransformFromDevice { get; }
public static MatrixTransform TransformToDevice { get; }
public static double DeviceDpiX { get; }
public static double DeviceDpiY { get; }
public static double LogicalToDeviceUnitsScalingFactorX => TransformToDevice.Matrix.M11;
public static double LogicalToDeviceUnitsScalingFactorY => TransformToDevice.Matrix.M22;
public static Point DevicePixelsToLogical(Point devicePoint, double dpiScaleX, double dpiScaleY)
{
_transformToDip = Matrix.Identity;
_transformToDip.Scale(1d / dpiScaleX, 1d / dpiScaleY);
return _transformToDip.Transform(devicePoint);
}
public static Size DeviceSizeToLogical(Size deviceSize, double dpiScaleX, double dpiScaleY)
{
var pt = DevicePixelsToLogical(new Point(deviceSize.Width, deviceSize.Height), dpiScaleX, dpiScaleY);
return new Size(pt.X, pt.Y);
}
public static Rect LogicalToDeviceUnits(this Rect logicalRect)
{
var result = logicalRect;
result.Transform(TransformToDevice.Matrix);
return result;
}
public static Rect DeviceToLogicalUnits(this Rect deviceRect)
{
var result = deviceRect;
result.Transform(TransformFromDevice.Matrix);
return result;
}
public static double RoundLayoutValue(double value, double dpiScale)
{
double newValue;
if (!MathHelper.AreClose(dpiScale, 1.0))
{
newValue = Math.Round(value * dpiScale) / dpiScale;
if (double.IsNaN(newValue) || double.IsInfinity(newValue) || MathHelper.AreClose(newValue, double.MaxValue))
{
newValue = value;
}
}
else
{
newValue = Math.Round(value);
}
return newValue;
}
}
}