wpf 根据不同屏幕分辨率自动适应屏幕

时间:2022-08-27 06:03:10

    问题

  • 界面布局是默认采用的1920*1080的分辨率布局的,现在想自动适应不同的分辨率下的屏幕。

    如textblock宽100 高40 文字是20px

    适应到分辨率为1600*900,该如何做才能让textblock看起来没变化

    谢谢

    2014年5月7日 2:46

答案

  • 可否考虑View Box? 只要按照固定值设计layout, 放入固定长宽的canvas/grid中,然后放入viewbox中,可保证您的所有控件长宽比例不变。

    改变窗口的大小,里面的控件会自适应改变。

    <Window x:Class="WpfApplication4.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Viewbox>
    <Canvas Height="1080" Width="1920">
    <TextBlock Text="Something" Canvas.Left="900" Canvas.Top="500" FontSize="32"/>
    </Canvas>
    </Viewbox>
    </Window>

    http://msdn.microsoft.com/en-us/library/system.windows.controls.viewbox.aspx


    2014年5月21日 3:20
  • 你好,

    请参考下面的代码:

    XAML:

    <Window x:Class="WPFresolutionIndependentApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    x:Name="myMainWindow"
    >
    <Grid Name="MainGrid" SizeChanged="MainGrid_SizeChanged">
    <Grid.LayoutTransform>
    <ScaleTransform x:Name="ApplicationScaleTransform"
    CenterX="0"
    CenterY="0"
    ScaleX="{Binding ElementName=myMainWindow, Path=ScaleValue}"
    ScaleY="{Binding ElementName=myMainWindow, Path=ScaleValue}" />
    </Grid.LayoutTransform>
    <Grid VerticalAlignment="Center" HorizontalAlignment="Center" Height="150">
    <TextBlock FontSize="20" Text="Hello World" Margin="5" VerticalAlignment="Top" HorizontalAlignment="Center"/>
    <Button Content="Button" VerticalAlignment="Bottom" HorizontalAlignment="Center"/>
    </Grid>
    </Grid>
    </Window>

    C#:

            public MainWindow()
    {
    InitializeComponent();
    }

    #region ScaleValue Depdency Property
    public static readonly DependencyProperty ScaleValueProperty = DependencyProperty.Register("ScaleValue", typeof(double), typeof(MainWindow), new UIPropertyMetadata(1.0, new PropertyChangedCallback(OnScaleValueChanged), new CoerceValueCallback(OnCoerceScaleValue)));

    private static object OnCoerceScaleValue(DependencyObject o, object value)
    {
    MainWindow mainWindow = o as MainWindow;
    if (mainWindow != null)
    return mainWindow.OnCoerceScaleValue((double)value);
    else
    return value;
    }

    private static void OnScaleValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
    MainWindow mainWindow = o as MainWindow;
    if (mainWindow != null)
    mainWindow
    .OnScaleValueChanged((double)e.OldValue, (double)e.NewValue);
    }

    protected virtual double OnCoerceScaleValue(double value)
    {
    if (double.IsNaN(value))
    return 1.0f;

    value
    = Math.Max(0.1, value);
    return value;
    }

    protected virtual void OnScaleValueChanged(double oldValue, double newValue)
    {

    }

    public double ScaleValue
    {
    get
    {
    return (double)GetValue(ScaleValueProperty);
    }
    set
    {
    SetValue(ScaleValueProperty, value);
    }
    }
    #endregion

    private void MainGrid_SizeChanged(object sender, EventArgs e)
    {
    CalculateScale();
    }

    private void CalculateScale()
    {
    double yScale = ActualHeight / 250f;
    double xScale = ActualWidth / 200f;
    double value = Math.Min(xScale, yScale);
    ScaleValue = (double)OnCoerceScaleValue(myMainWindow, value);
    }
    }

    详细信息:

    http://*.com/questions/3193339/tips-on-developing-resolution-independent-application/5000120#5000120

    http://geekswithblogs.net/rakker/archive/2012/07/02/easy-scaling-in-xaml-wpf.aspx

    谢谢!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place. 
    Click HERE to participate the survey.

    • 已标记为答案 skczjun 2014年5月9日 0:46
    2014年5月8日 6:15
    版主

全部回复

  • 看起来没有变化是指?

    1. 长宽比率不变,布局位置比率不变

    ->  可以布局到Grid对象中

    2. 字体比率不变

     -〉 根据长宽,重新计算FontSize


    2014年5月7日 2:52
  • 一个界面有许多的文本,都要重新计算FontSize?如果新添加一个Textblock又要后台添加代码?

    这样很繁琐啊

    看起来没有变化即,同样的屏幕,假设我在分辨率1920*1080下有个控件是1920px宽度的,如果我调整分辨率为1600*900就会超出屏幕,我想实现的是与屏幕一样宽

    2014年5月7日 5:15
  • 一个界面有许多的文本,都要重新计算FontSize?如果新添加一个Textblock又要后台添加代码?

    这样很繁琐啊

    看起来没有变化即,同样的屏幕,假设我在分辨率1920*1080下有个控件是1920px宽度的,如果我调整分辨率为1600*900就会超出屏幕,我想实现的是与屏幕一样宽

    一样宽的话,可以借助Grid,设置比率。上面已经说过了。如果更改字体显示,而TextBlock比较多的情况,可以借助ViewBox。

    下面是个例子,你可以参考下,我将TextBlock的宽度设为80%。

    <Grid>
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="0.8*"/>
    <ColumnDefinition Width="0.2*"/>
    </Grid.ColumnDefinitions>
    <Grid Background="LightBlue">
    <Viewbox>
    <TextBlock Text="test" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Stretch" />
    </Viewbox>
    </Grid>
    </Grid>

    XAML的特性,你好像还未完全了解,宽度可以设置参照比率的。

    根据宽度大小和字数多少更改FontSize的方法有很多种,你可以采用扩展属性或方法来实现。在宽度和字数更改事件里对其调用。

    如果有必要,也可以自定义控件,来对TextBlock扩展。

    当多个UI控件需要统一设置时,你可以考虑下Binding来统一实现。


    2014年5月7日 6:07
  • 也即是说像这样的
    <Grid x:Name="MainGrid">
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="300"></ColumnDefinition>
    <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Grid Grid.Column="0">
    <Grid.RowDefinitions>
    <RowDefinition Height="60"></RowDefinition>
    <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Content="放大比例" FontSize="24" Click="OnAddScale"></Button>
    <ListBox Grid.Row="1" HorizontalContentAlignment="Stretch" Background="#FFBBD4EC">
    <TextBlock Text="aaaaaaaa" FontSize="20"></TextBlock>
    <TextBlock Text="bbbbbbb" FontSize="20"></TextBlock>
    <TextBlock Text="ccccccccc" FontSize="20"></TextBlock>
    </ListBox>
    </Grid>
    <Grid Grid.Column="1">
    <Grid.RowDefinitions>
    <RowDefinition Height="60"></RowDefinition>
    <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Content="缩小比例" FontSize="24" Click="OnReduceScale"></Button>
    <ListBox Grid.Row="1" HorizontalContentAlignment="Stretch" Background="#FF8B8B96">
    <TextBlock Text="aaaaaaaa" FontSize="20"></TextBlock>
    <TextBlock Text="bbbbbbb" FontSize="20"></TextBlock>
    <TextBlock Text="ccccccccc" FontSize="20"></TextBlock>
    </ListBox>
    </Grid>
    </Grid>
    改为这样
    <Grid x:Name="MainGrid">
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="300*"></ColumnDefinition>
    <ColumnDefinition Width="500*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Grid Grid.Column="0">
    <Grid.RowDefinitions>
    <RowDefinition Height="60*"></RowDefinition>
    <RowDefinition Height="540*"></RowDefinition>
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Content="放大比例" FontSize="24" Click="OnAddScale"></Button>
    <ListBox Grid.Row="1" HorizontalContentAlignment="Stretch" Background="#FFBBD4EC">
    <TextBlock Text="aaaaaaaa" FontSize="20"></TextBlock>
    <TextBlock Text="bbbbbbb" FontSize="20"></TextBlock>
    <TextBlock Text="ccccccccc" FontSize="20"></TextBlock>
    </ListBox>
    </Grid>
    <Grid Grid.Column="1">
    <Grid.RowDefinitions>
    <RowDefinition Height="60*"></RowDefinition>
    <RowDefinition Height="540*"></RowDefinition>
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Content="缩小比例" FontSize="24" Click="OnReduceScale"></Button>
    <ListBox Grid.Row="1" HorizontalContentAlignment="Stretch" Background="#FF8B8B96">
    <TextBlock Text="aaaaaaaa" FontSize="20"></TextBlock>
    <TextBlock Text="bbbbbbb" FontSize="20"></TextBlock>
    <TextBlock Text="ccccccccc" FontSize="20"></TextBlock>
    </ListBox>
    </Grid>
    </Grid>
    但这样做就没法使用对Width="60"与Width="*"的搭配了

    2014年5月7日 8:39
  • 你好,

    请参考下面的代码:

    XAML:

    <Window x:Class="WPFresolutionIndependentApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    x:Name="myMainWindow"
    >
    <Grid Name="MainGrid" SizeChanged="MainGrid_SizeChanged">
    <Grid.LayoutTransform>
    <ScaleTransform x:Name="ApplicationScaleTransform"
    CenterX="0"
    CenterY="0"
    ScaleX="{Binding ElementName=myMainWindow, Path=ScaleValue}"
    ScaleY="{Binding ElementName=myMainWindow, Path=ScaleValue}" />
    </Grid.LayoutTransform>
    <Grid VerticalAlignment="Center" HorizontalAlignment="Center" Height="150">
    <TextBlock FontSize="20" Text="Hello World" Margin="5" VerticalAlignment="Top" HorizontalAlignment="Center"/>
    <Button Content="Button" VerticalAlignment="Bottom" HorizontalAlignment="Center"/>
    </Grid>
    </Grid>
    </Window>

    C#:

            public MainWindow()
    {
    InitializeComponent();
    }

    #region ScaleValue Depdency Property
    public static readonly DependencyProperty ScaleValueProperty = DependencyProperty.Register("ScaleValue", typeof(double), typeof(MainWindow), new UIPropertyMetadata(1.0, new PropertyChangedCallback(OnScaleValueChanged), new CoerceValueCallback(OnCoerceScaleValue)));

    private static object OnCoerceScaleValue(DependencyObject o, object value)
    {
    MainWindow mainWindow = o as MainWindow;
    if (mainWindow != null)
    return mainWindow.OnCoerceScaleValue((double)value);
    else
    return value;
    }

    private static void OnScaleValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
    MainWindow mainWindow = o as MainWindow;
    if (mainWindow != null)
    mainWindow
    .OnScaleValueChanged((double)e.OldValue, (double)e.NewValue);
    }

    protected virtual double OnCoerceScaleValue(double value)
    {
    if (double.IsNaN(value))
    return 1.0f;

    value
    = Math.Max(0.1, value);
    return value;
    }

    protected virtual void OnScaleValueChanged(double oldValue, double newValue)
    {

    }

    public double ScaleValue
    {
    get
    {
    return (double)GetValue(ScaleValueProperty);
    }
    set
    {
    SetValue(ScaleValueProperty, value);
    }
    }
    #endregion

    private void MainGrid_SizeChanged(object sender, EventArgs e)
    {
    CalculateScale();
    }

    private void CalculateScale()
    {
    double yScale = ActualHeight / 250f;
    double xScale = ActualWidth / 200f;
    double value = Math.Min(xScale, yScale);
    ScaleValue = (double)OnCoerceScaleValue(myMainWindow, value);
    }
    }

    详细信息:

    http://*.com/questions/3193339/tips-on-developing-resolution-independent-application/5000120#5000120

    http://geekswithblogs.net/rakker/archive/2012/07/02/easy-scaling-in-xaml-wpf.aspx

    谢谢!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place. 
    Click HERE to participate the survey.

    • 已标记为答案 skczjun 2014年5月9日 0:46
    2014年5月8日 6:15
    版主
  • 可否考虑View Box? 只要按照固定值设计layout, 放入固定长宽的canvas/grid中,然后放入viewbox中,可保证您的所有控件长宽比例不变。

    改变窗口的大小,里面的控件会自适应改变。

    <Window x:Class="WpfApplication4.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Viewbox>
    <Canvas Height="1080" Width="1920">
    <TextBlock Text="Something" Canvas.Left="900" Canvas.Top="500" FontSize="32"/>
    </Canvas>
    </Viewbox>
    </Window>

    http://msdn.microsoft.com/en-us/library/system.windows.controls.viewbox.aspx