Як отримати розмір поточного екрану в WPF?


87

Я знаю, що можу отримати розмір основного екрану за допомогою

System.Windows.SystemParameters.PrimaryScreenWidth;
System.Windows.SystemParameters.PrimaryScreenHeight;

Але як отримати розмір поточного екрану? (Багатоекранні користувачі не завжди використовують основний екран, і не всі екрани використовують однакову роздільну здатність, так?)

Було б непогано мати можливість отримати доступ до розміру з XAML, але цього було б достатньо з коду (C #).


1
Визначте «поточний». Вікно може бути на декількох екранах одночасно.
Джим Балтер,

Відповіді:


13

Наскільки я знаю, не існує власної функції WPF для отримання розмірів поточного монітора. Натомість ви можете PInvoke вбудовані функції моніторів декількох дисплеїв , обернути їх у керований клас і виставити всі властивості, необхідні для споживання їх із XAML.


Це саме те, чого я боявся - необхідність якось P / викликати матеріали або отримати доступ до System.Windows.Forms.Screen. І при цьому мені завжди потрібно визначити "незалежні від пристрою пікселі" ... Хоча дякую.
Nils

Так ... Можливо, вам також допоможе функція SystemParameters.ConvertPixel (). Це внутрішнє, але Reflector байдуже :))
Anvaka

74

Я створив невелику обгортку навколо екрану з System.Windows.Forms, наразі все працює ... Хоча я не впевнений щодо "незалежних від пристрою пікселів".

public class WpfScreen
{
    public static IEnumerable<WpfScreen> AllScreens()
    {
        foreach (Screen screen in System.Windows.Forms.Screen.AllScreens)
        {
            yield return new WpfScreen(screen);
        }
    }

    public static WpfScreen GetScreenFrom(Window window)
    {
        WindowInteropHelper windowInteropHelper = new WindowInteropHelper(window);
        Screen screen = System.Windows.Forms.Screen.FromHandle(windowInteropHelper.Handle);
        WpfScreen wpfScreen = new WpfScreen(screen);
        return wpfScreen;
    }

    public static WpfScreen GetScreenFrom(Point point)
    {
        int x = (int) Math.Round(point.X);
        int y = (int) Math.Round(point.Y);

        // are x,y device-independent-pixels ??
        System.Drawing.Point drawingPoint = new System.Drawing.Point(x, y);
        Screen screen = System.Windows.Forms.Screen.FromPoint(drawingPoint);
        WpfScreen wpfScreen = new WpfScreen(screen);

        return wpfScreen;
    }

    public static WpfScreen Primary
    {
        get { return new WpfScreen(System.Windows.Forms.Screen.PrimaryScreen); }
    }

    private readonly Screen screen;

    internal WpfScreen(System.Windows.Forms.Screen screen)
    {
        this.screen = screen;
    }

    public Rect DeviceBounds
    {
        get { return this.GetRect(this.screen.Bounds); }
    }

    public Rect WorkingArea
    {
        get { return this.GetRect(this.screen.WorkingArea); }
    }

    private Rect GetRect(Rectangle value)
    {
        // should x, y, width, height be device-independent-pixels ??
        return new Rect
                   {
                       X = value.X,
                       Y = value.Y,
                       Width = value.Width,
                       Height = value.Height
                   };
    }

    public bool IsPrimary
    {
        get { return this.screen.Primary; }
    }

    public string DeviceName
    {
        get { return this.screen.DeviceName; }
    }
}

Дякую за цю чудову маленьку обгортку, зауважте, що глобальний :: Rect потребував перетворення на звичайний Rect, коли я використовував WPF 3.5.
Енді Дент,

1
Мені подобається це. Звичайно, для цього потрібно трохи попрацювати, але я не сподіваюся знайти 100% рішення.
джефф

4
Чудово працює. Я щойно розширив метод GetRect, щоб повернути Rect у незалежних від пристрою пікселях: private Rect GetRect (значення прямокутника) {var pixelWidthFactor = SystemParameters.WorkArea.Width / this.screen.WorkingArea.Width; var pixelHeightFactor = SystemParameters.WorkArea.Height / this.screen.WorkingArea.Height; повернути новий Rect {X = value.X * pixelWidthFactor, Y = value.Y * pixelHeightFactor, Width = value.Width * pixelWidthFactor, Height = value.Height * pixelHeightFactor}; }
Юрген Байєр

1
Я вірю, що додавання коду від @ JürgenBayer ще більше покращить вашу відповідь. У мене виникла проблема з незалежними пікселями пристрою, і код від Юргена вирішив це. Дякую вам обом.
Бруно V

3
@ Юрген: Я вважаю, що ваш метод працює лише за дуже конкретних обставин. Якщо "this.screen" має інше співвідношення сторін, ніж основний монітор (який ваш метод завжди використовує в якості посилання замість поточного монітора), ви неправильно отримаєте різні коефіцієнти масштабу для ширини та висоти, що призведе до неправильних розмірів екрана. Якщо поточний екран має іншу настройку DPI, ніж основний екран, межі будуть неправильними. У моїй системі кожне значення поверненого Rect (дико) неправильне.
Вільфорд,

27

Тут приятель. Це дасть вам лише ширину та висоту обхідного місця

System.Windows.SystemParameters.WorkArea.Width
System.Windows.SystemParameters.WorkArea.Height

13
"Отримує розмір робочої області на первинному моніторі дисплея." - не те, що я шукав ....
Нільс

10

Це дасть вам поточний екран, заснований у верхньому лівому куті вікна, просто зателефонуйте йому.CurrentScreen (), щоб отримати інформацію про поточний екран.

using System.Windows;
using System.Windows.Forms;

namespace Common.Helpers
{
    public static class WindowHelpers
     {
        public static Screen CurrentScreen(this Window window)
         {
             return Screen.FromPoint(new System.Drawing.Point((int)window.Left,(int)window.Top));
         }
     }
}

Користувач шукає розміри поточного екрана, а не основного екрана.
greggannicott

3
це повертає поточний екран на основі верхнього лівого положення вікна, з якого ви викликаєте допоміжну функцію. Але мені, мабуть, щось не вистачає на це запитання на основі оцінки моєї відповіді.
EJ

Можливо, Грегганнікотт мав намір розмістити свій коментар до однієї з інших відповідей, оскільки він абсолютно не має відношення до цієї.
Джим Балтер,

@ jim-balter Проголосував - Насправді це найкраща відповідь тут, мені знадобився екран, щоб отримати робочу область, а потім переконатися, що моє діалогове вікно не перевищує межі, я розміщу своє рішення тут. Похвала EJ за швидку точну відповідь.
Juv

^ химерний коментар.
Джим Балтер

5

Витратьте час на сканування членів SystemParameters.

  • VirtualScreenWidth
  • VirtualScreenHeight

Вони навіть враховують взаємне розташування екранів.

Тестується лише з двома моніторами.


9
dana - Я не тестував цього, але чи не повертає VirtualScreen * повний розмір усіх екранів? - Мені спеціально потрібен розмір одного екрану (того, в якому знаходиться поточне вікно).
Нільс,

1
VirtualScreen, схоже, стосується розмірів усіх екранів
Томас

1
Один мій це повернув розмір усіх 4 моїх екранів разом.
DJ van Wyk,

3

Чому б просто не використовувати це?

var interopHelper = new WindowInteropHelper(System.Windows.Application.Current.MainWindow);
var activeScreen = Screen.FromHandle(interopHelper.Handle);

Екран - це Windows.Forms, а не WPF - але це вихідна точка. Якщо ви подивитесь на рішення, яке я використовував тоді ( stackoverflow.com/a/2118993/180156 ), це саме те, що я зробив - однак я загорнувся, System.Windows.Forms.Screenщоб впоратися з незалежним від пристрою пікселем
Нільс,

3

Якщо ви знайомі з використанням класу System.Windows.Forms, ви можете просто додати посилання на клас System.Windows.Forms до свого проекту:

Провідник рішень -> Посилання -> Додати посилання ... -> (Збірки: Фреймворк) -> прокрутіть вниз і перевірте збірку System.Windows.Forms -> Добре .

Тепер ви можете додавати за допомогою System.Windows.Forms; і використовуйте екран у своєму проекті wpf так само, як і раніше.


Це, безумовно, найпростіше рішення. Цікаво - крім додавання досить великої збірки, чи є вагомі причини не робити цього таким чином?
AeonOfTime

3

Мені також знадобився поточний розмір екрана, зокрема Робоча область, який повернув прямокутник, за винятком ширини панелі завдань.

Я використав його для того, щоб змінити положення вікна, яке відкривається праворуч і вниз, де розташована миша. Оскільки вікно досить велике, у багатьох випадках воно виходило за межі екрану. Наступний код заснований на @ej відповідь: Це дасть вам поточний екран ... . Різниця полягає в тому, що я також показую свій алгоритм перепозиціонування, який, я припускаю, насправді є суттю.

Кодекс:

using System.Windows;
using System.Windows.Forms;

namespace MySample
{

    public class WindowPostion
    {
        /// <summary>
        /// This method adjust the window position to avoid from it going 
        /// out of screen bounds.
        /// </summary>
        /// <param name="topLeft">The requiered possition without its offset</param>
        /// <param name="maxSize">The max possible size of the window</param>
        /// <param name="offset">The offset of the topLeft postion</param>
        /// <param name="margin">The margin from the screen</param>
        /// <returns>The adjusted position of the window</returns>
        System.Drawing.Point Adjust(System.Drawing.Point topLeft, System.Drawing.Point maxSize, int offset, int margin)
        {
            Screen currentScreen = Screen.FromPoint(topLeft);
            System.Drawing.Rectangle rect = currentScreen.WorkingArea;

            // Set an offset from mouse position.
            topLeft.Offset(offset, offset);

            // Check if the window needs to go above the task bar, 
            // when the task bar shadows the HUD window.
            int totalHight = topLeft.Y + maxSize.Y + margin;

            if (totalHight > rect.Bottom)
            {
                topLeft.Y -= (totalHight - rect.Bottom);

                // If the screen dimensions exceed the hight of the window
                // set it just bellow the top bound.
                if (topLeft.Y < rect.Top)
                {
                    topLeft.Y = rect.Top + margin;
                }
            }

            int totalWidth = topLeft.X + maxSize.X + margin;
            // Check if the window needs to move to the left of the mouse, 
            // when the HUD exceeds the right window bounds.
            if (totalWidth > rect.Right)
            {
                // Since we already set an offset remove it and add the offset 
                // to the other side of the mouse (2x) in addition include the 
                // margin.
                topLeft.X -= (maxSize.X + (2 * offset + margin));

                // If the screen dimensions exceed the width of the window
                // don't exceed the left bound.
                if (topLeft.X < rect.Left)
                {
                    topLeft.X = rect.Left + margin;
                }
            }

            return topLeft;
        }
    }
}

Деякі пояснення:

1) topLeft - position of the top left at the desktop (works                     
   for multi screens - with different aspect ratio).                            
            Screen1              Screen2                                        
        ─  ┌───────────────────┐┌───────────────────┐ Screen3                   
        ▲  │                   ││                   │┌─────────────────┐  ─     
        │  │                   ││                   ││   ▼-            │  ▲     
   1080 │  │                   ││                   ││                 │  │     
        │  │                   ││                   ││                 │  │ 900 
        ▼  │                   ││                   ││                 │  ▼     
        ─  └──────┬─────┬──────┘└──────┬─────┬──────┘└──────┬────┬─────┘  ─     
                 ─┴─────┴─            ─┴─────┴─            ─┴────┴─             
           │◄─────────────────►││◄─────────────────►││◄───────────────►│        
                   1920                 1920                1440                
   If the mouse is in Screen3 a possible value might be:                        
   topLeft.X=4140 topLeft.Y=195                                                 
2) offset - the offset from the top left, one value for both                    
   X and Y directions.                                                          
3) maxSize - the maximal size of the window - including its                     
   size when it is expanded - from the following example                        
   we need maxSize.X = 200, maxSize.Y = 150 - To avoid the expansion            
   being out of bound.                                                          

   Non expanded window:                                                         
   ┌──────────────────────────────┐ ─                                           
   │ Window Name               [X]│ ▲                                           
   ├──────────────────────────────┤ │                                           
   │         ┌─────────────────┐  │ │ 100                                       
   │  Text1: │                 │  │ │                                           
   │         └─────────────────┘  │ │                                           
   │                         [▼]  │ ▼                                           
   └──────────────────────────────┘ ─                                           
   │◄────────────────────────────►│                                             
                 200                                                            

   Expanded window:                                                             
   ┌──────────────────────────────┐ ─                                           
   │ Window Name               [X]│ ▲                                           
   ├──────────────────────────────┤ │                                           
   │         ┌─────────────────┐  │ │                                           
   │  Text1: │                 │  │ │                                           
   │         └─────────────────┘  │ │ 150                                       
   │                         [▲]  │ │                                           
   │         ┌─────────────────┐  │ │                                           
   │  Text2: │                 │  │ │                                           
   │         └─────────────────┘  │ ▼                                           
   └──────────────────────────────┘ ─                                           
   │◄────────────────────────────►│                                             
                 200                                                            
4) margin - The distance the window should be from the screen                   
   work-area - Example:                                                          
   ┌─────────────────────────────────────────────────────────────┐ ─            
   │                                                             │ ↕ Margin     
   │                                                             │ ─            
   │                                                             │              
   │                                                             │              
   │                                                             │              
   │                          ┌──────────────────────────────┐   │              
   │                          │ Window Name               [X]│   │              
   │                          ├──────────────────────────────┤   │              
   │                          │         ┌─────────────────┐  │   │              
   │                          │  Text1: │                 │  │   │              
   │                          │         └─────────────────┘  │   │              
   │                          │                         [▲]  │   │              
   │                          │         ┌─────────────────┐  │   │              
   │                          │  Text2: │                 │  │   │              
   │                          │         └─────────────────┘  │   │              
   │                          └──────────────────────────────┘   │ ─            
   │                                                             │ ↕ Margin     
   ├──────────────────────────────────────────────────┬──────────┤ ─            
   │[start] [♠][♦][♣][♥]                              │en│ 12:00 │              
   └──────────────────────────────────────────────────┴──────────┘              
   │◄─►│                                                     │◄─►│              
    Margin                                                    Margin            

* Note that this simple algorithm will always want to leave the cursor          
  out of the window, therefor the window will jumps to its left:                
  ┌─────────────────────────────────┐        ┌─────────────────────────────────┐
  │                  ▼-┌──────────────┐      │  ┌──────────────┐▼-             │
  │                    │ Window    [X]│      │  │ Window    [X]│               │
  │                    ├──────────────┤      │  ├──────────────┤               │
  │                    │       ┌───┐  │      │  │       ┌───┐  │               │
  │                    │  Val: │   │  │ ->   │  │  Val: │   │  │               │
  │                    │       └───┘  │      │  │       └───┘  │               │
  │                    └──────────────┘      │  └──────────────┘               │
  │                                 │        │                                 │
  ├──────────────────────┬──────────┤        ├──────────────────────┬──────────┤
  │[start] [][][]     │en│ 12:00 │        │[start] [][][]     │en│ 12:00 │
  └──────────────────────┴──────────┘        └──────────────────────┴──────────┘
  If this is not a requirement, you can add a parameter to just use             
  the margin:                                                                   
  ┌─────────────────────────────────┐        ┌─────────────────────────────────┐
  │                  ▼-┌──────────────┐      │                ┌─▼-───────────┐ │
  │                    │ Window    [X]│      │                │ Window    [X]│ │
  │                    ├──────────────┤      │                ├──────────────┤ │
  │                    │       ┌───┐  │      │                │       ┌───┐  │ │
  │                    │  Val: │   │  │ ->   │                │  Val: │   │  │ │
  │                    │       └───┘  │      │                │       └───┘  │ │
  │                    └──────────────┘      │                └──────────────┘ │
  │                                 │        │                                 │
  ├──────────────────────┬──────────┤        ├──────────────────────┬──────────┤
  │[start] [][][]     │en│ 12:00 │        │[start] [][][]     │en│ 12:00 │
  └──────────────────────┴──────────┘        └──────────────────────┴──────────┘
* Supports also the following scenarios:
  1) Screen over screen:
       ┌─────────────────┐  
       │                 │
       │                 │
       │                 │
       │                 │
       └─────────────────┘
     ┌───────────────────┐ 
     │                   │ 
     │  ▼-               │ 
     │                   │ 
     │                   │ 
     │                   │ 
     └──────┬─────┬──────┘ 
           ─┴─────┴─       
  2) Window bigger than screen hight or width
     ┌─────────────────────────────────┐        ┌─────────────────────────────────┐ 
     │                                 │        │ ┌──────────────┐                │
     │                                 │        │ │ Window    [X]│                │
     │                  ▼-┌────────────│─┐      │ ├──────────────┤ ▼-             │
     │                    │ Window    [│]│      │ │       ┌───┐  │                │
     │                    ├────────────│─┤ ->   │ │  Val: │   │  │                │ 
     │                    │       ┌───┐│ │      │ │       └───┘  │                │
     │                    │  Val: │   ││ │      │ │       ┌───┐  │                │
     │                    │       └───┘│ │      │ │  Val: │   │  │                │
     ├──────────────────────┬──────────┤ │      ├──────────────────────┬──────────┤
     │[start] [♠][♦][♣]     │en│ 12:00 │ │      │[start] [♠][♦][♣]     │en│ 12:00 │
     └──────────────────────┴──────────┘ │      └──────────────────────┴──────────┘
                          │       ┌───┐  │        │       └───┘  │
                          │  Val: │   │  │        └──────────────┘
                          │       └───┘  │
                          └──────────────┘


     ┌─────────────────────────────────┐             ┌─────────────────────────────────┐     
     │                                 │             │                                 │ 
     │                                 │             │ ┌───────────────────────────────│───┐
     │    ▼-┌──────────────────────────│────────┐    │ │ W▼-dow                        │[X]│
     │      │ Window                   │     [X]│    │ ├───────────────────────────────│───┤
     │      ├──────────────────────────│────────┤    │ │       ┌───┐      ┌───┐      ┌─┤─┐ │
     │      │       ┌───┐      ┌───┐   │  ┌───┐ │ -> │ │  Val: │   │ Val: │   │ Val: │ │ │ │
     │      │  Val: │   │ Val: │   │ Va│: │   │ │    │ │       └───┘      └───┘      └─┤─┘ │
     │      │       └───┘      └───┘   │  └───┘ │    │ └───────────────────────────────│───┘
     ├──────────────────────┬──────────┤────────┘    ├──────────────────────┬──────────┤
     │[start] [♠][♦][♣]     │en│ 12:00 │             │[start] [♠][♦][♣]     │en│ 12:00 │     
     └──────────────────────┴──────────┘             └──────────────────────┴──────────┘     
  • У мене не було іншого вибору, як використання формату коду (інакше пробіли були б втрачені).
  • Спочатку це з'являлось у наведеному вище коді як <remark><code>...</code></remark>

1

Я розумію вимоги. Річ у тому, що існують методи WPF для отримання цих значень - але так, один із авторів має рацію, а не безпосередньо. Рішення полягає не в тому, щоб отримати всі ці обхідні шляхи, а в тому, щоб змінити початковий підхід відповідно до чистого проектування та розробки.

A) Встановіть для початкового головного вікна екран

B) Отримати значення для ActualWindow, включаючи масу корисних методів WPF

В) Ви можете додати скільки завгодно Windows для поведінки, яку ви хочете мати, наприклад, розміру, мінімізованого, що завгодно ... але тепер ви завжди можете отримати доступ до завантаженого та відображеного екрана

Будьте обережні з наступним прикладом, навколо є деякий Кодекс, який вимагає використання такого підходу, однак він повинен спрацювати (це дасть Вам бали за кожен з кутів екрану): Робочий приклад на одиночному Подвійний монітор та різні роздільні здатності (у класі основного головного вікна):

InitializeComponent();
[…]
ActualWindow.AddHandler(Window.LoadedEvent, new RoutedEventHandler(StartUpScreenLoaded));

Маршрут події:

private void StartUpScreenLoaded(object sender, RoutedEventArgs e)
    {
        Window StartUpScreen = sender as Window;

        // Dispatcher Format B:
        Dispatcher.Invoke(new Action(() =>
        {
            // Get Actual Window on Loaded
            StartUpScreen.InvalidateVisual();
            System.Windows.Point CoordinatesTopRight = StartUpScreen.TranslatePoint(new System.Windows.Point((StartUpScreen.ActualWidth), (0d)), ActualWindow);
            System.Windows.Point CoordinatesBottomRight = StartUpScreen.TranslatePoint(new System.Windows.Point((StartUpScreen.ActualWidth), (StartUpScreen.ActualHeight)), ActualWindow);
            System.Windows.Point CoordinatesBottomLeft = StartUpScreen.TranslatePoint(new System.Windows.Point((0d), (StartUpScreen.ActualHeight)), ActualWindow);

            // Set the Canvas Top Right, Bottom Right, Bottom Left Coordinates
            System.Windows.Application.Current.Resources["StartUpScreenPointTopRight"] = CoordinatesTopRight;
            System.Windows.Application.Current.Resources["StartUpScreenPointBottomRight"] = CoordinatesBottomRight;
            System.Windows.Application.Current.Resources["StartUpScreenPointBottomLeft"] = CoordinatesBottomLeft;
        }), DispatcherPriority.Loaded);
    }

1

Якщо ви використовуєте будь-яке повноекранне вікно (яке має його WindowState = WindowState.Maximized, WindowStyle = WindowStyle.None), ви можете обернути його вміст System.Windows.Controls.Canvasтаким чином:

<Canvas Name="MyCanvas" Width="auto" Height="auto">
...
</Canvas>

Тоді ви можете використовувати MyCanvas.ActualWidthі MyCanvas.ActualHeightдля отримання роздільної здатності поточного екрану, враховуючи налаштування DPI та в незалежних від пристрою пристроях. Він не додає полів, як це робить розгорнене вікно.

(Canvas приймає UIElements як дітей, тому ви зможете використовувати його з будь-яким вмістом.)


0

Центрувати вікно на екрані в XAML, WindowStartupLocation="CenterOwner"а потім викликати в WindowLoaded ()

double ScreenHeight = 2 * (Top + 0.5 * Height);


-4
double screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
double screenhight= System.Windows.SystemParameters.PrimaryScreenHeight;

4
Як і попередня відповідь, це стосується лише основного екрана. Мені потрібен був поточний екран.
Нільс,

-4

Це працює з

this.Width = System.Windows.SystemParameters.VirtualScreenWidth;
this.Height = System.Windows.SystemParameters.VirtualScreenHeight;

Перевірено на 2 моніторах.


якщо ви подивитесь на відповідь від 18 травня '10 о 15:52 - яка точно відповідала вашій, ви побачите, що VirtualScreenохоплює всі екрани - так що це ніколи не спрацює, якщо у вас більше одного екрана!
Нільс,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.