0

私の要件:

  • UserControlマップや描画などのカスタム イメージのロジックを処理する永続
  • ズームまたはパンの移動中に画像にキャッシュを実装するためのコンテナーのセット
  • VisualBrushUserControlエフェクトで使用するコンテナに追加できるのコピー

現在、RenderTargetBitmap を使用してイメージ キャッシングを実装していますが、使用しているVisualBrush-coveredRectangleオブジェクトに問題があるようです。

私の質問VisualBrush:オブジェクトを使用した後にオブジェクトを正しくレンダリングするには、このコードに何を追加/変更できRenderTargetBitmapますか? 目に見えないようRenderTargetBitmapにする奇妙なことは何ですか?VisualBrush

これは、かなりの量のコードがなければ再現できなかった問題です。

私のxamlファイルには次のものがあります:

<Window x:Class="ElementRender.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="350" Width="525">
  <Grid>
    <Grid Name="_contentContainer">
      <Rectangle Fill="White"/>
      <Grid Name="_content">
        <Grid Name="_back"/>
        <Grid Name="_body"/>
      </Grid>
    </Grid>
    <StackPanel VerticalAlignment="Bottom" Orientation="Horizontal">
      <Button Content="New" Name="New"/>
      <Button Content="Move" Name="Move"/>
      <Button Content="Update" Name="Update"/>
    </StackPanel>
  </Grid>
</Window>

および .xaml.cs:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

public partial class MainWindow : Window
{

  private const int imageWidth = 150;
  private const int imageHeight = 150;
  private readonly UserControl Control;

  public MainWindow()
  {
     InitializeComponent();

     // User Control setup
     Control = new UserControl() {
        Width = imageWidth, Height = imageHeight,
        Content = BuildImage()
     };
     _body.Children.Add(SoftCopy(Control));

     // event setup
     Move.Click += (sender, e) => _content.RenderTransform = new TranslateTransform(50, 50);
     New.Click += (sender, e) => {
        HardCopy();
        _content.RenderTransform = null;
        Control.Content = BuildImage();
     };
  }

  private FrameworkElement BuildImage()
  {
     return new Rectangle{Fill=Brushes.Blue};
  }
  private void HardCopy()
  {
     int width = (int) _contentContainer.ActualWidth;
     int height = (int) _contentContainer.ActualHeight;

     // render the current image
     var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
     DrawingVisual dv = new DrawingVisual();
     using (var context = dv.RenderOpen())
     {
        var brush = new VisualBrush(_contentContainer) { Opacity = .5 };
        context.DrawRectangle(brush, null, new Rect(0, 0, width, height));
     }
     rtb.Render(dv);
     var lastRender = new Image
     {
        Source = rtb,
        Stretch = Stretch.None,
        HorizontalAlignment = HorizontalAlignment.Center,
        VerticalAlignment = VerticalAlignment.Center,
        Width = width,
        Height = height
     };
     _back.Children.Clear();
     _back.Children.Add(lastRender);
  }
  private FrameworkElement SoftCopy(FrameworkElement element)
  {
     return new Rectangle{Fill= new VisualBrush(element), Width=element.Width, Height=element.Height};
  }
}

コードに関するいくつかのヘルプ ノート:

  • xaml は_contentContainerと連携しHardCopy()て、現在の画像を画像キャッシュにコピーします_back
  • SoftCopy過去のものとまったく同じように見えるが、変換、効果、または視覚的な親がない FrameworkElement を返します。これはとても重要です。
  • BuildImage初期画像が何らかの形で変換された後、キャッシュに貼り付けられる新しい画像の作成をシミュレートします。

SoftCopy()から を削除してアプリケーションをビルドして実行すると、目的_body.Children.Add(SoftCopy(Control));の効果が得られます。新しい要素が古い要素の上に貼り付けられ、古い要素がその変換を保持しているように見えます。

var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);または、から行を切り取るHardCopyと、キャッシュ機能は壊れますが、SoftCopy は正しく表示されます。

ただし、アプリケーションをそのまま実行すると、新しい BlueRectangle (VisualBrush を介してレンダリングされたもの) がまったく表示されないことがわかります。これは、[新規] ボタンをもう一度押して画像をキャッシュにプッシュし、それでもなお新しく作成された画像が表示されません。

4

2 に答える 2

3

私はこれを WPF のバグと呼ぶほど大げさに言います。私は最終的に、私が得ていた奇妙な動作を修正する方法を見つけました:

var visual = visualBrush.Visual;
visualBrush.Visual = null;
visualBrush.Visual = visual;

これは基本的に null 操作である必要があります。最終的に、ビジュアル ブラシは開始時と同じビジュアルになります。ただし、レンダリング後にこのコード セグメントを追加すると、私が抱えていた問題が修正さVisualBrushれました。RenderTargetBitmap

于 2012-11-01T17:16:22.363 に答える
0

投稿をよく理解していませんでしたが、重要なことがいくつかあります。

要素に RenderTransform/Margins を適用してそれを撮影すると (RenderTargetBItmap)、時間がかかります。オフセットされ、サブピクチャのみが取得されます。

アイデアは、rendertransforms なしで写真を撮り、後で古いものから RenderTransform をコピーすることです。必要に応じて。

于 2012-09-15T17:02:30.510 に答える