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>
如果您尝试以下实验会发生什么?
- 在主窗口大小设置为 1920 x 1080 的情况下运行应用。
- 在运行应用时,主窗口大小设置为 1024 x 576。
当您使用较小的窗口大小运行时,矢量图形看起来几乎相同,只是更小,还是看起来仍然不同?
如果它们看起来几乎相同,只是更小,这意味着您的图形设置为拉伸并填充其父容器。使用1920 x 1080显示器时,纵横比为1920 / 1080 = 1.78
。使用1024 x 768显示器时,纵横比为1024 / 768 = 1.33
。(请注意,1024 x 576 的纵横比与 1920 x 1080 的纵横比相同。由于较小的显示器具有较高的纵横比,因此拉伸以填充容器的图形将显示得更高。
如果不看到 XAML,就很难准确诊断导致意外拉伸的原因,但由于您提到了矢量图形,因此我假设您使用的是 Path
、Ellipse
和 Rectangle
等控件。其中每个控件都有一个 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 应用程序看起来有点模糊。
在您的情况下,您1024x768
和1920x1080
都有96dpi
,这意味着矢量图形将在两个显示器上转换为相同的像素大小。 不同之处在于,最大表单大小仅在一台显示器上1024x768
,而在另一台显示器上1920x1080
。 如果使用Grid
划分显示,则每列在较小分辨率显示器上的像素较少,这意味着任何形状(知道两个监视器上的形状都需要相同的像素宽度)会使特定形状占据列的更多比例。
三种不同的解决方案
- 在
1920x1080
开发电脑上,将 WPF 应用程序窗口设置为固定大小 1024x768。 然后,部署的应用在全屏Maximised
时看起来与开发计算机完全相同
<Window x:Class=" ...
xmlns=" ....
Width="1024" Height="768" >
....
</Window>
- 用
Viewbox
包围所有控件,并将Stretch
属性设置为UniformToFill
。 这将允许控件报告其大小(在 WPF 布局过程的Measure
阶段),然后统一缩放控件以适应可用大小。
<Window x:Class=" ...
....
<Viewbox Stretch="UniformToFill">
<Grid>
....
</Grid>
</Viewbox>
</Window>
- 仅缩放屏幕的一部分,使某些区域(例如按钮的文本)呈现在
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;
}
}
在这里,当窗口大小发生变化时,我们有一个回调(通过Window
类LayoutUpdated
处理程序)。 我们查看窗口的宽度是否小于设计时窗口大小,并仅适当缩放Canvas
UI 元素,而将其他控件缩放到 100%。 LayoutTransform
可用于大多数 WPF UI 控件,而不仅仅是 Canvas
。
解决方案 2 和 3 提供了缩放,但它们确实有一些副作用,即如果您开发了一个图表,其中在宽度为 1 像素的两个形状之间绘制了一条连接线,那么当缩放为 1:1 时,这将正确呈现,但抗锯齿会导致单像素线在某些情况下显示实心 1 像素,但在其他情况下当缩放明显不同时会出现抖动。 有一些高级选项需要大量研究(例如 RenderOptions
)并了解渲染过程以消除这些影响。