- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当我使用 WPF 绘制许多简单的形状时,我不需要阻止 UI。
在 WinForms 中,我会设置后台缓冲区并绘制到后台线程上的缓冲区,然后将生成的缓冲区绘制到控件。它运作良好。
在 WPF 中,我尝试过使用 DrawingVisual,但它似乎在编写绘图时阻塞了 UI 线程。
我如何将 DrawingVisual.RenderOpen() 下的所有内容移动到后台线程上,以便在它工作时 UI 线程不会被阻塞?
最佳答案
我想添加一种在其他线程中将 VisualBrush 绘制到 DrawingBrush 的方法。
众所周知,VisualBrush 应该在 UI 线程中使用,而 VisualBrush 不能卡住,不能在其他线程中使用。
如果要在其他线程中使用 VisualBrush 并将其绘制到 DrawingVisual ,则应将 VisualBrush 更改为 Image。
要将 VisualBrush 更改为 Image 作为代码:
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;
}
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;
}
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);
}
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;
关于.net - 后台线程上的 WPF DrawingVisual?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6084585/
我创建自己的 FrameworkElement并覆盖 VisualChildrenCount{get;}和 GetVisualChild(int index)通过返回我自己的 DrawingVisua
我想给我的 DrawingVisual 一个模糊效果.我可以使用 BitmapEffect 来做到这一点属性如: DrawingVisual drawingVisual = new DrawingVi
我的代码在性能方面存在一些问题......我需要将多种颜色的矩形渲染到我的 DrawingVisual。 第一个版本很简单: using (DrawingContext dc = Canvas.Ren
当我使用 WPF 绘制许多简单的形状时,我不需要阻止 UI。 在 WinForms 中,我会设置后台缓冲区并绘制到后台线程上的缓冲区,然后将生成的缓冲区绘制到控件。它运作良好。 在 WPF 中,我尝试
我有一个 DrawingVisual例如,我使用此方法创建的对象: Private Function CreateDrawingVisualRectangle() As DrawingVisual
我正在开发WPF MVVM应用程序。它具有从Canvas继承的自定义 Canvas 类。有一个窗口,其中放置了一个自定义 Canvas (使用XAML),并且其背景色设置为Transaparent。使
我有一个 DrawingVisual对象,我想更改它的填充和描边。 我已经为 Fill 尝试过这个: DrawingVisual MyDrawing = new DrawingVisual(); Se
使用 Visual C# 2010,我正在尝试根据从 Windows Kinect 接收到的帧编写一个 .avi 文件。使用 BitmapEncoder 和 PngBitmapEncoder(保存到流
我有一个继承自 Canvas 的 DerivedCanvas 类。我用它来绘制几个自定义绘图视觉效果,但无法弄清楚如何将 Button 对象添加为 DrawingVisual 对象的子对象。下面是我在
MSDN 写道: DrawingVisual is a lightweight drawing class that is used to render shapes, images, or text
我正在尝试在 System.Windows.Media.DrawingVisual 中绘制一些东西,但我需要以毫米为单位绘制薄片。我该怎么做? 最佳答案 在 WPF 中,您甚至无法在不付出额外努力的情
我正在尝试实现一种算法,该算法将找到最佳比例系数和最佳角度来定位图形,使其不与容器的边缘重叠并且采用最佳角度(由图形尽可能宽的角度定义)。我正在使用 DrawingVisual来代表这个数字。 我现在
我有一个绘图视觉对象,我有绘图,如何将它添加到我的 Canvas 并显示? DrawingVisual drawingVisual = new DrawingVisual(); // Retrie
我创建了一个最小的项目,以便“开始”在 WPF 中使用 DrawingVisuals 进行绘图(到目前为止我还是初学者)。 我的项目仅包含主窗口的 XAML 和隐藏代码。该项目的唯一目的是打开一个窗口
我正在开发一个类似游戏的应用程序,它有多达一千种形状(椭圆和线条),以 60fps 的速度不断变化。阅读了 excellent article on rendering many moving sha
我正在尝试使用 MouseButtonEventHandler 在 Canvas 中添加绘图可视对象。但是无法获取点击事件。我在这里做错了什么? public class VisualHost : U
我看过几个关于在 WPF 中渲染 1 像素线的示例,但似乎没有一个适用于我的情况。我正在使用 DrawingVisual 和 DrawingContext 来绘制一些形状,并使用 RenderTarg
用例:我使用 WPF 在 Web 上下文中的图像上动态叠加文本。 解决方案: 我正在使用 DrawingContext来自 DrawingVisual (包裹在 using 语句中)绘制原始位图和覆盖
我有一个类继承了 InkCanvas 类。我覆盖了 VisualChildrenCount 属性和 GetVisualChild 方法: Visual GetVisualChild(int index
我正在 WPF 中开发一个项目,该项目每秒更新 View 高达 30 次。据我所知,我正在使用 MVVM 模式,并且对目前的结果相当满意。但是我想知道是否有更有效的方法来更新我的主机容器中 Visua
我是一名优秀的程序员,十分优秀!