C #: Отримати повний розмір робочого столу?


77

Як дізнатися розмір всього робочого столу? Не "робоча зона" і не "роздільна здатність екрану", обидва з яких стосуються лише одного екрану. Я хочу дізнатись загальну ширину та висоту віртуального робочого столу, кожен монітор якого відображає лише частину.


2
Можливо, "повний розмір робочого столу" буде залежати від розташування екранів. Не знаю, як це розрахувати, але ви все одно можете визначити кількість екранів та роздільну здатність кожного екрана за допомогою System.Windows.Forms.Screen.AllScreens.
Havenard

Відповіді:


130

У вас є два варіанти:

  1. PresentationFramework.dll

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

    SystemInformation.VirtualScreen.Width   
    SystemInformation.VirtualScreen.Height
    

Використовуйте перший варіант, якщо ви розробляєте програму WPF.


1
Більше таких відповідей! Короткий, правильний та естетично приємний!
Bitterblue,

Я знайшов сценарії, коли ці значення реєструватимуть лише один екран, якщо ввімкнено масштабування. Може залежати від апаратного забезпечення, ще не впевнений.
Келлі Елтон,

Це, мабуть, було дано ще в 2011 році, коли масштабування багато робочих столів не було річчю. @KellyElton оновіть відповідь, якщо знайдете виправлення.
Денніс

1
Мені не вдалося знайти рішення цього, я думаю, це помилка. Я використовую адаптер Blackweb BWA17HO002 usb3 для hdmi з Intel HD 520 (ноутбук). Коли у мене масштаб дисплея> 150% на ноутбуці, ці значення повернуть лише розміри екрана ноутбука. Як тільки я видалю масштаб, він реєструє другий монітор.
Келлі Елтон,

31

Думаю, настав час оновити цю відповідь за допомогою невеликого 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);

3
Я український програміст. Я перевіряю, що цей код працює з коробки. Просто скопіюйте та вставте.
Вова Попов


7

Щоб отримати фізичний розмір пікселів монітора, ви можете використовувати це.

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


}

Це перший, який повідомляє правильний розмір, але лише для одного монітора. 😑
BrainSlugs83

6

Це не дає відповіді на запитання, а лише додає додаткового розуміння точки (розміщення) вікна на всіх екранах).

Використовуйте наведений нижче код, щоб з’ясувати, чи знаходиться Точка (наприклад, останнє відоме Розташування вікна) в межах загального робочого столу. Якщо ні, скиньте Розташування вікна до типового значення pBaseLoc ;

Код не враховує панель завдань або інші панелі інструментів, тому що ви там є.

Приклад використання: Збереження розташування вікна в базі даних від станції A . Користувач входить до станції B за допомогою 2 моніторів і переміщує вікно до 2-го монітора, виходячи із збереження нового місця. Назад до станції А вікно не відображатиметься, якщо не буде використаний наведений вище код.

Моє подальше рішення дозволило зберегти ідентифікатор користувача та 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;

6
Якщо ви знаєте, що це не відповідає на питання, чому ви публікуєте це як відповідь на питання? Чи не повинно перше речення пролунало на сполох?
Timwi

1
З іншого боку, це саме те, що я шукав, коли шукав цю тему
Саймон Гіллбі

3

Я думаю, що найкращим способом отримати "справжній" розмір екрану є отримання значень безпосередньо з відеоконтролера.


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

Це повинно зробити роботу;) Вітаю ...


1

Ви можете використовувати межі System.Drawing.

Ви можете створити подібну функцію

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і т.д.


1

Цей метод повертає прямокутник, який містить усі межі екранів, використовуючи найнижчі значення для лівого та верхнього та найвищі значення для правого та нижнього ...

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

Поясніть, будь ласка.
Syeda Zunaira

Він проходить через всі екрани. Якщо лівий край менший за змінну 'l', він встановлює для 'l' це нове значення, якщо нижній край більше за 'b', то він встановлює це. Кінцевим результатом є l, t, r, b, встановлені лівий, верхній, правий та нижній краї усього видимого робочого столу.
dynamichael

1

Отримайте розмір віртуального дисплея без будь-яких залежностей

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

Найкраща відповідь IMO, відсутність явних залежностей.
Zintom,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.