如何在WPF中获取当前屏幕的大小?


87

我知道我可以通过使用获得主屏幕的大小

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

但是,如何获取当前屏幕的大小?(多屏幕用户并不总是使用主屏幕,并且并非所有屏幕都使用相同的分辨率,对吗?)

能够从XAML访问大小很好,但是从代码(C#)进行访问就足够了。


1
定义“当前”。一个窗口可以一次显示在多个屏幕上。
吉姆·巴尔特

Answers:


13

据我所知,没有本机WPF函数来获取当前监视器的尺寸。相反,您可以PInvoke本机多个显示监视器功能,将它们包装在托管类中,并公开从XAML使用它们所需的所有属性。


这正是我所担心的-需要P / Invoke东西或以某种方式访问​​System.Windows.Forms.Screen。而且在这样做时,我总是需要计算“与设备无关的像素”……不过,谢谢。
尼尔斯

是的...也许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; }
    }
}

感谢这个很棒的小包装程序,请注意,当我与WPF 3.5一起使用时,需要将global :: Rect转换为纯Rect。
Andy Dent 2010年

1
我喜欢这个。当然,这需要一些工作,但我不希望找到100%的解决方案。
jeff,2015年

4
效果很好。我只是扩展了GetRect方法,以使用独立于设备的像素返回Rect:私有Rect GetRect(Rectangle value){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中的代码将进一步改善您的答案。我遇到了与设备无关的像素的问题,Jürgen的代码解决了这个问题。谢谢你们俩。
布鲁诺五世

3
@Jürgen:我相信您的方法仅在非常特殊的情况下有效。如果“ this.screen”的纵横比与主监视器(您的方法始终将其用作参考而不是当前监视器)不同,则您将错误地获得不同的宽度和高度比例因子,从而导致屏幕尺寸错误。如果当前屏幕的DPI设置与主屏幕不同,则边界将全部错误。在我的系统上,返回的Rect的每个单个值都是(完全)错误的。
威尔福德


10

这将基于窗口的左上角为您提供当前屏幕,只需调用this.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 2014年

3
这会根据您从中调用辅助函数的窗口的左上位置返回当前屏幕。但是,根据我的回答得分,我一定会对此问题有所遗漏。
EJ 2016年

也许greggannicott打算将他的评论发布到其他答案之一,因为它与这一答案完全无关。
吉姆·巴尔特

@ jim-balter投票-实际上,这是最好的答案,我需要屏幕以获取工作区域,然后确保我的对话框没有超出限制,我将在此处发布解决方案。对EJ表示感谢,以快速找到答案。
7

^奇怪的评论。
Jim Balter

5

花点时间浏览SystemParameters成员。

  • VirtualScreenWidth
  • VirtualScreenHeight

这些甚至考虑到屏幕的相对位置。

仅在两个监视器上进行过测试。


9
dana-我还没有测试过,但是VirtualScreen *不会返回所有屏幕的完整尺寸吗?-我特别需要一个屏幕的大小(当前窗口所在的屏幕)。
尼尔斯2010年

1
VirtualScreen似乎指的是所有屏幕的大小
Thomas

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以应对与设备无关的像素
Nils

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方法

C)您可以根据需要添加任意数量的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.ActualWidthMyCanvas.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个显示器上测试。


如果您查看的是2010年5月18日15:52的答案-与您的答案完全相同,您会看到它VirtualScreen涵盖了所有屏幕-因此,如果您有多个屏幕,这将永远无效!
尼尔斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.