如何查找整个桌面的大小?不是“工作区”和也不是“屏幕分辨率”,这两个属性只涉及一个屏幕。我想找出虚拟桌面的总宽度和高度,其中每个显示器仅显示一部分。
如何查找整个桌面的大小?不是“工作区”和也不是“屏幕分辨率”,这两个属性只涉及一个屏幕。我想找出虚拟桌面的总宽度和高度,其中每个显示器仅显示一部分。
PresentationFramework.dll
SystemParameters.VirtualScreenWidth
SystemParameters.VirtualScreenHeight
System.Windows.Forms.dll
SystemInformation.VirtualScreen.Width
SystemInformation.VirtualScreen.Height
如果你正在开发 WPF 应用程序,可以使用第一种选项。
我认为是时候用一些LINQ来更新这个答案了,它可以轻松地通过单个表达式获取整个桌面大小。
Console.WriteLine(
Screen.AllScreens.Select(screen=>screen.Bounds)
.Aggregate(Rectangle.Union)
.Size
);
我想你想要的是这样的:
int minx, miny, maxx, maxy;
minx = miny = int.MaxValue;
maxx = maxy = int.MinValue;
foreach(Screen screen in Screen.AllScreens){
var bounds = screen.Bounds;
minx = Math.Min(minx, bounds.X);
miny = Math.Min(miny, bounds.Y);
maxx = Math.Max(maxx, bounds.Right);
maxy = Math.Max(maxy, bounds.Bottom);
}
Console.WriteLine("(width, height) = ({0}, {1})", maxx - minx, maxy - miny);
请记住,这并不是全部情况。多个显示器可能会错开或以非矩形的形式排列。因此,并非(minx,miny)和(maxx,maxy)之间的所有空间都可见。
编辑:
我刚意识到可以使用Rectangle.Union
使代码更简洁:
Rectangle rect = new Rectangle(int.MaxValue, int.MaxValue, int.MinValue, int.MinValue);
foreach(Screen screen in Screen.AllScreens)
rect = Rectangle.Union(rect, screen.Bounds);
Console.WriteLine("(width, height) = ({0}, {1})", rect.Width, rect.Height);
检查:
SystemInformation.VirtualScreen.Width
SystemInformation.VirtualScreen.Height
static class DisplayTools
{
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
private enum DeviceCap
{
Desktopvertres = 117,
Desktophorzres = 118
}
public static Size GetPhysicalDisplaySize()
{
Graphics g = Graphics.FromHwnd(IntPtr.Zero);
IntPtr desktop = g.GetHdc();
int physicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.Desktopvertres);
int physicalScreenWidth = GetDeviceCaps(desktop, (int)DeviceCap.Desktophorzres);
return new Size(physicalScreenWidth, physicalScreenHeight);
}
}
这并没有回答问题,只是在窗口点(位置)在所有屏幕中的额外见解上添加了一些内容。
使用以下代码查找一个点(例如窗口的最后已知位置)是否在整个桌面的范围内。如果不在,则将窗口的位置重置为默认值pBaseLoc;
代码不考虑任务栏或其他工具栏,你需要自己处理。
示例用法:从站点A保存窗口位置到数据库。用户登录具有2个监视器的站点B并将窗口移动到第二个监视器,然后退出保存新位置。回到站点A,如果不使用上述代码,则不会显示窗口。
我的进一步解决方案是实现将userID和站点IP(&winLoc)保存到给定应用程序的数据库或本地用户首选项文件中,然后加载该站点和应用程序的用户首选项。
Point pBaseLoc = new Point(40, 40)
int x = -500, y = 140;
Point pLoc = new Point(x, y);
bool bIsInsideBounds = false;
foreach (Screen s in Screen.AllScreens)
{
bIsInsideBounds = s.Bounds.Contains(pLoc);
if (bIsInsideBounds) { break; }
}//foreach (Screen s in Screen.AllScreens)
if (!bIsInsideBounds) { pLoc = pBaseLoc; }
this.Location = pLoc;
using System;
using System.Management;
using System.Windows.Forms;
namespace MOS
{
public class ClassMOS
{
public static void Main()
{
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_VideoController");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("CurrentHorizontalResolution: {0}", queryObj["CurrentHorizontalResolution"]);
Console.WriteLine("-----------------------------------");
Console.WriteLine("CurrentVerticalResolution: {0}", queryObj["CurrentVerticalResolution"]);
}
}
catch (ManagementException e)
{
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
}
}
}
该方法通过使用Left和Top的最低值以及Right和Bottom的最高值,返回包含所有屏幕边界的矩形...
static Rectangle GetDesktopBounds() {
var l = int.MaxValue;
var t = int.MaxValue;
var r = int.MinValue;
var b = int.MinValue;
foreach(var screen in Screen.AllScreens) {
if(screen.Bounds.Left < l) l = screen.Bounds.Left ;
if(screen.Bounds.Top < t) t = screen.Bounds.Top ;
if(screen.Bounds.Right > r) r = screen.Bounds.Right ;
if(screen.Bounds.Bottom > b) b = screen.Bounds.Bottom;
}
return Rectangle.FromLTRB(l, t, r, b);
}
public System.Windows.Form.Screen[] GetScreens(){
Screen[] screens = Screen.AllScreens;
return screens;
}
然后你可以像这样将屏幕一、二等存储在变量中:
System.Windows.Form.Screen[] screens = func.GetScreens();
System.Windows.Form.Screen screen1 = screens[0];
System.Drawing.Rectangle screen1Bounds = screen1.Bounds;
Width
,Height
等。public enum SystemMetric
{
VirtualScreenWidth = 78, // CXVIRTUALSCREEN 0x0000004E
VirtualScreenHeight = 79, // CYVIRTUALSCREEN 0x0000004F
}
[DllImport("user32.dll")]
public static extern int GetSystemMetrics(SystemMetric metric);
public static Size GetVirtualDisplaySize()
{
var width = GetSystemMetrics(SystemMetric.VirtualScreenWidth);
var height = GetSystemMetrics(SystemMetric.VirtualScreenHeight);
return new Size(width, height);
}
你会发现许多窗口操作尚未可用,或者可能永远不会被提供。我使用PInvoke.User32 nuget包取得了最大的成功。
var screenX = PInvoke.User32.GetSystemMetrics(PInvoke.User32.SystemMetric.SM_CXSCREEN);
var screenY = PInvoke.User32.GetSystemMetrics(PInvoke.User32.SystemMetric.SM_CYSCREEN);