利用WPF建立自适应窗口大小布局的WinForm窗口31

来源:互联网 发布:田众和时代网络 编辑:程序博客网 时间:2024/05/21 18:48

利用WPF建立自适应窗口大小布局的WinForm窗口

编写WinForm程序时,都会碰到一个问题。就是WinForm窗口在不同分辨率下的大小问题。举例说明,你编写的WinForm窗口在1024×768下是合适、匀称的。不过,如果用户的计算机的分辨率为1400×900时,你的WinForm窗口就显得偏小,其中的字体和控件都显得偏小。如果用户的分辨率为640×480,那你的窗口就远远超过它的屏幕的大小。 如何解决这个问题?一般的WinForm程序都会这样操作:程序启动——》获取屏幕分辨率——》调整窗体的大小——》调整各个控件大小及位置——》调整各个控件的字体。这样操作比较繁琐,并且要考虑到各种分辨率的情况。这样一来,如果WinForm窗口上有若干控件,调整是一件很痛苦的事。

有没有这样的手段。我只要调整WinForm窗口的大小,其中的各个控件大小(包括字体)自动的等比例缩放?

还记得一些DirectX的游戏程序吗?当设定为固定的分辨率时(比如800×600),在全屏的时候,他都会自动缩放。WinForm有这样的手段吗?

答案是肯定的。在WPF中就能很简单的实现该功能。

利用WPF中的ViewBox容器空间。ViewBox是一个容器空间,它会自动缩放容器中的子空间以填满自身,同时它只能有一个子控件。不过,我们可以把Canvas控件作为ViewBox控件的子控件。然后在Canvas控件中布局其他的控件。

先看看下面的窗口的Xaml文件

<Window x:Class="Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPFTest"

mc:Ignorable="d"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" SizeToContent="Manual" Width="400" Height="300">

<DockPanel Name="DockPanel1" LastChildFill="True">

<Menu Height="23" Name="Menu1" DockPanel.Dock="Top">

<MenuItem Header="Menu1">

<MenuItem Header="H1" />

<MenuItem Header="H2" />

</MenuItem>

<MenuItem Header="Menu2">

<MenuItem Header="L1" />

<MenuItem Header="L2" />

<Separator />

<MenuItem Header="L4" />

</MenuItem>

</Menu>

<StatusBar Height="23" Name="StatusBar1" DockPanel.Dock="Bottom"> <StatusBarItem Content="S1" Name="S1"/>

<StatusBarItem Content="S2" Name="S2"/>

<StatusBarItem Content="S3" Name="S3"/>

</StatusBar>

<Viewbox Name="Viewbox1" Stretch="Fill">

<Canvas Height="200" Name="Canvas1" Width="300"

Background="#FF8EDE75">

<Button Canvas.Left="43" Canvas.Top="40" Content="Button" Height="37" Name="Button1" Width="87" />

</Canvas>

</Viewbox>

</DockPanel>

</Window>

先简单的说明这个XAML文件

最外面的是Window容器,设置了标题(WPFTest)和大小(400×300),它也只能有一个子控件。

Window的子控件是DockPanel容器,是自动停靠容器控件。设置

LastChildFill="True",表示最后一个子控件自动填充剩余的空间。没有设置大小,默认大小是Window的客户区大小。

DockPanel控件有三个子控件

1、Menu控件:菜单控件,自动停靠在容器的顶端

2、StatusBar控件:状态栏控件,自动停靠在容器的底部

3、ViewBox控件:容器控件,自动填充DockPanel剩余的控件。没有设置大小,为填充的大小。设置填充的模式为Fill,表示子控件填充自身的容器的大小。在ViewBox中放置了一个Canvas控件,设置了大小(注:一定要设置大小,否则默认时会产生各种不可思议的效果),设置了背景色。在Canvas中放置了一个Button控件。只是示例,Canvas中还能放置其他的控件

在Window的代码中输入如下的代码

Public Class Window1

Private _I As Integer

Private Sub Window1_SizeChanged(ByVal sender As Object, ByVal e As System.Windows.SizeChangedEventArgs) Handles Me.SizeChanged

_I += 1

Me.S1.Content = "窗口宽度:" & Me.Width

Me.S2.Content = "内容宽度:" & Me.Viewbox1.Width

Me.S3.Content = "按钮宽度:" & Me.Button1.Width & ";刷新次数:" & _I End Sub

End Class

启动后是如下的效果

可以看出窗口的宽度是400,由于ViewBox没有设置宽度,故显示非数字,按钮的宽度是87

拖动右下角,调整Window的大小。如下图所示

和上图的比较,Window的大小发生了变化。ViewBox中的子控件也自动的拉伸了。这个从Button的外观能很明显的感受到。更神奇的是,无论我怎么调整Window的大小,Button的外观也随着Window的大小而改变,不过,在内部的逻辑中,Button的宽度始终是87,始终没有发生变化。

另,由于Menu和StatusBar不在ViewBox内。故这两个控件没有缩放,还是原始的大小

这给我们带来了极大的便利。无论window被调整到如何,在内部逻辑中,ViewBox中的子控件Canvas的逻辑大小始终是300×200。我们不需要再为调整后的大小设计额外的代码。

实际上,我猜测。ViewBox的显示机制是,先在内存中把按照逻辑大小把子控件显示出来,然后等比例的缩放显示到ViewBox的客户区。

回到开始的话题。编写的WinForm窗口如何应对不同的分辨率?

在WPF中,将所有的客户控件放在Canvas中再放在ViewBox控件中,利用ViewBox的特性来实现自动的缩放。流程就变成了:程序启动——》获取屏幕分辨率——》

调整窗体

的大小。其余控件的缩放就交给ViewBox控件吧。而且由于逻辑的大小没有发生变化,你还不必要再额外添加代码。

网上ViewBox控件介绍的比较少,用ViewBox来实现自适应窗体的大小确是独辟蹊径。

 

 

 

 

例子:
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Width="450" Height="120" >
    <Grid>
        <Viewbox>    <!--不能设置宽度高度才能跟随窗口变化大小,stretch要为Fill才能填满,为UniForm则不会填满-->
            <Grid>
                <Button Content="AAA" Height="23" HorizontalAlignment="Left"  Name="btnloadeddll" VerticalAlignment="Top" Width="93" Margin="0,0,0,0"/>
                <Button Content="BBB" Height="23" HorizontalAlignment="Left"  Name="btnloadedtxt" VerticalAlignment="Top" Width="93" Margin="0,50,0,0"/>
                <TextBox Height="23" HorizontalAlignment="Left" Margin="100,0,0,0" Name="txtloaddll" VerticalAlignment="Top" Width="205" BorderBrush="Black" />
                <TextBox Height="23" HorizontalAlignment="Left" Margin="100,50,0,0" Name="txtloadtxt" VerticalAlignment="Top" Width="205" BorderBrush="Black" />
                <Button Content="CCC" Height="23" HorizontalAlignment="Left" Margin="310,0,0,0" Name="button3" VerticalAlignment="Top" Width="75"/>
                <Button Content="DDD" Height="23" HorizontalAlignment="Left" Margin="310,50,0,0" Name="button4" VerticalAlignment="Top" Width="75" />               
            </Grid>
        </Viewbox>
    </Grid>
</Window>