等效于 wpf 中的 CreateGraphics

本文关键字:中的 CreateGraphics wpf | 更新日期: 2023-09-27 17:56:14

所以,我用了winForms 。创建图形来绘制各种不同的东西,从线条到框再到图像。它非常活泼,反应迅速。

我正在尝试用 C# 学习 WPF

我发现 WPF 允许我将矩形对象"添加"到画布上,这将正确显示它们。但是,我有时会绘制数十万个矩形,并且绘制速度可能会变得非常慢,并且当我移动其中一个矩形时,UI 变得不那么活泼。

直接在 winForms 中的元素上绘画不是很快,但无论我绘制多少,它都是一致的。

是否有类似的解决方案可以在 WPF 中执行此操作?

我尝试向System.Drawing添加一个 linq ,这给了我一个Graphics对象,但我尝试的 wpf 元素都没有 .CreateGraphics() 方法。

等效于 wpf 中的 CreateGraphics

WPF 使用与 WinForms 不同的图形操作模型。

使用WinForms,您可以直接编辑屏幕上的像素。 绘制像素后,矩形的概念将丢失。 绘制像素是一项非常快速的操作。

使用 WPF,您不能控制屏幕上的像素。 直接绘制是。 DirectDraw 是一个基于矢量的合成引擎。 您不绘制像素。 定义矢量形状(或视觉对象)。 形状或矩形的概念将保留,即使在图像呈现到屏幕上后也是如此。 添加与其他矩形重叠的新矩形时,需要重绘所有其他矩形。这可能是您的性能下降的地方。 使用 WinForms 时不会发生这种情况。

您可以通过重写 OnRender 来稍微提高 WPF 的性能。 您可以削减矩形对象的开销并直接提供视觉对象。 但是,您仍然没有将像素绘制到屏幕上。 您正在定义 DirectDraw 用于呈现图像的形状。 在这方面,OnRender名称可能有点误导。

我相信您可以找到很多技巧来提高应用程序在 WPF 中的性能。 有一些方法仍然可以绘制像素 - 但这有点违背了 WPF 的重点。

你在做什么需要数千个矩形?

您需要创建一个重写 OnRender 的控件,并在其中进行绘制。无法绘制到另一个控件上,但控件可以自行绘制。

此外,请记住,WPF 使用保留的图形,因此,如果更改某些内容,则需要根据需要使视觉对象失效。

编辑:

像这样:

public class MyControl : Control {
    public MyControl() {
       this.Rects = new ObservableCollection<Rect>();
       // TODO: attach to CollectionChanged to know when to invalidate visual
    }
    public ObservableCollection<Rect> Rects { get; private set; }
    protected override void OnRender(DrawingContext dc) {
        SolidColorBrush mySolidColorBrush  = new SolidColorBrush();
        mySolidColorBrush.Color = Colors.LimeGreen;
        Pen myPen = new Pen(Brushes.Blue, 10);
        foreach (Rect rect in this.Rects)
            dc.DrawRectangle(mySolidColorBrush, myPen, rect);
    }
}

如前所述,WPF 使用保留图形方法,因此您实际上在内存中创建 100,000 个 Rectangle 对象,然后绘制所有对象。 速度减慢可能是由于垃圾回收和一般内存问题。

除了重写 OnRender 方法之外,您还可以研究以下几件事。

  1. 使用熟悉的 GDI 方法将矩形绘制到后台线程中的图像,然后将结果写入 WPF 可写位图

  2. 使用 D3DImage 并利用硬件加速。 这需要您了解 DirectX(或 Direct2D)库。 如果你对这种方法感兴趣,我建议你看看SlimDx。

问题很可能不是 WPF 无法呈现 1000 多个图形对象,而是您在 WPF 对象层次结构中创建和添加的项目太靠前。 毕竟,它确实使用GPU进行所有图形咕噜声工作。

应尽可能接近"Visual"类添加对象,一旦开始基于后一个"UIElement"添加对象,就会要求 WPF 跟踪每个对象的用户单击、悬停等,而不仅仅是绘制它。