Como posso obter as dimensões da tela ativa?


142

O que estou procurando é o equivalente a System.Windows.SystemParameters.WorkArea ao monitor em que a janela está atualmente.

Esclarecimento: A janela em questão é WPF, não WinForm.


2
Alteração da resposta aceita para refletir a melhor maneira de fazer isso no WPF. System.Windows.SystemParameters. *
— chilltemp

1
A obsessão por não usar um espaço para nome WinForms parece estranha para mim, não ganha nada; em vez disso, deixa você sem as ferramentas necessárias para resolver adequadamente o problema.
— Jeff Yates

4
Para mim, não se trata de WinForms vs. WPF. É sobre aprender algo novo. Não consigo decidir qual caminho é melhor se não aprender dos dois lados.
— Chilltemp # 3/10

3
Bem, nesse cenário, não há "nos dois sentidos", pois há apenas uma maneira de fazer isso, que é usar o material WinForms.
— Jeff Yates

@ Jeff Yates: Você está correto. Desenterrei o projeto original para o qual fiz essa pergunta e descobri que usava as propriedades PrimaryScreen *. Eles resolveram minhas necessidades do dia, mas não a pergunta real que eu fiz. Desculpe pelo desvio; Alterei a resposta aceita de acordo.
— Chilltemp

Respostas:


143

Screen.FromControl, Screen.FromPointE Screen.FromRectangledeve ajudá-lo com isso. Por exemplo, no WinForms, seria:

class MyForm : Form
{
  public Rectangle GetScreen()
  {
    return Screen.FromControl(this).Bounds;
  }
}

Não conheço uma chamada equivalente para WPF. Portanto, você precisa fazer algo como este método de extensão.

static class ExtensionsForWPF
{
  public static System.Windows.Forms.Screen GetScreen(this Window window)
  {
    return System.Windows.Forms.Screen.FromHandle(new WindowInteropHelper(window).Handle);
  }
}

1
Talvez minha marcação não tenha deixado claro que estou usando janelas WPF, não WinForms. Eu não tenho o System.Windows.Forms.dll mencionado e não funcionaria de qualquer maneira, pois o WPF tem sua própria árvore de herança.
— Chilltemp 31/10/08

1
De nada. Peço desculpas por não ter chegado diretamente à resposta - tive que investigar o que estava disponível no WPF antes de atualizar minha postagem.
— Jeff Yates

Isso funciona para colocar uma janela na borda direita: var bounds = this.GetScreen (). WorkingArea; this.Left = bounds.Right - this.Width; Mas requer referências a System.Windows.Forms e System.Drawing, o que não é o ideal.
— Anthony

1
@evios Cuidado que esta chamada não reconhece DPI; você precisará fazer cálculos.
— precisa

6
No meu aplicativo VS 2015 WPF direcionado ao .NET 4.5 no meu sistema de 4 monitores no Windows 10 Pro (v10.0.14393) com windowno monitor acima do meu primário (por exemplo, seu Top < 0), FromHandleretornei o Screendo meu monitor primário (mesmo que windowestivesse completamente dentro o monitor secundário)!?! Suspiro. Parece que vou ter que procurar no Screen.AllScreensArray sozinho. Por que as coisas não podem "simplesmente funcionar"?!? Arrrrgh.
— Tom

62

Você pode usar isso para obter os limites do espaço de trabalho da área de trabalho da tela principal:

System.Windows.SystemParameters.WorkArea

Isso também é útil para obter apenas o tamanho da tela principal:

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


19
Estou confuso ... Isso parece retornar apenas as dimensões da tela principal. Eu quero saber as dimensões da tela da janela está atualmente em ...
— VitalyB

1
isso não responde à pergunta e, mesmo que você queira apenas obter o tamanho da exibição principal, os SystemParameters (no WPF) estão incorretos. eles retornam unidades independentes de dispositivo e não pixels. para uma melhor implementação ver esta resposta: stackoverflow.com/questions/254197/...
— Patrick Klug

1
PrimaryScreenHeight / Width funcionou exatamente como o esperado e o MSDN possui o seguinte: "Obtém um valor que indica a altura da tela, em pixels, do monitor principal". A WorkArea não diz especificamente pixels, mas a documentação e os exemplos de uso me levam a acreditar que também está em pixels. Você tem um link para algo que indica o uso de unidades independentes de dispositivo?
— Chilltemp # 3/10


17

Adicionando uma solução que não usa WinForms, mas NativeMethods. Primeiro, você precisa definir os métodos nativos necessários.

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


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


    [DllImport( "user32.dll" )]
    public static extern Boolean GetMonitorInfo( IntPtr hMonitor, NativeMonitorInfo lpmi );


    [Serializable, StructLayout( LayoutKind.Sequential )]
    public struct NativeRectangle
    {
        public Int32 Left;
        public Int32 Top;
        public Int32 Right;
        public Int32 Bottom;


        public NativeRectangle( Int32 left, Int32 top, Int32 right, Int32 bottom )
        {
            this.Left = left;
            this.Top = top;
            this.Right = right;
            this.Bottom = bottom;
        }
    }


    [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Auto )]
    public sealed class NativeMonitorInfo
    {
        public Int32 Size = Marshal.SizeOf( typeof( NativeMonitorInfo ) );
        public NativeRectangle Monitor;
        public NativeRectangle Work;
        public Int32 Flags;
    }
}

E, em seguida, obtenha a alça do monitor e as informações do monitor assim.

        var hwnd = new WindowInteropHelper( this ).EnsureHandle();
        var monitor = NativeMethods.MonitorFromWindow( hwnd, NativeMethods.MONITOR_DEFAULTTONEAREST );

        if ( monitor != IntPtr.Zero )
        {
            var monitorInfo = new NativeMonitorInfo();
            NativeMethods.GetMonitorInfo( monitor, monitorInfo );

            var left = monitorInfo.Monitor.Left;
            var top = monitorInfo.Monitor.Top;
            var width = ( monitorInfo.Monitor.Right - monitorInfo.Monitor.Left );
            var height = ( monitorInfo.Monitor.Bottom - monitorInfo.Monitor.Top );
        }

1
Você consegue o tamanho real da tela se houver fator de escala de suas janelas (100% / 125% / 150% / 200%)?
— Kiquenet 23/07/19


12

Cuidado com o fator de escala de suas janelas (100% / 125% / 150% / 200%). Você pode obter o tamanho real da tela usando o seguinte código:

SystemParameters.FullPrimaryScreenHeight
SystemParameters.FullPrimaryScreenWidth

1
Isso é para a tela principal - e se a janela do aplicativo estiver em uma tela virtual (estendida) (por exemplo, se você tiver um ou dois monitores externos conectados ao seu PC)?
— Matt

4

Eu queria ter a resolução da tela antes de abrir a primeira das minhas janelas, então aqui está uma solução rápida para abrir uma janela invisível antes de realmente medir as dimensões da tela (você precisa adaptar os parâmetros da janela à sua janela para garantir que ambos estejam abertos em a mesma tela - principalmente a WindowStartupLocationé importante)

Window w = new Window();
w.ResizeMode = ResizeMode.NoResize;
w.WindowState = WindowState.Normal;
w.WindowStyle = WindowStyle.None;
w.Background = Brushes.Transparent;
w.Width = 0;
w.Height = 0;
w.AllowsTransparency = true;
w.IsHitTestVisible = false;
w.WindowStartupLocation = WindowStartupLocation.Manual;
w.Show();
Screen scr = Screen.FromHandle(new WindowInteropHelper(w).Handle);
w.Close();

3

Esta é uma " solução Center Screen DotNet 4.5 ", usando SystemParameters em vez de System.Windows.Forms ou My.Compuer.Screen : Como o Windows 8 alterou o cálculo da dimensão da tela, a única maneira de funcionar para mim é assim (cálculo da barra de tarefas incluído):

Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    Dim BarWidth As Double = SystemParameters.VirtualScreenWidth - SystemParameters.WorkArea.Width
    Dim BarHeight As Double = SystemParameters.VirtualScreenHeight - SystemParameters.WorkArea.Height
    Me.Left = (SystemParameters.VirtualScreenWidth - Me.ActualWidth - BarWidth) / 2
    Me.Top = (SystemParameters.VirtualScreenHeight - Me.ActualHeight - BarHeight) / 2         
End Sub

Tela central WPF XAML


instalação do instalador no WPF?
— Kiquenet 23/07/19

A principal questão é sobre a posição da tela. Como o instalador Msi, Innosetup ou outros, criei meu próprio instalador com verificação de CPU, verificação de permissão, verificação de driver e muito mais, muito simples de usar. Essa é a captura de tela sobre.
— Nasenbaer

3

Eu precisava definir o tamanho máximo do meu aplicativo de janela. Este pode ser alterado de acordo com a aplicação apresentada na tela principal ou na secundária. Para superar esse problema, criamos um método simples que mostrarei a seguir:

/// <summary>
/// Set the max size of the application window taking into account the current monitor
/// </summary>
public static void SetMaxSizeWindow(ioConnect _receiver)
{
    Point absoluteScreenPos = _receiver.PointToScreen(Mouse.GetPosition(_receiver));

    if (System.Windows.SystemParameters.VirtualScreenLeft == System.Windows.SystemParameters.WorkArea.Left)
    {
        //Primary Monitor is on the Left
        if (absoluteScreenPos.X <= System.Windows.SystemParameters.PrimaryScreenWidth)
        {
            //Primary monitor
            _receiver.WindowApplication.MaxWidth = System.Windows.SystemParameters.WorkArea.Width;
            _receiver.WindowApplication.MaxHeight = System.Windows.SystemParameters.WorkArea.Height;
        }
        else
        {
            //Secondary monitor
            _receiver.WindowApplication.MaxWidth = System.Windows.SystemParameters.VirtualScreenWidth - System.Windows.SystemParameters.WorkArea.Width;
            _receiver.WindowApplication.MaxHeight = System.Windows.SystemParameters.VirtualScreenHeight;
        }
    }

    if (System.Windows.SystemParameters.VirtualScreenLeft < 0)
    {
        //Primary Monitor is on the Right
        if (absoluteScreenPos.X > 0)
        {
            //Primary monitor
            _receiver.WindowApplication.MaxWidth = System.Windows.SystemParameters.WorkArea.Width;
            _receiver.WindowApplication.MaxHeight = System.Windows.SystemParameters.WorkArea.Height;
        }
        else
        {
            //Secondary monitor
            _receiver.WindowApplication.MaxWidth = System.Windows.SystemParameters.VirtualScreenWidth - System.Windows.SystemParameters.WorkArea.Width;
            _receiver.WindowApplication.MaxHeight = System.Windows.SystemParameters.VirtualScreenHeight;
        }
    }
}

1

no winforms C #, tenho o ponto de partida (por exemplo, quando temos vários monitor / diplay e um formulário está chamando outro) com a ajuda do seguinte método:

private Point get_start_point()
    {
        return
            new Point(Screen.GetBounds(parent_class_with_form.ActiveForm).X,
                      Screen.GetBounds(parent_class_with_form.ActiveForm).Y
                      );
    }

1

WinForms

Para configurações de vários monitores, você também precisará ter em conta a posição X e Y:

Rectangle activeScreenDimensions = Screen.FromControl(this).Bounds;
this.Size = new Size(activeScreenDimensions.Width + activeScreenDimensions.X, activeScreenDimensions.Height + activeScreenDimensions.Y);

0

Este código de depuração deve executar bem o truque:

Você pode explorar as propriedades da classe Screen

Coloque todas as exibições em uma matriz ou lista usando Screen.AllScreens e capture o índice da exibição atual e suas propriedades.

insira a descrição da imagem aqui

C # (convertido de VB por Telerik - verifique novamente)

        {
    List<Screen> arrAvailableDisplays = new List<Screen>();
    List<string> arrDisplayNames = new List<string>();

    foreach (Screen Display in Screen.AllScreens)
    {
        arrAvailableDisplays.Add(Display);
        arrDisplayNames.Add(Display.DeviceName);
    }

    Screen scrCurrentDisplayInfo = Screen.FromControl(this);
    string strDeviceName = Screen.FromControl(this).DeviceName;
    int idxDevice = arrDisplayNames.IndexOf(strDeviceName);

    MessageBox.Show(this, "Number of Displays Found: " + arrAvailableDisplays.Count.ToString() + Constants.vbCrLf + "ID: " + idxDevice.ToString() + Constants.vbCrLf + "Device Name: " + scrCurrentDisplayInfo.DeviceName.ToString + Constants.vbCrLf + "Primary: " + scrCurrentDisplayInfo.Primary.ToString + Constants.vbCrLf + "Bounds: " + scrCurrentDisplayInfo.Bounds.ToString + Constants.vbCrLf + "Working Area: " + scrCurrentDisplayInfo.WorkingArea.ToString + Constants.vbCrLf + "Bits per Pixel: " + scrCurrentDisplayInfo.BitsPerPixel.ToString + Constants.vbCrLf + "Width: " + scrCurrentDisplayInfo.Bounds.Width.ToString + Constants.vbCrLf + "Height: " + scrCurrentDisplayInfo.Bounds.Height.ToString + Constants.vbCrLf + "Work Area Width: " + scrCurrentDisplayInfo.WorkingArea.Width.ToString + Constants.vbCrLf + "Work Area Height: " + scrCurrentDisplayInfo.WorkingArea.Height.ToString, "Current Info for Display '" + scrCurrentDisplayInfo.DeviceName.ToString + "' - ID: " + idxDevice.ToString(), MessageBoxButtons.OK, MessageBoxIcon.Information);
}

VB (código original)

 Dim arrAvailableDisplays As New List(Of Screen)()
    Dim arrDisplayNames As New List(Of String)()

    For Each Display As Screen In Screen.AllScreens
        arrAvailableDisplays.Add(Display)
        arrDisplayNames.Add(Display.DeviceName)
    Next

    Dim scrCurrentDisplayInfo As Screen = Screen.FromControl(Me)
    Dim strDeviceName As String = Screen.FromControl(Me).DeviceName
    Dim idxDevice As Integer = arrDisplayNames.IndexOf(strDeviceName)

    MessageBox.Show(Me,
                    "Number of Displays Found: " + arrAvailableDisplays.Count.ToString & vbCrLf &
                    "ID: " & idxDevice.ToString + vbCrLf &
                    "Device Name: " & scrCurrentDisplayInfo.DeviceName.ToString + vbCrLf &
                    "Primary: " & scrCurrentDisplayInfo.Primary.ToString + vbCrLf &
                    "Bounds: " & scrCurrentDisplayInfo.Bounds.ToString + vbCrLf &
                    "Working Area: " & scrCurrentDisplayInfo.WorkingArea.ToString + vbCrLf &
                    "Bits per Pixel: " & scrCurrentDisplayInfo.BitsPerPixel.ToString + vbCrLf &
                    "Width: " & scrCurrentDisplayInfo.Bounds.Width.ToString + vbCrLf &
                    "Height: " & scrCurrentDisplayInfo.Bounds.Height.ToString + vbCrLf &
                    "Work Area Width: " & scrCurrentDisplayInfo.WorkingArea.Width.ToString + vbCrLf &
                    "Work Area Height: " & scrCurrentDisplayInfo.WorkingArea.Height.ToString,
                    "Current Info for Display '" & scrCurrentDisplayInfo.DeviceName.ToString & "' - ID: " & idxDevice.ToString, MessageBoxButtons.OK, MessageBoxIcon.Information)

Lista de telas

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.