【问题标题】:Freeze certain controls while Scaling (Render as Bitmap)缩放时冻结某些控件(渲染为位图)
【发布时间】:2013-08-16 10:06:40
【问题描述】:

无论原始控件大小如何,我都在尝试以各种大小拍摄 WPF 控件的快照。假设控件大小是 300 像素的宽度和高度,我正在尝试拍摄各种尺寸的快照,例如 1500 像素的高度和宽度、100 像素的高度和宽度等等。

这里是快照sn-p

        objFramework.LayoutTransform =
            new ScaleTransform(actualWidth / requiredWidth, actualHeight / requiredHeight);

            renderBitmap = new RenderTargetBitmap(requiredWidth, requiredHeight, 96d, 96d, PixelFormats.Pbgra32);

            var dv = new DrawingVisual();
            using (DrawingContext ctx = dv.RenderOpen())
            {
                var vb = new VisualBrush(objFramework);
                ctx.DrawRectangle(vb, null, new Rect(0, 0, requiredWidth, requiredHeight));
            }

            renderBitmap.Render(dv);

我在寻找什么:

我不希望缩放少数子控件。即使发生缩放,内部的 TextBlock 或 Grid Row 的高度之一也是恒定的。我的示例控制结构

<Grid>
    <Border x:Name="brdTiles"  VerticalAlignment="Center" HorizontalAlignment="Center" BorderThickness="1" BorderBrush="Black" >
        <local:GridExtension x:Name="grdTileHolder" Background="#FFFFFF" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="25" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>


            <Grid Grid.Row="0" Grid.Column="1" x:Name="TileColumnHeader" >                        
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="100" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="25"></RowDefinition>
                </Grid.RowDefinitions>
                <ComboBox x:Name="grd1" Grid.Column="0" FontSize="10" Height="20" >
                    <ComboBoxItem Content="Item 1" />
                    <ComboBoxItem Content="Item 2" />
                    <ComboBoxItem Content="Item 3" />
                </ComboBox>
                <TextBlock x:Name="txt1" Grid.Column="1" Text="20" FontSize="10" Height="20"/>
                <TextBlock x:Name="txt2" Grid.Column="2" Text="30" FontSize="10" Height="20"/>
                <TextBlock x:Name="txt3" Grid.Column="3" Text="40" FontSize="10" Height="20"/>
            </Grid>

            <Grid Grid.Column="0" Grid.Row="1"  x:Name="TileRowHeader" >
                <Grid.RowDefinitions>
                    <RowDefinition Height="100" />
                    <RowDefinition Height="30" />
                    <RowDefinition Height="30" />
                    <RowDefinition Height="30" />
                </Grid.RowDefinitions>

                <ComboBox HorizontalAlignment="Center" VerticalAlignment="Center" MinWidth="100" Grid.Row="0" >
                    <ComboBox.LayoutTransform>
                        <RotateTransform Angle="90" />
                    </ComboBox.LayoutTransform>
                    <ComboBox.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Vertical" IsItemsHost="True">
                                <StackPanel.LayoutTransform>
                                    <RotateTransform Angle="270" />
                                </StackPanel.LayoutTransform>
                            </StackPanel>
                        </ItemsPanelTemplate>
                    </ComboBox.ItemsPanel>
                    <ComboBox.ItemContainerStyle>
                        <Style TargetType="ComboBoxItem">
                            <Setter Property="LayoutTransform">
                                <Setter.Value>
                                    <RotateTransform Angle="0" />
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </ComboBox.ItemContainerStyle>
                    <ComboBoxItem>Hello</ComboBoxItem>
                    <ComboBoxItem>World</ComboBoxItem>
                    <ComboBoxItem>Foo</ComboBoxItem>
                    <ComboBoxItem>Check</ComboBoxItem>
                    </ComboBox>


            <TextBlock Text="2" Grid.Row="1" />
                <TextBlock Text="3" Grid.Row="2" />
                <TextBlock Text="4" Grid.Row="3" />
            </Grid>
            <Grid Grid.Row="1" Grid.Column="1" Margin="2" Name="TileViewGrid" Background="#FFFFFF" ShowGridLines="False"  HorizontalAlignment="Center" VerticalAlignment="Center" />
        </local:GridExtension>
    </Border>
</Grid>

我为什么要这样

拍摄各种尺寸的快照时,里面的文字看起来很模糊。所以我们在重新渲染控件时需要一个高质量的文本。

【问题讨论】:

  • 渲染图片时,常量大小控制的大小是否正确?
  • @mrtig ,我无法关注你,但复制所有子控件被渲染并以不同大小结束。它不是恒定的。我希望很少有控件的大小保持不变。

标签: c# wpf scaling


【解决方案1】:

如果您要考虑更改逻辑以循环(遍历)整个显示堆栈,并在所有项目上设置 RenderTransform 而不仅仅是容器,也许这样的事情会起作用;

class NonScalableTextBlock : System.Windows.Controls.TextBlock
{
    public Transform RenderTransform
    {
        get 
        { 
            return base.RenderTransform; 
        }

        set 
        { 
            // do nothing
        }
    }
}

(因此,当您不希望它扩展时,您可以使用此类代替标准 TextBlocks)

它隐藏了其父级的 LayoutTransform 属性,因此您将覆盖它以不执行任何操作。出于某种原因,RenderTransform 比 LayoutTransform 更适合我,不知道为什么。

【讨论】:

    【解决方案2】:

    您无需对控件应用任何转换。您可以简单地更改传递给 RenderTargetBitmap 的构造函数的 DPI 值。
    这样,控件将具有相同的逻辑大小,但更详细(更高的分辨率)。

    有关示例,请参阅 High-Resolution Printing of WPF 3D Visuals

    【讨论】:

      猜你喜欢
      • 2017-12-09
      • 1970-01-01
      • 1970-01-01
      • 2015-08-15
      • 2013-10-18
      • 2011-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多