2012-09-15 2 views
0

내 요구 사항 :RenderTargetBitmap과 VisualBrush를 함께 사용하면 멋지게 만들 수 있습니까?

  • 등의지도 나 줌 또는 팬 이동하는 동안 이미지 캐싱을 구현하는 컨테이너의
  • 세트를 그리기로, 사용자 정의 이미지 로직을 처리하는 지속적인 UserControl
  • VisualBrush 나는 효과와 함께 사용하기 위해 컨테이너에 추가 할 수있는 UserControl의 사본 내가 현재 RenderTargetBitmap와 이미지 캐싱을 구현할 수 있지만,이 갖고있는 것 같아요

문제가있는 VisualBrush- 해당 Rectangle 개체를 사용하고 있습니다.

내 질문 : 나는 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은 초기 이미지가 어떻게 든 변형 된 후에 캐시에 붙여 넣을 새 이미지를 생성합니다. 새로운 요소는 기존의 요소 위에 붙여되며, 기존의 요소의 변환을 유지하는 것 : 당신이 _body.Children.Add(SoftCopy(Control));에서 SoftCopy()을 제거 응용 프로그램을 구축하고 실행하면

, 당신은 내가 얻고 싶은 효과를 볼.

또는 var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);HardCopy에서 잘라 내면 캐싱 기능이 손상되지만 SoftCopy가 올바르게 표시됩니다.

그러나 응용 프로그램을있는 그대로 실행하면 새 BlueRectangle (VisualBrush를 통해 렌더링 됨)이 전혀 표시되지 않으며 "새로 만들기"단추를 다시 누르거나 이미지를 캐시하고 새롭게 생성 된 이미지를 표시하지 않습니다. 당신이 거 나쁜 시간이있어

당신이 요소에으로 RenderTransform/여백을 적용하면 그것 (RenderTargetBItmap)의 사진을 촬영할 :

+0

이 문제는 여기에서 완전히 다루었습니다 : http://stackoverflow.com/questions/2851236/rendertargetbitmap-resourceced-visualbrush-incomplete-image –

답변

3

저는 이것을 WPF에서 버그라고 부를만큼 화려 할 것입니다.

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

이 본질적으로 널 (null) 작업을해야한다 : 말, 시각적 브러시가 시작했을 때와 같은 시각을 가지고 나는 결국 내가지고 있던 이상한 행동을 수정하는 방법을 알아 냈다. 그러나이 코드 세그먼트를 VisualBrushRenderTargetBitmap으로 렌더링 한 후 추가하면 문제가 해결되었습니다.

0

는 꽤 게시물을 이해하지 못했지만 몇 가지 중요한 것이있다. 그것은 상쇄 될 것이고 당신은 하위 그림 만 얻을 것입니다.

아이디어는 렌더링 변환없이 사진을 찍은 다음 나중에 이전의 RenderTransform을 복사하는 것입니다. 필요한 경우.

+0

이 글은 오래된 글이지만, RenderTransform/여백? 나는 오프셋 문제 (왼쪽)도 얻는다. 이 WPF 버그는 어디서나 문서화되어 있습니까? – MC9000

관련 문제