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

  • 问题

  • 界面布局是默认采用的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://stackoverflow.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://stackoverflow.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


  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值