渲染目标位图 +资源化 VisualBrush = 不完整的图像
我发现了“Visual to RenderTargetBitmap”问题的新变化!
我正在为设计师渲染 WPF 内容的预览。这意味着我需要获取 WPF 视觉对象并将其渲染为位图,而不显示该视觉对象。有一个很好的小方法可以做到这一点,就像在这里看到它一样,它
private static BitmapSource CreateBitmapSource(FrameworkElement visual)
{
Border b = new Border { Width = visual.Width, Height = visual.Height };
b.BorderBrush = Brushes.Black;
b.BorderThickness = new Thickness(1);
b.Background = Brushes.White;
b.Child = visual;
b.Measure(new Size(b.Width, b.Height));
b.Arrange(new Rect(b.DesiredSize));
RenderTargetBitmap rtb = new RenderTargetBitmap(
(int)b.ActualWidth,
(int)b.ActualHeight,
96,
96,
PixelFormats.Pbgra32);
// intermediate step here to ensure any VisualBrushes are rendered properly
DrawingVisual dv = new DrawingVisual();
using (var dc = dv.RenderOpen())
{
var vb = new VisualBrush(b);
dc.DrawRectangle(vb, null, new Rect(new Point(), b.DesiredSize));
}
rtb.Render(dv);
return rtb;
}
工作得很好,除了一个小事...如果我的 FrameworkElement 有一个 VisualBrush,那么该画笔不会出现在最终渲染的位图中。像这样的事情:
<UserControl.Resources>
<VisualBrush
x:Key="LOLgo">
<VisualBrush.Visual>
<!-- blah blah -->
<Grid
Background="{StaticResource LOLgo}">
<!-- yadda yadda -->
其他所有内容都会渲染到位图,但 VisualBrush 不会显示。显而易见的谷歌解决方案已经被尝试过,但都失败了。即使是那些特别提到 VisualBrushes 的 RTB 位图也缺失了。
我偷偷怀疑这可能是由于它是一个资源而导致的,而惰性资源没有被内联。因此,一个可能的修复方法是,以某种方式(???)在渲染之前强制解析所有静态资源引用。但我完全不知道该怎么做。
有人能解决这个问题吗?
I've found a new twist on the "Visual to RenderTargetBitmap" question!
I'm rendering previews of WPF stuff for a designer. That means I need to take a WPF visual and render it to a bitmap without that visual ever being displayed. Got a nice little method to do it like to see it here it goes
private static BitmapSource CreateBitmapSource(FrameworkElement visual)
{
Border b = new Border { Width = visual.Width, Height = visual.Height };
b.BorderBrush = Brushes.Black;
b.BorderThickness = new Thickness(1);
b.Background = Brushes.White;
b.Child = visual;
b.Measure(new Size(b.Width, b.Height));
b.Arrange(new Rect(b.DesiredSize));
RenderTargetBitmap rtb = new RenderTargetBitmap(
(int)b.ActualWidth,
(int)b.ActualHeight,
96,
96,
PixelFormats.Pbgra32);
// intermediate step here to ensure any VisualBrushes are rendered properly
DrawingVisual dv = new DrawingVisual();
using (var dc = dv.RenderOpen())
{
var vb = new VisualBrush(b);
dc.DrawRectangle(vb, null, new Rect(new Point(), b.DesiredSize));
}
rtb.Render(dv);
return rtb;
}
Works fine, except for one leeetle thing... if my FrameworkElement has a VisualBrush, that brush doesn't end up in the final rendered bitmap. Something like this:
<UserControl.Resources>
<VisualBrush
x:Key="LOLgo">
<VisualBrush.Visual>
<!-- blah blah -->
<Grid
Background="{StaticResource LOLgo}">
<!-- yadda yadda -->
Everything else renders to the bitmap, but that VisualBrush just won't show. The obvious google solutions have been attempted and have failed. Even the ones that specifically mention VisualBrushes missing from RTB'd bitmaps.
I have a sneaky suspicion this might be caused by the fact that its a Resource, and that lazy resource isn't being inlined. So a possible fix would be to, somehow(???), force resolution of all static resource references before rendering. But I have absolutely no idea how to do that.
Anybody have a fix for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您有两个问题:
问题的直接原因是无法刷新调度程序队列,因为 VisualBrush 使用它,但不久您可能会遇到PresentationSource 问题,所以我会修复这两个问题。
我是这样做的:
仅供参考,StaticResource 查找在任何情况下都不会延迟:它在加载 XAML 时进行处理,并立即替换为从 ResourceDictionary 检索到的值。 StaticResource 可能关联的唯一方式是它是否因为两个资源具有相同的密钥而选择了错误的资源。我只是想我应该解释一下——这与你的实际问题无关。
You have two problems:
The immediate cause of your problem is failure to flush the Dispatcher queue, since VisualBrush uses it, but you will probably run into the PresentationSource problem before long so I would fix both of these.
Here is how I do it:
FYI, StaticResource lookup is never delayed under any circumstances: It is processed the moment the XAML is loaded and immediately replaced with the value retrieved from the ResourceDictionary. The only way StaticResource could possibly be related is if it picked up the wrong resource because two resources had the same key. I just thought I should explain this -- it has nothing to do with your actual problem.
好吧,要内联它,您可以这样做:
如果这不起作用,我的猜测是它一定是您正在使用的
Visual
实例特定的东西(并且这将需要进一步的代码以更好地诊断)。Well to inline it, you could just do something like this:
If that doesn't work, my guess would be that it must be something specific with the
Visual
instance you are using (and that will require further code to better diagnose).