简体   繁体   中英

WPF Application Changes From Monitor To Monitor

I am writing a WPF application to be a GUI for a piece of industrial automation. When run on my development machine with a screen resolution on 1920x1080 it looks a certain way but when I run it on my target machine 1024x768 it changes. Mostly everything grows. I thought the idea of Vector based is that stuff should remain the same size. I have ruled out the computer(Themes settings etc) by plugging the monitor directly into my development machine(It a touch screen monitor). So its either something Im doing incorrect in my application or the monitor itself

Any ideas??

Edit xaml sample

<Controls:MetroWindow x:Class="Trax_HMI.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
    Title="MainWindow" Height="768" Width="1024" WindowStyle="None" WindowState="Maximized" UseNoneWindowStyle="True" ShowTitleBar="False">
    <Grid >

        <Image HorizontalAlignment="Left" Height="559" Margin="10,10,-30,-42" VerticalAlignment="Top" Width="780" Source="Cell Layout.png"/>

        <Button Content="Log Off" HorizontalAlignment="Left" Height="44" Margin="542,10,0,0" VerticalAlignment="Top" Width="132" Click="Button_Click"/>
        <Button Content="Close" HorizontalAlignment="Left" Height="39" Margin="542,59,0,0" VerticalAlignment="Top" Width="132" Click="Button_Click_1"/>
        <Label x:Name="OPCState" HorizontalAlignment="Left" Height="27" Margin="10,10,0,0" VerticalAlignment="Top" Width="217"/>
        <Button Content="Reset" HorizontalAlignment="Left" Height="38" Margin="918,720,0,0" VerticalAlignment="Top" Width="96"/>
     </Grid>
 </Controls:MetroWindow>

What happens if you try the following experiment?

  1. Run your app with your main window size set to 1920 x 1080.
  2. Run your app with your main window size set to 1024 x 576.

When you run with the smaller window size, do your vector graphics look pretty much the same, only smaller, or do they still look different?

If they look pretty much the same, only smaller, that means your graphics are set to stretch and fill their parent container. With a 1920 x 1080 monitor, the aspect ratio is 1920 / 1080 = 1.78 . With a 1024 x 768 monitor, the aspect ratio is 1024 / 768 = 1.33 . (Note that 1024 x 576 has the same aspect ratio as 1920 x 1080.) Since the smaller monitor has a taller aspect ratio, graphics stretched to fill the container will appear taller.

Without seeing your XAML, it's a little difficult to diagnose exactly what's causing the undesired stretching, but since you mention vector graphics, I'm going to assume you're using controls such as Path , Ellipse , and Rectangle . Each of these controls has a Stretch property. I recommend you read up on Stretch in the documentation . I would guess you should be setting Stretch to Uniform rather than Fill , but you will have to experiment to determine exactly what works best.

If you still need help, please post some examples showing your XAML markup.

WPF does not work with actual pixels. Actually it is using DPI settings. Is it possible the DPI settings for the displays are different? Even on the same machine DPI settings are unique per display. If this is the problem this question might help you further.

I too develop for industrial automation equipment, but in my case I target 1080p displays but also want a laptop to be able to demo the software at a lower resolution (eg 1440x900 ).

When run on my development machine with a screen resolution on 1920x1080 it looks a certain way but when I run it on my target machine 1024x768 it changes. Mostly everything grows.

What you will find is that for Microsoft Windows screen resolutions all default to 96dpi no matter what size the monitor is. For example I have a 22" monitor running at 1080p , I can also connect the same PC to my 55" TV at 1080p also. Even though the 22" monitor (using a tape measure) would physically fit in a 2x2 grid in the same size as my 55" TV the output bitmap of 1920x1080 for the two displays is exactly the same if I took a screen grab.

So all monitors are 96dpi which is now starting to cause problems when you have the Retina type displays of 1920x1080 on a 10" tablet, and more frequently the "Make text and other Items larger" settings are available in the display settings to tweak away from the 96dpi to cope with these situations. WPF applications will scale properly but Win32 apps look a bit fuzzy.

In your case you have 96dpi for both 1024x768 and 1920x1080 meaning the vector graphics will translate to the same pixels size on both displays. The difference being that the maximum form size is only 1024x768 on one monitor and 1920x1080 on the other. If you divide the display using a Grid then each column has less pixels on the smaller resolution display meaning any shapes (knowing that the shapes on both monitors will need the same width in pixels) makes a particular shape take more proportion of the column.

Three different Solutions

  1. On your 1920x1080 development PC then make your WPF application window a fixed size of 1024x768. Your deployed app will then look exactly like your development machine when it is Maximised to full screen
  <Window x:Class=" ...
    xmlns=" ....
    Width="1024" Height="768" >
    ....
  </Window>
  1. Surround all controls with a Viewbox and set the Stretch attribute to UniformToFill . This will allow your controls to report their size (during the Measure phase of the WPF layout process) and then scale uniformly the controls to fit in the available size.
  <Window x:Class=" ...
   ....

    <Viewbox Stretch="UniformToFill">
       <Grid>
        ....
       </Grid>
    </Viewbox>

  </Window>
  1. Only scale a proportion of the screen leaving some areas (eg text for buttons) rendering at 96dpi . You could only enclose parts of the display again with a Viewbox or alternatively use the underline function of the Viewbox which is available to any control via the LayoutTransform dependency property.
  <Window x:Class=" ...
     LayoutUpdated="Window_LayoutUpdated" >

   ....

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20*"/>
            <ColumnDefinition Width="60*"/>
            <ColumnDefinition Width="20*"/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="20*"/>
            <RowDefinition Height="60*"/>
            <RowDefinition Height="20*"/>
        </Grid.RowDefinitions>

        <Canvas Grid.Row="1" Grid.Column="1">
            <Canvas.LayoutTransform>
                <ScaleTransform x:Name="PageScale" ScaleX="1" ScaleY="1"/>
            </Canvas.LayoutTransform>
            <Rectangle Width="700" Height="700" Fill="Red"/>
        </Canvas>
    </Grid>
</Window>

Then in the code-behind

    private void Window_LayoutUpdated(object sender, EventArgs e)
    {
        if ((ActualWidth != 0) && (ActualWidth < 1900))
        {
            var scale = ActualWidth / 1920.0;
            PageScale.ScaleX = scale;
            PageScale.ScaleY = scale;
        }
        else
        {
            PageScale.ScaleX = 1.0;
            PageScale.ScaleY = 1.0;
        }
    }

Here we have a callback when the windows size has changed (via the handler for LayoutUpdated of the Window class). We see if the width of the window is less than the design time window size and scale appropriately the Canvas UI element only, leaving the other controls scaling to 100%. LayoutTransform can be used on most WPF UI controls, not just Canvas .

Solutions 2 & 3 provide the scaling but they do have some side-effects, namely if you have developed a diagram where a connector line is drawn between two shapes with a width of 1 pixel then this is renders correctly when the scaling is 1:1, but anti-aliasing causes the single pixel line to show solid 1 pixel in some cases but a dithered in others when the scaling is significantly different. There are advanced options that require lots of research (eg RenderOptions ) and an understanding of the rendering process to eliminate these effects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM