내 요구 사항 :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)의 사진을 촬영할 :
이 문제는 여기에서 완전히 다루었습니다 : http://stackoverflow.com/questions/2851236/rendertargetbitmap-resourceced-visualbrush-incomplete-image –