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

时间:2009-12-18 11:02:16

标签: c# wpf xaml size screen

我知道我可以使用

获得主屏幕的大小
System.Windows.SystemParameters.PrimaryScreenWidth;
System.Windows.SystemParameters.PrimaryScreenHeight;

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

能够从XAML访问大小会很好,但是从代码(C#)这样做就足够了。

15 个答案:

答案 0 :(得分:68)

我在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; }
    }
}

答案 1 :(得分:18)

这里是布迪。这将只给出工作区的宽度和高度

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

答案 2 :(得分:12)

据我所知,没有本地WPF功能来获取当前监视器的尺寸。相反,你可以PInvoke本机multiple display monitors functions,将它们包装在托管类中,并公开你需要从XAML中使用它们的所有属性。

答案 3 :(得分:6)

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

答案 4 :(得分:5)

花些时间浏览SystemParameters成员。

  • VirtualScreenWidth
  • VirtualScreenHeight

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

仅使用两台显示器进行测试。

答案 5 :(得分:3)

我还需要当前的屏幕尺寸,特别是工作区域,该尺寸返回不包括任务栏宽度的矩形。

我用它来重新放置一个窗口,该窗口向右下方打开到鼠标所在的位置。由于窗口很大,因此在许多情况下,它超出了屏幕范围。以下代码基于@ e-j答案:This will give you the current screen...。区别在于,我还展示了我的重新定位算法,我认为这实际上就是重点。

代码:

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>

答案 6 :(得分:2)

如果您熟悉使用 System.Windows.Forms 类,那么您只需将System.Windows.Forms类的引用添加到项目中:

解决方案资源管理器 - &gt; 参考文献 - &gt; 添加引用... - &gt; (大会:框架) - &gt;向下滚动并检查 System.Windows.Forms 程序集 - &gt;的确定

现在您可以像以前一样在wpf项目中添加使用System.Windows.Forms; 语句和使用屏幕。

答案 7 :(得分:1)

为什么不直接使用它?

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

答案 8 :(得分:1)

如果您使用任何全屏窗口(具有其@Override public void actionPerformed (ActionEvent e){ ),则可以将其内容包装在WindowState = WindowState.Maximized, WindowStyle = WindowStyle.None中,如下所示:

System.Windows.Controls.Canvas

然后,您可以使用<Canvas Name="MyCanvas" Width="auto" Height="auto"> ... </Canvas> MyCanvas.ActualWidth来获得当前屏幕的分辨率,同时考虑DPI设置并以设备独立单位为单位。 它不会像最大化窗口本身那样增加任何边距。

(Canvas接受MyCanvas.ActualHeight作为孩子,因此您应该可以将其与任何内容一起使用。)

答案 9 :(得分:1)

我偶然发现了这篇文章,发现没有一个答案能完全体现我想要做的事情。我有一台分辨率为 3840x2160 的笔记本电脑和两台分辨率为 1920x1080 的显示器。为了在我的 WPF 应用程序中获得正确的监视器大小,我必须make the application DPI aware。然后我使用 Win32 API 来获取显示器大小。

我首先将窗口移动到我想要从中获取大小的监视器。然后通过获取应用程序 MainWindow 的 hwnd(不必是主窗口,但我的应用程序只有一个窗口)和一个 IntPtr 到监视器。然后我创建了 MONITORINFOEX 结构的一个新实例并调用了 GetMonitorInfo 方法。

MONITORINFOEX 结构具有工作区和屏幕的全分辨率,因此您可以返回任何您需要的。这也将允许您省略对 System.Windows.Forms 的引用(假设您的应用程序中不需要它的其他内容)。我使用 .NET Framework Reference Source for System.Windows.Forms.Screen 想出了这个解决方案。

public System.Drawing.Size GetMonitorSize()
{
    var window = System.Windows.Application.Current.MainWindow;
    var hwnd = new WindowInteropHelper(window).EnsureHandle();
    var monitor = NativeMethods.MonitorFromWindow(hwnd, NativeMethods.MONITOR_DEFAULTTONEAREST);
    NativeMethods.MONITORINFO info = new NativeMethods.MONITORINFO();
    NativeMethods.GetMonitorInfo(new HandleRef(null, monitor), info);
    return info.rcMonitor.Size;
}

internal static class NativeMethods
{
    public const Int32 MONITOR_DEFAULTTONEAREST = 0x00000002;

    [DllImport("user32.dll")]
    public static extern IntPtr MonitorFromWindow(IntPtr handle, Int32 flags);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern bool GetMonitorInfo(HandleRef hmonitor, MONITORINFO info);
    
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
    public class MONITORINFO
    {
        internal int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
        internal RECT rcMonitor = new RECT();
        internal RECT rcWork = new RECT();
        internal int dwFlags = 0;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;

        public RECT(int left, int top, int right, int bottom)
        {
            this.left = left;
            this.top = top;
            this.right = right;
            this.bottom = bottom;
        }

        public RECT(System.Drawing.Rectangle r)
        {
            left = r.Left;
            top = r.Top;
            right = r.Right;
            bottom = r.Bottom;
        }

        public static RECT FromXYWH(int x, int y, int width, int height) => new RECT(x, y, x + width, y + height);

        public System.Drawing.Size Size => new System.Drawing.Size(right - left, bottom - top);
    }
}

答案 10 :(得分:0)

我了解需求。 关键是,有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);
    }

答案 11 :(得分:0)

使用XAML WindowStartupLocation="CenterOwner"在屏幕上居中放置一个窗口,然后在WindowLoaded()中调用

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

答案 12 :(得分:0)

我很欣赏这是一个老问题,但鉴于 WPF 仍然没有提供一种“开箱即用”的好方法,而且上述答案似乎有点过于复杂,希望您能在下面找到解决方案更容易消化..

  • WPF 友好,即返回与设备无关的单位(不是 WinForm 样式像素)
  • 支持不同 DPI 的显示器
  • 适合任何大小/位置的任务栏
  • System.Windows.Window 上的扩展方法。

享受:)

using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
using Point = System.Drawing.Point;

namespace ClrVpin.Shared
{
    public static class WindowExtensions
    {
        public static Rect GetCurrentScreenWorkArea(this Window window)
        {
            var screen = Screen.FromPoint(new Point((int) window.Left, (int) window.Top));
            var dpiScale = VisualTreeHelper.GetDpi(window);

            return new Rect {Width = screen.WorkingArea.Width / dpiScale.DpiScaleX, Height = screen.WorkingArea.Height / dpiScale.DpiScaleY};
        }
    }
}

答案 13 :(得分:-3)

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

答案 14 :(得分:-4)

适用于

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

在2台显示器上测试。