C# 获取当前屏幕信息(宽高和位置)
上一篇博客《C# 获取当前屏幕DPI》,介绍了如何获取当前屏幕的DPI设置
本章主要介绍如何获取当前窗口所在屏幕的信息
Sreen获取当前屏幕信息
如果当前是单屏幕,可以直接获取主屏幕
var primaryScreen = Screen.PrimaryScreen;
如果当前是多屏,建议通过窗口句柄获取Screen信息
var window = Window.GetWindow(ExportButton);//获取当前主窗口 var intPtr = new WindowInteropHelper(window).Handle;//获取当前窗口的句柄 var screen = Screen.FromHandle(intPtr);//获取当前屏幕
DpiPercent
DPI转换比例常量,DpiPercent = 96;
为何DpiPercent为96 ?有一个概念“设备无关单位尺寸”,其大小为1/96英寸。比如:
【物理单位尺寸】=1/96英寸 * 96dpi = 1像素;
【物理单位尺寸】=1/96英寸 * 120dpi = 1.25像素;
关于WPF单位和系统DPI,可以参考《WPF编程宝典》中相关章节
Screen.Bounds
Bounds对应的是屏幕的分辨率,而要通过Bounds.Width获取屏幕的宽度,则需要将其转化为WPF单位的高宽。
步骤:
- 获取当前屏幕的物理尺寸(X/Y方向的像素)--如X方向 currentGraphics.DpiX / DpiPercent
- 将Screen.Bounds的信息转化为WPF单位信息 --如高度 screen.Bounds.Width / dpiXRatio
using (Graphics currentGraphics = Graphics.FromHwnd(intPtr)) { double dpiXRatio = currentGraphics.DpiX / DpiPercent; double dpiYRatio = currentGraphics.DpiY / DpiPercent; var width = screen.Bounds.Width / dpiXRatio; var height = screen.Bounds.Height / dpiYRatio; var left = screen.Bounds.Left / dpiXRatio; var top = screen.Bounds.Top / dpiYRatio; }
User32-MonitorFromWindow获取屏幕信息
除了Screen对象,也可以通过User32获取指定窗口所在屏幕信息:
1 private static MonitorInfo GetMonitorByWindow(IntPtr windowHandle)
2 {
3 IntPtr monitorHandle = MonitorFromWindow(windowHandle, MONITOR_DEFAULTTONEAREST);
4 var mi = new MonitorInfoEx();
5 mi.Size = Marshal.SizeOf(mi);
6 var success = GetMonitorInfo(monitorHandle, ref mi);
7 if (!success)
8 {
9 return null;
10 }
11 var info = new MonitorInfo
12 {
13 ScreenSize =
14 new Vector2(mi.Monitor.right - mi.Monitor.left, mi.Monitor.bottom - mi.Monitor.top),
15 MonitorArea = new Rect(mi.Monitor.left, mi.Monitor.top, mi.Monitor.right - mi.Monitor.left,
16 mi.Monitor.bottom - mi.Monitor.top),
17 WorkArea = new Rect(mi.WorkArea.left, mi.WorkArea.top, mi.WorkArea.right - mi.WorkArea.left,
18 mi.WorkArea.bottom - mi.WorkArea.top),
19 IsPrimary = mi.Flags > 0,
20 Hmon = monitorHandle,
21 DeviceName = mi.DeviceName
22 };
23 return info;
24 }
25 [DllImport("user32.dll", SetLastError = true)]
26 static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
27
28 const uint MONITOR_DEFAULTTONULL = 0x00000000;
29 const uint MONITOR_DEFAULTTOPRIMARY = 0x00000001;
30 const uint MONITOR_DEFAULTTONEAREST = 0x00000002;
31 [DllImport("user32.dll", CharSet = CharSet.Auto)]
32 private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MonitorInfoEx lpmi);
33
34 private const int CCHDEVICENAME = 32;
35 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
36 internal struct MonitorInfoEx
37 {
38 public int Size;
39 public RECT Monitor;
40 public RECT WorkArea;
41 public uint Flags;
42
43 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
44 public string DeviceName;
45 }
P/Invoke 调用MonitorFromWindow获取显示器句柄,然后用GetMonitorInfo拿到屏幕信息。推荐使用这个方案,获取到的比较详细。
另外,如需要所有屏幕,可以使用EnumDisplayMonitors函数搭配GetMonitorInfo,枚举到所有屏幕。
SystemParameters获取屏幕的高宽
也可以通过System.Windows.SystemParameters,直接获取主屏幕信息,不过这个类只能获取主屏幕的高宽。
这里的高宽指的是实际高宽。
主屏幕:
var screenHeight = SystemParameters.PrimaryScreenHeight; var screenWidth = SystemParameters.PrimaryScreenWidth;
多屏时全屏幕:
var primaryScreenHeight = SystemParameters.FullPrimaryScreenHeight; var primaryScreenWidth = SystemParameters.FullPrimaryScreenWidth;
当前工作区域:(除去任务栏的区域)
var workAreaWidth = SystemParameters.WorkArea.Size.Width; var workAreaHeight = SystemParameters.WorkArea.Size.Height;
关键字:WPF单位,屏幕高宽/位置
作者:唐宋元明清2188
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。