wpf canvas viewbox lcd scaletransform

WPF para pantalla LCD Full HD



canvas viewbox (2)

WPF usa unidades independientes del dispositivo para especificar ancho / alturas / posiciones / grosores, etc.

1 DIU / DIP = 1 píxel físico cuando su pantalla DPI está configurada en 96 ppp ..... pero 1 DIU = una cantidad diferente de píxeles físicos cuando el DPI no es de 96 ppp.

Si usa un Canvas , coloca los elementos usando DIU.

Ahora implica que quiere posicionarse absolutamente en términos de coordenadas de píxeles.

Entonces, para hacer esto con el Canvas sin importar cuál sea la configuración de DPI actual, debe usar un truco de escala (puede hacerlo con un ViewBox o un LayoutTransform ).

El siguiente ejemplo muestra una forma de lograrlo (mi pantalla es 1366x768 ... puede cambiarla a Full HD).

Mira el DPI del sistema y reduce el Canvas cada vez que sube el DPI. Esto le permite usar coordenadas de Canvas que realmente significan coordenadas de píxeles.

Si puede cambiar la pantalla de los usuarios a 96 ppp, entonces no es necesario hacer el truco de escalado porque 1 DIU = 1 píxel físico a 96 ppp ... no es necesario cambiar el tamaño.

<Window x:Class="WpfApplication12.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowStyle="None" AllowsTransparency="True" Background="White" SizeToContent="WidthAndHeight" Title="MainWindow" Loaded="Window_Loaded"> <Viewbox x:Name="viewbox"> <Canvas x:Name="canvas"> <Rectangle x:Name="rect" Canvas.Top="10" Canvas.Left="10" Stroke="Red" StrokeThickness="1"/> <Button Canvas.Top="20" Canvas.Left="20">Test Button</Button> <Ellipse Canvas.Top="100" Canvas.Left="100" Width="100" Height="100" Stroke="Red" StrokeThickness="10"/> <TextBlock Canvas.Top="100" Canvas.Left="100" FontSize="15">Some Text</TextBlock> </Canvas> </Viewbox> </Window>

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApplication12 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { // HD const int screenwidth = 1366; const int screenheight = 768; // FULL HD //const int screenwidth = 1920; //const int screenheight = 1080; public MainWindow() { InitializeComponent(); Top = 0; Left = 0; canvas.Width = screenwidth; canvas.Height = screenheight; rect.Width = screenwidth - 20; rect.Height = screenheight - 20; } private void Window_Loaded(object sender, RoutedEventArgs e) { bool bScaleBackToPixels = true; if (bScaleBackToPixels) { PresentationSource presentationsource = PresentationSource.FromVisual(this); Matrix m = presentationsource.CompositionTarget.TransformToDevice; double DpiWidthFactor = m.M11; double DpiHeightFactor = m.M22; viewbox.Width = screenwidth / DpiWidthFactor; viewbox.Height = screenheight / DpiHeightFactor; } else { viewbox.Width = screenwidth; viewbox.Height = screenheight; } } } }

<Window x:Class="WpfApplication12.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowStyle="None" AllowsTransparency="True" Background="White" SizeToContent="WidthAndHeight" Title="MainWindow" Loaded="Window_Loaded"> <Canvas x:Name="canvas"> <Rectangle x:Name="rect" Canvas.Top="10" Canvas.Left="10" Stroke="Red" StrokeThickness="1"/> <Button Canvas.Top="20" Canvas.Left="20">Test Button</Button> <Ellipse Canvas.Top="100" Canvas.Left="100" Width="100" Height="100" Stroke="Red" StrokeThickness="10"/> <TextBlock Canvas.Top="100" Canvas.Left="100" FontSize="15">Some Text</TextBlock> </Canvas> </Window>

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApplication12 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { // HD const int screenwidth = 1366; const int screenheight = 768; // FULL HD //const int screenwidth = 1920; //const int screenheight = 1080; public MainWindow() { InitializeComponent(); Top = 0; Left = 0; canvas.Width = screenwidth; canvas.Height = screenheight; rect.Width = screenwidth - 20; rect.Height = screenheight - 20; } private void Window_Loaded(object sender, RoutedEventArgs e) { bool bScaleBackToPixels = true; if (bScaleBackToPixels) { PresentationSource presentationsource = PresentationSource.FromVisual(this); Matrix m = presentationsource.CompositionTarget.TransformToDevice; double DpiWidthFactor = m.M11; double DpiHeightFactor = m.M22; double scalex = 1 / DpiWidthFactor; double scaley = 1 / DpiHeightFactor; canvas.LayoutTransform = new ScaleTransform(scalex, scaley); } } } }

En la configuración de 96 ppp (Más pequeño - 100%) la pantalla se ve así:

En la configuración de 120 ppp (Medio - 125%) (es decir, 96 x 1.25 = 120 ppp), la pantalla se ve así cuando utilizo la técnica ScaleBackToPixels anterior (es decir, tiene el mismo aspecto que la primera pantalla).

En la configuración de 120 ppp (Medio - 125%) (es decir, 96 x 1.25 = 120 ppp), la pantalla se ve así cuando no hace ningún ajuste (observe cómo el círculo es más grande, y la fuente y el tamaño del botón )

Las 3 imágenes una al lado de la otra para la comparación:

Estoy desarrollando una aplicación WPF que se mostrará en una pantalla LCD Full HD (42 pulgadas). Además, necesito acomodar los controles en posiciones absolutas. En el entorno de desarrollo, no puedo ver una ventana de 1920x1080 (esta es la resolución fija de la pantalla de destino).

¿Cuál es la mejor práctica para lograr esta tarea?


Aquí está la transformación que hace que la resolución de pantalla 1920x1080 (FullHD) sea visible en la resolución de pantalla de mi laptop 1366x768:

XAML

<ContentControl Canvas.Left="1630" Canvas.Top="400" Content="{Binding Time}" /> <ContentControl Canvas.Left="1630" Canvas.Top="590" Content="{Binding NextPrayTime}" /> <ContentControl Canvas.Left="1650" Canvas.Top="700" Content="{Binding Today}" /> <ContentControl Canvas.Right="520" Canvas.Top="120" Content="{Binding Content}" /> <ContentControl Canvas.Left="0" Canvas.Top="965" Content="{Binding PrayTimes}"> </ContentControl> </Canvas> </Viewbox>

DO#

static public class HD { static public float Width { get { return 1366.0f; } } static public float Height { get { return 768.0f; } } } static public class FHD { static public float Width { get { return 1920.0f; } } static public float Height { get { return 1080.0f; } } } static public class HDRatios { static public double Width { get { #if (DEBUG) return double.Parse((HD.Width / FHD.Width).ToString("0.0")); #else return 1; #endif } } static public double Height { get { #if (DEBUG) return double.Parse((HD.Height / FHD.Height).ToString("0.0")); #else return 1; #endif } }

El código demuestra que en el entorno de desarrollo (indicador DEBUG) se aplicará la transformación y en la versión de lanzamiento la transformación no se aplicará ya que Canvas.Left y Canvas.Top están de acuerdo con la resolución de Full HD.

Espero que esta experiencia ayude a otros que se encuentran a mostrar controles en WPF dentro de un Canvas en métricas absolutas.