WPF'de mevcut ekranın boyutu nasıl alınır?


90

Kullanarak birincil ekranın boyutunu alabileceğimi biliyorum

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

Ama mevcut ekranın boyutunu nasıl elde ederim? (Çoklu Ekran kullanıcıları her zaman birincil ekranı kullanmazlar ve tüm ekranlar aynı çözünürlüğü kullanmaz, değil mi?)

Boyuta XAML'den erişebilmek güzel olurdu, ancak bunu koddan (C #) yapmak yeterli olacaktır.


1
"Akımı" tanımlayın. Bir pencere aynı anda birden fazla ekranda olabilir.
Jim Balter

Yanıtlar:


15

Bildiğim kadarıyla, mevcut monitörün boyutlarını almak için yerel bir WPF işlevi yok. Bunun yerine, yerel birden çok görüntü izleme işlevini PInvoke edebilir , bunları yönetilen sınıfa sarabilir ve XAML'den kullanmanız gereken tüm özellikleri açığa çıkarabilirsiniz.


Tam olarak korktuğum şey buydu - öğeleri P / Invoke etme veya bir şekilde System.Windows.Forms.Screen'e erişme ihtiyacı. Ve bunu yaparken her zaman "cihazdan bağımsız pikselleri" hesaplamam gerekir ... Yine de teşekkürler.
Nils

Evet ... Belki SystemParameters.ConvertPixel () işlevi de size yardımcı olacaktır. Dahili, ama Reflektör umursamıyor
:)

76

System.Windows.Forms'tan Screen etrafında küçük bir sarmalayıcı oluşturdum, şu anda her şey çalışıyor ... Yine de "aygıttan bağımsız pikseller" hakkında emin değilim.

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

Bu harika küçük paketleyici için teşekkürler, WPF 3.5 ile kullandığımda global :: Rect'in sadece düz Rect'e dönüştürülmesi gerektiğini unutmayın.
Andy Dent

1
Bunu severim. Elbette biraz çalışılması gerekiyor, ancak% 100 çözüm bulmayı beklemiyorum.
jeff

4
Harika çalışıyor. Rect'i cihazdan bağımsız piksellerde döndürmek için GetRect yöntemini genişlettim: private Rect GetRect (Rectangle değeri) {var pixelWidthFactor = SystemParameters.WorkArea.Width / this.screen.WorkingArea.Width; var pixelHeightFactor = SystemParameters.WorkArea.Height / this.screen.WorkingArea.Height; yeni Rect {X = value.X * pixelWidthFactor, Y = value.Y * pixelHeightFactor, Width = value.Width * pixelWidthFactor, Height = value.Height * pixelHeightFactor}; }
Jürgen Bayer

1
@ JürgenBayer'dan kod eklemenin cevabınızı daha da iyileştireceğine inanıyorum. Cihazdan bağımsız piksellerle ilgili sorunu yaşadım ve Jürgen'in kodu sorunu çözdü. İkinize de teşekkürler.
Bruno V

3
@ Jürgen: Yönteminizin yalnızca çok özel koşullarda işe yaradığına inanıyorum. "This.screen" birincil monitörden farklı bir en boy oranına sahipse (yönteminiz her zaman mevcut monitör yerine referans olarak kullanır), genişlik ve yükseklik için hatalı şekilde farklı ölçek faktörleri alırsınız ve bu da yanlış ekran boyutlarına neden olur. Mevcut ekranın birincil ekrandan farklı bir DPI ayarı varsa, sınırlar tamamen yanlış olacaktır. Sistemimde, döndürülen Rect'in her bir değeri (çılgınca) yanlış.
wilford

27

İşte dostum. Bu size yalnızca çalışma alanının genişliğini ve yüksekliğini verecektir

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

13
"Birincil görüntü monitöründeki çalışma alanının boyutunu alır." - aradığım şey değil ....
Nils

12

Bu size pencerenin sol üst köşesine dayalı mevcut ekranı verecektir, sadece mevcut ekran hakkında bilgi almak için this.CurrentScreen () 'i çağırın.

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

Kullanıcı, birincil ekran yerine mevcut ekranın boyutlarını arıyor.
greggannicott

3
bu, yardımcı işlevi çağırdığınız pencerenin sol üst konumuna bağlı olarak geçerli ekranı döndürür. Ancak cevabımın puanına göre bu soruda bir şey kaçırıyor olmalıyım.
EJ

Belki de greggannicott, bu yanıtla tamamen alakasız olduğu için yorumunu diğer yanıtlardan birine göndermek istemiştir.
Jim Balter

@ jim-balter Oy Verildi - Aslında buradaki en iyi cevap bu, çalışma alanını elde etmek için Ekrana ihtiyacım vardı ve ardından diyaloğumun sınırı aşmadığından emin ol, çözümümü burada yayınlayacağım. Hızlı cevap için EJ'ye şeref.
Cuv

^ tuhaf yorum.
Jim Balter

4

Ayrıca mevcut ekran boyutuna, özellikle de Görev Çubuğu genişliğini hariç tutan dikdörtgeni döndüren Çalışma alanına ihtiyacım vardı.

Sağa ve aşağıya doğru açılan bir pencereyi farenin bulunduğu yere yeniden konumlandırmak için kullandım. Pencere oldukça büyük olduğu için çoğu durumda ekran sınırlarının dışına çıktı. Aşağıdaki kod @ej cevap dayanmaktadır: Bu, geçerli ekran verecek ... . Aradaki fark, aslında asıl mesele olduğunu düşündüğüm yeniden konumlandırma algoritmamı da göstermem.

Kod:

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

Bazı açıklamalar:

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 │     
     └──────────────────────┴──────────┘             └──────────────────────┴──────────┘     
  • Kod formatını kullanmaktan başka seçeneğim yoktu (aksi takdirde beyaz boşluklar kaybolurdu).
  • Başlangıçta bu, yukarıdaki kodda bir <remark><code>...</code></remark>

4

SystemParameters üyelerini taramak için zaman ayırın.

  • VirtualScreenWidth
  • VirtualScreenHeight

Bunlar, ekranların göreceli konumlarını bile hesaba katıyor.

Yalnızca iki monitörle test edilmiştir.


9
dana - Bunu test etmedim, ancak VirtualScreen * tüm ekranların tam boyutunu döndürmüyor mu? - Özellikle bir ekranın boyutuna ihtiyacım var (mevcut pencerenin bulunduğu ekran).
Nils

1
VirtualScreen tüm ekranların boyutuna atıfta bulunuyor gibi görünüyor
Thomas

1
Bir mayın bu, toplam 4 ekranımın boyutunu döndürdü.
DJ van Wyk

3

Neden bunu kullanmıyorsun?

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

Ekran WPF yerine Windows.Forms'tur - ancak bu bir başlangıç ​​noktasıdır. O zamanlar kullandığım çözüme bakarsanız ( stackoverflow.com/a/2118993/180156 ) tam olarak yaptığım şey buydu - ancak System.Windows.Forms.Screencihazdan bağımsız pikselle başa çıkmak için
Nils

3

System.Windows.Forms sınıfını kullanmaya aşina iseniz, o zaman projenize System.Windows.Forms sınıfının bir başvurusunu ekleyebilirsiniz :

Solution Explorer -> Referanslar -> Referans Ekle ... -> (Montajlar: Çerçeve) -> aşağı kaydırın ve System.Windows.Forms montajını kontrol edin -> Tamam .

Şimdi System.Windows.Forms kullanarak ekleyebilirsiniz ; wpf projenizde daha önce olduğu gibi ifadesi ve ekranı kullanın.


Bu, açık ara en kolay çözümdür. Merak ediyorum - oldukça büyük bir montaj eklemenin dışında, bunu bu şekilde yapmamak için herhangi bir iyi sebep var mı?
AeonOfTime

1

Talepleri anlıyorum. Mesele şu ki, bu değerleri elde etmek için WPF Yöntemleri var - ama evet, katkıda bulunanlardan biri haklı, doğrudan değil. Çözüm, tüm bu geçici çözümleri elde etmek değil, ilk yaklaşımı temiz Tasarım ve Geliştirmeye göre değiştirmektir.

A) İlk Ana Pencereyi Ekrana Ayarlayın

B) Bir ton kullanışlı WPF Yöntemini içeren ActualWindow için Değerleri Alın

C) Yeniden boyutlandırılabilir, simge durumuna küçültülmüş gibi sahip olmak istediğiniz davranış için istediğiniz kadar Windows ekleyebilirsiniz… ancak artık her zaman Yüklenen ve Oluşturulan Ekrana erişebilirsiniz

Lütfen aşağıdaki örneğe dikkat edin, etrafta bu tür bir yaklaşımı kullanmayı gerekli kılan bazı Kurallar vardır, ancak işe yaraması gerekir (Size Ekranınızın her bir Köşesi için Puanlar verecektir): Tekli Çalışma Örneği, Çift Monitör ve farklı Çözünürlükler (Primal Ana Pencere Sınıfı İçinde):

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

Yönlendirilmiş Olay:

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

Herhangi bir tam ekran pencere kullanıyorsanız (bu pencereye sahip WindowState = WindowState.Maximized, WindowStyle = WindowStyle.None), içeriğini şu şekilde kaydırabilirsiniz System.Windows.Controls.Canvas:

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

Daha sonra göz önünde bulundurulan DPI ayarları ile ve cihazdan bağımsız birimlerde mevcut ekranın çözünürlüğünü kullanabilir MyCanvas.ActualWidthve MyCanvas.ActualHeightalabilirsiniz. Büyütülmüş pencerenin yaptığı gibi herhangi bir kenar boşluğu eklemez.

(Canvas, UIElemente-postaları çocuk olarak kabul eder , bu nedenle herhangi bir içerikle kullanabilmeniz gerekir.)


0

WindowStartupLocation="CenterOwner"XAML'de ekranda Pencereyi ortalayın ve ardından WindowLoaded () 'da arayın

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


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

4
Önceki cevap gibi bu sadece birincil Ekran içindir. Mevcut ekrana ihtiyacım vardı .
Nils

-4

İle çalışır

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

2 monitörde test edilmiştir.


18 Mayıs 2010 15:52 cevabına bakarsanız - ki bu sizinki ile tamamen aynıydı VirtualScreen- tüm ekranlara yayıldığını göreceksiniz - yani birden fazla ekranınız varsa bu asla çalışmayacaktır!
Nils
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.