简体   繁体   中英

C#: Get complete desktop size?

How do I find out the size of the entire desktop? Not the "working area" and not the "screen resolution", both of which refer to only one screen. I want to find out the total width and height of the virtual desktop of which each monitor is showing only a part.

You have two options:

  1. PresentationFramework.dll

     SystemParameters.VirtualScreenWidth SystemParameters.VirtualScreenHeight 
  2. System.Windows.Forms.dll

     SystemInformation.VirtualScreen.Width SystemInformation.VirtualScreen.Height 

Use the first option if you developing a WPF application.

I think it's time to bring this answer up to date with a little LINQ, which makes it easy to get the entire desktop size with a single expression.

Console.WriteLine(
    Screen.AllScreens.Select(screen=>screen.Bounds)
    .Aggregate(Rectangle.Union)
    .Size
);

My original answer follows:


I guess what you want is something like this:

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);

Keep in mind that this doesn't tell the whole story. It is possible for multiple monitors to be staggered, or arranged in a nonrectangular shape. Therefore, it may be that not all of the space between (minx, miny) and (maxx, maxy) is visible.

EDIT:

I just realized that the code could be a bit simpler using 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);

Check:

SystemInformation.VirtualScreen.Width
SystemInformation.VirtualScreen.Height

This doesn't answer the question, but merely adds additional insight on a window's Point (location) within all the screens).

Use the code below to find out if a Point (eg last known Location of window) is within the bounds of the overall Desktop. If not, reset the window's Location to the default pBaseLoc ;

Code does not account for the TaskBar or other Toolbars, yer on yer own there.

Example Use: Save the Window location to a database from station A . User logs into station B with 2 monitors and moves the window to the 2nd monitor, logs out saving new location. Back to station A and the window wouldn't be shown unless the above code is used.

My further resolve implemented saving the userID and station's IP (& winLoc) to database or local user prefs file for a given app, then load in user pref for that station & app.

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;

To get the physical pixel size of the monitor you can use this.

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);
    }


}

You can use the Bounds of System.Drawing .

You can create a function like this

public System.Windows.Form.Screen[] GetScreens(){
    Screen[] screens = Screen.AllScreens;
    return screens;
}

and than you can get the screen one, two, etc. in a variable like this:

System.Windows.Form.Screen[] screens = func.GetScreens();
System.Windows.Form.Screen screen1 = screens[0];

then you can get the bounds of the screen:

System.Drawing.Rectangle screen1Bounds = screen1.Bounds;

With this code you will get all the properties like Width , Height , etc.

This method returns the rectangle that contains all of the screens' bounds by using the lowest values for Left and Top, and the highest values for Right and 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);
}

I think the best way to get the "real" screen-size, is to get the values directly from the video-controller.


    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);
                }
            }
        }
}

This should do the job ;) Greetings ...

Get the Size of a virtual display without any dependencies

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);
}

派生自 SM_XVIRTUALSCREEN 等的值是物理坐标,不等于控制面板中屏幕缩放 125%、150%、175% 的逻辑坐标。

You'll find that many window manipulations are not yet available or may not ever be made available. I've had the greatest success with PInvoke.User32 nuget package.

var screenX = PInvoke.User32.GetSystemMetrics(PInvoke.User32.SystemMetric.SM_CXSCREEN);
var screenY = PInvoke.User32.GetSystemMetrics(PInvoke.User32.SystemMetric.SM_CYSCREEN);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM