104 lines
3.6 KiB
C#
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;
|
|
}
|
|
}
|
|
} |