WPF 应用程序从一个监视器更改为另一个监视器

本文关键字:监视器 另一个 一个 应用程序 WPF | 更新日期: 2023-09-27 18:31:39

我正在编写一个WPF应用程序,作为工业自动化的GUI。 当我在屏幕分辨率为 1920x1080 的开发计算机上运行时,它看起来以某种方式,但当我在目标计算机 1024x768 上运行它时,它会发生变化。 大多数东西都在增长。 我认为基于矢量的想法是东西应该保持相同的大小。 我已经通过将显示器直接插入我的开发机器(触摸屏显示器)来排除计算机(主题设置等)。 所以要么是我在我的应用程序中做错了什么,要么是显示器本身

任何想法??

编辑 xaml 示例

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

WPF 应用程序从一个监视器更改为另一个监视器

如果您尝试以下实验会发生什么?

  1. 在主窗口大小设置为 1920 x 1080 的情况下运行应用。
  2. 在运行应用时,主窗口大小设置为 1024 x 576。

当您使用较小的窗口大小运行时,矢量图形看起来几乎相同,只是更小,还是看起来仍然不同?

如果它们看起来几乎相同,只是更小,这意味着您的图形设置为拉伸并填充其父容器。使用1920 x 1080显示器时,纵横比为1920 / 1080 = 1.78 。使用1024 x 768显示器时,纵横比为1024 / 768 = 1.33 。(请注意,1024 x 576 的纵横比与 1920 x 1080 的纵横比相同。由于较小的显示器具有较高的纵横比,因此拉伸以填充容器的图形将显示得更高。

如果不看到 XAML,就很难准确诊断导致意外拉伸的原因,但由于您提到了矢量图形,因此我假设您使用的是 PathEllipseRectangle 等控件。其中每个控件都有一个 Stretch 属性。我建议您阅读文档中的Stretch。我猜你应该Stretch设置为Uniform而不是Fill,但你必须进行实验以确定什么效果最好。

如果仍需要帮助,请发布一些显示 XAML 标记的示例。

WPF 不适用于实际像素。实际上它使用的是DPI设置。显示器的 DPI 设置是否可能不同?即使在同一台机器上,DPI 设置对于每个显示器也是唯一的。如果这是问题所在,这个问题可能会进一步帮助您。

我也为工业自动化设备开发,但就我而言,我的目标是1080p显示器,但也希望笔记本电脑能够以较低的分辨率演示软件(例如 1440x900)。

当我在屏幕分辨率为 1920x1080 的开发计算机上运行时,它看起来以某种方式,但当我在目标计算机 1024x768 上运行它时,它会发生变化。大多数东西都在增长。

您会发现,对于Microsoft Windows屏幕分辨率,无论显示器的大小如何,所有屏幕分辨率都默认为96dpi。 例如,我有一个 22 英寸显示器在 1080p 上运行,我也可以将同一台 PC 连接到我的 55 英寸电视1080p。 即使 22 英寸显示器(使用卷尺)在物理上适合与我的 55 英寸电视相同尺寸的 2x2 网格,如果我抓取屏幕,两个显示器的1920x1080输出位图完全相同。

因此,所有显示器都96dpi当您在 10 英寸平板电脑上显示 Retina 类型的 1920x1080 时,现在开始引起问题,并且更常见的是显示设置中可以使用"放大文本和其他项目"设置以调整远离 96dpi 以应对这些情况。 WPF 应用程序将正确缩放,但 Win32 应用程序看起来有点模糊。

在您的情况下,您1024x7681920x1080都有96dpi,这意味着矢量图形将在两个显示器上转换为相同的像素大小。 不同之处在于,最大表单大小仅在一台显示器上1024x768,而在另一台显示器上1920x1080。 如果使用Grid划分显示,则每列在较小分辨率显示器上的像素较少,这意味着任何形状(知道两个监视器上的形状都需要相同的像素宽度)会使特定形状占据列的更多比例。

三种不同的解决方案

  1. 1920x1080开发电脑上,将 WPF 应用程序窗口设置为固定大小 1024x768。 然后,部署的应用在全屏Maximised时看起来与开发计算机完全相同
  <Window x:Class=" ...
    xmlns=" ....
    Width="1024" Height="768" >
    ....
  </Window>
  1. Viewbox包围所有控件,并将 Stretch 属性设置为 UniformToFill 。 这将允许控件报告其大小(在 WPF 布局过程的Measure阶段),然后统一缩放控件以适应可用大小。
  <Window x:Class=" ...
   ....
    <Viewbox Stretch="UniformToFill">
       <Grid>
        ....
       </Grid>
    </Viewbox>
  </Window>
  1. 仅缩放屏幕的一部分,使某些区域(例如按钮的文本)呈现在96dpi。 只能使用Viewbox再次包围显示的某些部分,或者使用Viewbox的下划线函数,该函数可通过 LayoutTransform 依赖项属性提供给任何控件。
  <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>

然后在代码隐藏中

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

在这里,当窗口大小发生变化时,我们有一个回调(通过WindowLayoutUpdated处理程序)。 我们查看窗口的宽度是否小于设计时窗口大小,并仅适当缩放Canvas UI 元素,而将其他控件缩放到 100%。 LayoutTransform可用于大多数 WPF UI 控件,而不仅仅是 Canvas

解决方案 2 和 3 提供了缩放,但它们确实有一些副作用,即如果您开发了一个图表,其中在宽度为 1 像素的两个形状之间绘制了一条连接线,那么当缩放为 1:1 时,这将正确呈现,但抗锯齿会导致单像素线在某些情况下显示实心 1 像素,但在其他情况下当缩放明显不同时会出现抖动。 有一些高级选项需要大量研究(例如 RenderOptions)并了解渲染过程以消除这些影响。