#pragma warning disable 1591, 618 namespace AntdWpf.Microsoft.Windows.Shell.Standard { using System; using System.Diagnostics.CodeAnalysis; using System.Windows; using System.Windows.Media; internal static class DpiHelper { [ThreadStatic] private static Matrix _transformToDevice; [ThreadStatic] private static Matrix _transformToDip; /// /// Convert a point in device independent pixels (1/96") to a point in the system coordinates. /// /// A point in the logical coordinate system. /// Returns the parameter converted to the system's coordinates. public static Point LogicalPixelsToDevice(Point logicalPoint, double dpiScaleX, double dpiScaleY) { _transformToDevice = Matrix.Identity; _transformToDevice.Scale(dpiScaleX, dpiScaleY); return _transformToDevice.Transform(logicalPoint); } /// /// Convert a point in system coordinates to a point in device independent pixels (1/96"). /// /// A point in the physical coordinate system. /// Returns the parameter converted to the device independent coordinate system. public static Point DevicePixelsToLogical(Point devicePoint, double dpiScaleX, double dpiScaleY) { _transformToDip = Matrix.Identity; _transformToDip.Scale(1d / dpiScaleX, 1d / dpiScaleY); return _transformToDip.Transform(devicePoint); } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] public static Rect LogicalRectToDevice(Rect logicalRectangle, double dpiScaleX, double dpiScaleY) { Point topLeft = LogicalPixelsToDevice(new Point(logicalRectangle.Left, logicalRectangle.Top), dpiScaleX, dpiScaleY); Point bottomRight = LogicalPixelsToDevice(new Point(logicalRectangle.Right, logicalRectangle.Bottom), dpiScaleX, dpiScaleY); return new Rect(topLeft, bottomRight); } public static Rect DeviceRectToLogical(Rect deviceRectangle, double dpiScaleX, double dpiScaleY) { Point topLeft = DevicePixelsToLogical(new Point(deviceRectangle.Left, deviceRectangle.Top), dpiScaleX, dpiScaleY); Point bottomRight = DevicePixelsToLogical(new Point(deviceRectangle.Right, deviceRectangle.Bottom), dpiScaleX, dpiScaleY); return new Rect(topLeft, bottomRight); } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] public static Size LogicalSizeToDevice(Size logicalSize, double dpiScaleX, double dpiScaleY) { Point pt = LogicalPixelsToDevice(new Point(logicalSize.Width, logicalSize.Height), dpiScaleX, dpiScaleY); return new Size { Width = pt.X, Height = pt.Y }; } public static Size DeviceSizeToLogical(Size deviceSize, double dpiScaleX, double dpiScaleY) { Point pt = DevicePixelsToLogical(new Point(deviceSize.Width, deviceSize.Height), dpiScaleX, dpiScaleY); return new Size(pt.X, pt.Y); } public static Thickness LogicalThicknessToDevice(Thickness logicalThickness, double dpiScaleX, double dpiScaleY) { Point topLeft = LogicalPixelsToDevice(new Point(logicalThickness.Left, logicalThickness.Top), dpiScaleX, dpiScaleY); Point bottomRight = LogicalPixelsToDevice(new Point(logicalThickness.Right, logicalThickness.Bottom), dpiScaleX, dpiScaleY); return new Thickness(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y); } #region Per monitor dpi support public static DpiScale GetDpi(Visual visual) { #if NET40 || NET45 var source = PresentationSource.FromVisual(visual); if (source?.CompositionTarget == null) { return new DpiScale(1.0, 1.0); } var device = source.CompositionTarget.TransformToDevice; return new DpiScale(device.M11, device.M22); #else return VisualTreeHelper.GetDpi(visual); #endif } internal static DpiScale GetDpi(this Window window) { return GetDpi((Visual)window); } #endregion Per monitor dpi support } #if NET40 || NET45 /// Stores DPI information from which a or is rendered. public struct DpiScale { private readonly double _dpiScaleX; private readonly double _dpiScaleY; /// Gets the DPI scale on the X axis. /// The DPI scale for the X axis. public double DpiScaleX { get { return this._dpiScaleX; } } /// Gets the DPI scale on the Yaxis. /// The DPI scale for the Y axis. public double DpiScaleY { get { return this._dpiScaleY; } } /// Get or sets the PixelsPerDip at which the text should be rendered. /// The current value. public double PixelsPerDip { get { return this._dpiScaleY; } } /// Gets the DPI along X axis. /// The DPI along the X axis. public double PixelsPerInchX { get { return 96.0 * this._dpiScaleX; } } /// Gets the DPI along Y axis. /// The DPI along the Y axis. public double PixelsPerInchY { get { return 96.0 * this._dpiScaleY; } } /// Initializes a new instance of the structure. /// The DPI scale on the X axis. /// The DPI scale on the Y axis. public DpiScale(double dpiScaleX, double dpiScaleY) { this._dpiScaleX = dpiScaleX; this._dpiScaleY = dpiScaleY; } } #endif }