主窗体DPI、鼠标所在屏幕的DPI
1 开启DPI感知app.manifest
<!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。
将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
2 获取主窗体DPI
private double GetDpiScale()
{
var mainWindow = Application.Current.MainWindow;
if (mainWindow == null) return 1.0;
var presentationSource = PresentationSource.FromVisual(mainWindow);
if (presentationSource?.CompositionTarget == null) return 1.0;
return presentationSource.CompositionTarget.TransformToDevice.M11;
}
private double GetDpiScale()
{
//这个是主屏幕的DPI
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
{
// 获取当前屏幕的DPI
float dpiX = g.DpiX;
// 标准DPI是96,计算缩放比例
return dpiX / 96.0f;
}
}
3 获取鼠标点击屏幕的DPI
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Service
{
public class ScreenHelper
{
// 导入必要的 Windows API
[DllImport("user32.dll")]
private static extern IntPtr MonitorFromPoint(Point pt, uint dwFlags);
[DllImport("shcore.dll")]
private static extern int GetDpiForMonitor(IntPtr hmonitor, MonitorDpiType dpiType, out uint dpiX, out uint dpiY);
private enum MonitorDpiType
{
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
MDT_RAW_DPI = 2,
MDT_DEFAULT = MDT_EFFECTIVE_DPI
}
// 获取当前鼠标所在屏幕的DPI缩放比例
public static double GetDpiScaleAtMousePosition()
{
// 获取鼠标当前位置
Point mousePos = Cursor.Position;
// 获取鼠标所在屏幕的句柄
IntPtr monitorHandle = MonitorFromPoint(mousePos, 2 /*MONITOR_DEFAULTTONEAREST*/);
// 获取该屏幕的DPI
uint dpiX, dpiY;
if (GetDpiForMonitor(monitorHandle, MonitorDpiType.MDT_EFFECTIVE_DPI, out dpiX, out dpiY) == 0)
{
// 计算缩放比例(基于标准96DPI)
return dpiX / 96.0;
}
// 如果API调用失败,回退到主屏幕的DPI
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
{
return g.DpiX / 96.0;
}
}
}
}