RenderTargetBitmap + Resource'd VisualBrush = неполное изображение

Я нашел новое скручивание на "Визуальным к 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;
}

Хорошо работает, за исключением одной leeetle вещи..., если мой FrameworkElement имеет VisualBrush, та кисть не заканчивается в финале, представленном битовым массивом. Что-то вроде этого:

<UserControl.Resources>
    <VisualBrush
        x:Key="LOLgo">
        <VisualBrush.Visual>
            <!-- blah blah -->
<Grid 
    Background="{StaticResource LOLgo}">
<!-- yadda yadda -->

Все остальное представляет к битовому массиву, но который просто не покажет VisualBrush. Очевидные решения Google были предприняты и перестали работать. Даже те, которые конкретно упоминают VisualBrushes, отсутствующий в битовых массивах RTB'd.

У меня есть подлое подозрение, это могло бы быть вызвано тем, что это - Ресурс, и что ленивый ресурс не встраивается. Таким образом, возможная фиксация была бы к, так или иначе (???), разрешение силы всех статических ссылок ресурса перед рендерингом. Но у меня нет абсолютно никакой идеи, как сделать это.

У кого-либо есть фиксация для этого?

8
задан 17 May 2010 в 17:24
поделиться

2 ответа

У вас две проблемы:

  1. Вы не установили PresentationSource для вашего визуального объекта, поэтому события Loaded не срабатывают.
  2. Вы не промыли очередь диспетчера. Без промывки очереди диспетчера любая функциональность, использующая обратные вызовы диспетчера, не будет работать.

Непосредственной причиной вашей проблемы является неспособность промыть очередь диспетчера, поскольку VisualBrush использует ее, но вы, вероятно, столкнетесь с проблемой PresentationSource в ближайшее время, поэтому я бы исправил обе эти проблемы.

Вот как я это делаю:

// 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 может возможно быть связан, это если он подбирает неправильный ресурс, потому что два ресурса имеют одинаковый ключ. Я просто подумал, что должен объяснить это - это не имеет никакого отношения к вашей реальной проблеме.

14
ответ дан 5 December 2019 в 12:08
поделиться

Чтобы встроить это, вы можете просто сделать что-то вроде этого:

<Grid>
    <Grid.Background>
        <VisualBrush>
            <VisualBrush.Visual>
                <!-- blah blah -->
            </VisualBrush.Visual>
        </VisualBrush>
    </Grid.Background>
</Grid>

Если это не сработает, я предполагаю, что это должно быть что-то особенное с Visual , который вы используете (и для лучшей диагностики потребуется дополнительный код).

0
ответ дан 5 December 2019 в 12:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: