Quiero agregar una forma de dibujar un VisualBrush a DrawingBrush en otro hilo.
Como todos sabemos, el VisualBrush debe usar en el subproceso de IU y el bloqueo de VisualBrush que no se puede usar en otro hilo.
Si desea utilizar VisualBrush en otro hilo y dibujarlo en DrawingVisual, debe cambiar VisualBrush a Image.
Para cambiar VisualBrush de imagen como el código:
public static BitmapSource ToImageSource(this Brush brush, Size size, double dpiX, double dpiY)
{
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
drawingContext.DrawRectangle(brush, (Pen) null, new Rect(size));
BitmapImage bitmapImage = new BitmapImage();
if (Math.Abs(size.Width) > 0.001 && Math.Abs(size.Height) > 0.001)
{
RenderTargetBitmap bitmap = new RenderTargetBitmap((int) (size.Width * dpiX/96.0), (int) (size.Height * dpiY/96.0), dpiX, dpiY, PixelFormats.Pbgra32);
bitmap.Render((Visual) drawingVisual);
bitmapImage.BeginInit();
bitmapImage.DecodePixelWidth = (int) (size.Width * dpiX/96.0);
bitmapImage.DecodePixelHeight = (int) (size.Height * dpiY/96.0);
bitmapImage.StreamSource = (Stream) bitmap.ToMemoryStream(ImageFormat.Png);
bitmapImage.EndInit();
bitmapImage.Freeze();
}
return (BitmapSource) bitmapImage;
}
y se puede dibujar en el otro hilo.
var drawVisual=VisualBrush.ToImageSource(drawBounds.Size the drawBounds is we give, Dpix you can write 96, Dpiy);
Thread thread = new Thread(() =>
{
var target = new VisualTarget(hostVisual);
s_event.Set();
var dv = new DrawingVisual();
using (var dc = dv.RenderOpen())
{
dc.DrawRectangle(new ImageBrush(drawVisual), new Pen(Brushes.Black, 0.0), drawBounds);
}
target.RootVisual = dv;
}
Pero si debe dibujar una cierta VisualBrush a DrawingVisual y cambiar el DrawingVisual a BitmapImage y mostrar la imagen.
Debe wirte la VsisualBrush a la imagen en UIThread
List<(ImageSource brush, Rect drawBounds)> drawVisual = new List<(ImageSource, Rect)>();
foreach (var temp in Elements)
{
UIElement element = temp;
Rect descendantBounds = VisualTreeHelper.GetDescendantBounds(element);
var drawBounds = descendantBounds;
drawBounds.Offset(temp location - new Point());
await Dispatcher.InvokeAsync(() =>
{
var brush = new VisualBrush(element);
drawVisual.Add((brush.ToImageSource(drawBounds.Size, Dpix, Dpiy), drawBounds));
}, DispatcherPriority.Input);
}
Para VisualTaget debe utilizar el Visual, cómo cambiar el DrawingVisual a BitmapImage y muestran?
HostVisual hostVisual = new HostVisual();
List<(ImageSource brush, Rect drawBounds)> drawVisual = new List<(ImageSource, Rect)>();
foreach (var temp in Elements)
{
Element element = temp;
Rect descendantBounds = VisualTreeHelper.GetDescendantBounds(element);
var drawBounds = descendantBounds;
drawBounds.Offset(temp.Bounds.Location - new Point());
await Dispatcher.InvokeAsync(() =>
{
var brush = new VisualBrush(element);
drawVisual.Add((brush.ToImageSource(drawBounds.Size, Dpi.System.X, Dpi.System.Y), drawBounds));
}, DispatcherPriority.Input);
}
Thread thread = new Thread(() =>
{
var target = new VisualTarget(hostVisual);
s_event.Set();
var dv = new DrawingVisual();
using (var dc = dv.RenderOpen())
{
foreach (var temp in drawVisual)
{
dc.DrawRectangle(new ImageBrush(temp.brush), new Pen(Brushes.Black, 0.0), temp.drawBounds);
}
}
var bounds = VisualTreeHelper.GetDescendantBounds(dv);
var width = (int) Math.Round(bounds.Width);
var height = (int) Math.Round(bounds.Height);
var bitmap = new RenderTargetBitmap((int) Math.Round(width * Dpi.System.FactorX),
(int) Math.Round(height * Dpi.System.FactorY), Dpi.System.X, Dpi.System.Y,
PixelFormats.Pbgra32);
bitmap.Render(dv);
dv = new DrawingVisual();
using (var dc = dv.RenderOpen())
{
dc.DrawImage(bitmap, new Rect(size));
}
target.RootVisual = dv;
System.Windows.Threading.Dispatcher.Run();
});
thread.TrySetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
s_event.WaitOne();
VisualHost.Child = hostVisual;
El elemento es nuestro CustomControl que tiene una propiedad para obtener su ubicación.
Pero no es una buena manera para Dispatcher.InvokeAsync necesita demasiado tiempo.
DwayneNeed usa HostVisual para dibujar el pincel, pero cuando el Pincel es VisualBrush, en el subproceso UI, no lo dibujará en otro subproceso. – lindexi