RenderTargetBitmap +资源的VisualBrush =图片不完整 [英] RenderTargetBitmap + Resource'd VisualBrush = incomplete image

查看:176
本文介绍了RenderTargetBitmap +资源的VisualBrush =图片不完整的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现"Visual to RenderTargetBitmap"问题有了新的变化!

I've found a new twist on the "Visual to RenderTargetBitmap" question!

我正在为设计师渲染WPF素材的预览.这意味着我需要拍摄WPF视觉并将其渲染为位图,而无需显示该视觉.有一个不错的小方法可以做到,就像在这里看到它一样

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;
}

工作正常,除了一件棘手的事情...如果我的FrameworkElement具有VisualBrush,则该笔刷不会最终出现在最终渲染的位图中.像这样:

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 -->

其他所有内容都会渲染到位图,但是VisualBrush不会显示.明显的google解决方案已经尝试并且失败了.甚至那些专门提到VisualBrush的人都从RTB的位图中丢失了.

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?

推荐答案

您有两个问题:

  1. 您未在视觉上设置PresentationSource,因此不会触发Loaded事件.
  2. 您没有刷新分派器队列.如果不刷新Dispatcher队列,使用Dispatcher回调的任何功能将无法正常工作.

您的问题的直接原因是由于VisualBrush使用了刷新Dispatcher队列失败,但是您很可能不久就会遇到PresentationSource问题,因此我将同时解决这两个问题.

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.

这是我的方法:

// Create the container
var container = new Border
{
  Child = contentVisual,
  Background = Brushes.White,
  BorderBrush = Brushes.Black,
  BorderThickness = new Thickness(1),
};

// Measure and arrange the container
container.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
container.Arrange(new Rect(container.DesiredSize));

// Temporarily add a PresentationSource if none exists
using(var temporaryPresentationSource = new HwndSource(new HwndSourceParameters()) { RootVisual = (VisualTreeHelper.GetParent(container)==null ? container : null) })
{
  // Flush the dispatcher queue
  Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() => { }));

  // Render to bitmap
  var rtb = new RenderTargetBitmap((int)b.ActualWidth, (int)b.ActualHeight, 96, 96, PixelFormats.Pbgra32);
  rtb.Render(container);

  return rtb;
}

仅供参考,在任何情况下都不会延迟StaticResource查找:在加载XAML并立即将其替换为从ResourceDictionary检索的值后立即进行处理. StaticResource可能可能相关的 方式是,如果它选择了错误的资源,因为两个资源具有相同的密钥.我只是想我应该解释一下-与您的实际问题无关.

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.

这篇关于RenderTargetBitmap +资源的VisualBrush =图片不完整的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆