Pregunta

He encontrado un nuevo giro a la pregunta "Visual a RenderTargetBitmap"!

Estoy prestando vistas previas de WPF cosas para un diseñador. Eso significa que tengo que tomar un WPF visual y hacerlo a un mapa de bits sin que visual cada vez que se visualiza. ¿Tienes un método poco agradable de hacer que les gusta ver que aquí va

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

funciona bien, excepto por una cosa ... si mi leeetle FrameworkElement tiene una VisualBrush, que el cepillo no terminar en el mapa de bits final renderizada. Algo como esto:

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

Todo lo demás hace que el mapa de bits, pero que VisualBrush simplemente no se mostrará. Las soluciones de Google obvias se han intentado y han fracasado. Incluso los que mencionan específicamente VisualBrushes que faltan de mapas de bits RTB'd.

Tengo una ligera sospecha de que esto podría ser causado por el hecho de que es un recurso y, a ese recurso perezoso no está siendo inline. Por lo que una posible solución sería, de alguna manera (???), la resolución de la fuerza de todas las referencias de recursos estáticos antes de renderizar. Pero no tengo ni idea de cómo hacerlo.

Alguien tiene una solución para esto?

¿Fue útil?

Solución

Existen dos problemas:

  1. No se ha configurado un PresentationSource visuales en sus eventos tan cargado no se disparará.
  2. No se podía tirar la cola Dispatcher. Sin tirar de la cola de Dispatcher, cualquier funcionalidad que utiliza devoluciones de llamada del despachador no funcionará.

La causa inmediata de su problema es la falta de vaciar la cola Dispatcher, ya VisualBrush lo usa, pero es probable que se encontrará con el problema PresentationSource en poco tiempo, así que fijar ambos.

Aquí es cómo lo hago:

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

FYI, StaticResource búsqueda se nunca se retrasó bajo ninguna circunstancia: Se procesa el momento en que se carga el XAML e inmediatamente reemplazado con el valor recuperado del ResourceDictionary. El solamente StaticResource manera podría posiblemente estar relacionado es si recogido el recurso incorrecto debido a que dos recursos tenían la misma clave. Sólo pensé que debería explicar esto - no tiene nada que ver con su problema real

.

Otros consejos

Bueno a inline ella, usted podría hacer algo como esto:

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

Si esto no funciona, creo que ha de ser que tiene que ser algo específico con la instancia Visual que está utilizando (y que requerirá código adicional a un mejor diagnóstico).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top