C# Direct2D/GDI+;和缓慢的Windows窗体绘图-可以做什么?

C# Direct2D/GDI+;和缓慢的Windows窗体绘图-可以做什么?,c#,gdi,direct2d,slimdx,devexpress-windows-ui,C#,Gdi,Direct2d,Slimdx,Devexpress Windows Ui,我经常使用Visual Studio 2008、.NET C#2.0-3.5和Windows窗体,我注意到,像我之前的许多人一样,GDI+在绘图控件方面非常慢注意我不太处理图像(JPG、GIF等)。图像仅在某些位置作为图标显示。这实际上是绘制速度较慢的控件/窗体/等 问题在于,您可以看到正在绘制控件,而绘制一组看似简单的控件可能需要几秒钟的时间。也就是说,它落后而可怕 我做了一些测试,我只是在一个表单上放置了一些标签(40-50),点击F5运行,然后等待它们被绘制出来。再说一次,这不是一次很好的

我经常使用Visual Studio 2008、.NET C#2.0-3.5和Windows窗体,我注意到,像我之前的许多人一样,GDI+在绘图控件方面非常慢注意我不太处理图像(JPG、GIF等)。图像仅在某些位置作为图标显示。这实际上是绘制速度较慢的控件/窗体/等

问题在于,您可以看到正在绘制控件,而绘制一组看似简单的控件可能需要几秒钟的时间。也就是说,它落后而可怕

我做了一些测试,我只是在一个表单上放置了一些标签(40-50),点击F5运行,然后等待它们被绘制出来。再说一次,这不是一次很好的经历

因此,WPF可能会解决这个问题,但我/我们还没有准备好转移到WPF。所以我四处寻找解决方法或修复方法,我偶然发现了Direct2D,当我阅读其他一些库时

让我有点困惑,因此这些问题:

1) 首先,我想要的是一种相当简洁的方法,用更快、硬件加速的方法取代GDI+。有没有可能不用去WPF,也不用重写我所有的Windows窗体代码就可以做到这一点

每当我在Digt2D上读到任何东西时,我就会看到很多通常是可怕的C++代码,告诉我如何手工编写代码来绘图。我不想那样

2) 在网上阅读时,我偶然发现了SlimDX,但我不知道如何使用它(我承认,我在写作方面也没有做过很多尝试)。假设我已经有了一个GUI应用程序(Windows窗体、标准C#代码)——我能用SlimDX(或类似的东西)来“替换”GDI+而不需要太多重写吗

我的问题是,我找不到任何例子或类似的例子来告诉我,在我已经创建的Windows窗体软件中是否可以使用SlimDX、Direct2D或其他类似的东西,如果可能的话,如何做到这一点

希望我不是太模糊=)

==EDIT==2010-09-22

我已经在我的真实应用程序中进行了一些测试,并将其中一个缓慢的事情与此隔离:

当我向UserControl中的某些标签添加文本时,这些控件会调整自身大小以适应文本。例如,包含的GroupControl会根据刚刚添加到标签的.text属性中的文本大小调整一点

大约有10个标签控件。第一次更新标签并更改尺寸时,整个过程大约需要500 ms。第二次更新标签且尺寸没有更改时,大约需要0 ms

==编辑2==2010-09-22

发现了一个减速器。然后,如果正在添加的文本的字符串长度与更新之前的文本长度不同,则将字符串添加到文本属性的速度较慢

Im使用DevXPress库,LabelControls可以设置为AutoSizeMode。如果我将其设置为“无”,那么当添加长度与前一个文本不同的文本时,延迟将消失。我想这个问题对于普通标签控件也是一样的,因为它也有一个AutoSize=true/false设置


然而,这是一个“变通方法”,但仍然证明了我的观点——调整大小时速度非常慢,这是非常糟糕的。

关于你的第一个问题,我不得不使用GDI来做一些图像处理的事情,在GDI+下需要花费很长时间。这是4-5年前的事了,使用托管C#与GDI合作是一件痛苦的事——不知道它现在改变了多少。有很多好的和快速的函数,比如BitBlt,它们在绘图时非常快,但是在释放资源(句柄)和内存时需要非常小心。我还有另一个问题,那就是将结果保存为JPEG,而它在GDI中不存在,因此我必须使用CxImage读取HBitmap,然后保存它

总之,GDI非常快速和健壮。如果DirectX中有更好的抽象,那么您最好使用它们。

我们在C#app中使用SlimDX。。。。但我们实际上在做3D。我们编写了自己的2D库,以便能够进行简单的2D绘图。SlimDX只是DirectX的一个轻量级包装器。因此,您将获得DirectX的所有优点和缺点。像这样,如果没有显卡,你的问题是模仿它

如果你想在屏幕外绘制位图,我会选择WPF,因为它与C#集成得很好,几乎在任何地方都能工作,并且在有硬件可用时可以加速。您可以将输出复制到位图,并在常规GDI/Winforms中使用该位图。但是如果你做一些相当复杂的事情(大量的过滤器,混合纹理等等),它只会比GDI+更快

编辑:

为了回应这些评论,我构建了一个小示例表单。第一次切换时会有几秒钟的等待,但之后会有响应。比我预期的慢,但无论如何都是可用的。如果这是关于他在应用程序中看到的性能,请Ted发表评论

public class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        // *** EDIT ***
        this.tabPage1.SuspendLayout();
        this.tabPage2.SuspendLayout();
        this.tabControl1.SuspendLayout();
        this.SuspendLayout();

        FillTab(tabPage1, Color.White);
        FillTab(tabPage2, Color.Yellow);

        // *** EDIT ***
        this.tabPage1.ResumeLayout(false);
        this.tabPage2.ResumeLayout(false);
        this.tabControl1.ResumeLayout(false);
        this.ResumeLayout(false);
    }

    private static void FillTab(TabPage tabPage, Color color)
    {
        for (int i = 0; i < 200; ++ i)
        {
            int left = (i % 5) * 320;
            int topOffset = (i / 5) * 23;
            tabPage.Controls.Add(new Label { Left = left, Top = topOffset, Width = 100, Text = "Label" });
            tabPage.Controls.Add(new TextBox() { BackColor = color, Left = left + 100, Top = topOffset, Width = 100, Text = tabPage.Text });
            tabPage.Controls.Add(new ComboBox { BackColor = color, Left = left + 200, Top = topOffset, Width = 100 });
        }

    }

    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.tabControl1 = new System.Windows.Forms.TabControl();
        this.tabPage1 = new System.Windows.Forms.TabPage();
        this.tabPage2 = new System.Windows.Forms.TabPage();
        this.tabControl1.SuspendLayout();
        this.SuspendLayout();
        // 
        // tabControl1
        // 
        this.tabControl1.Controls.Add(this.tabPage1);
        this.tabControl1.Controls.Add(this.tabPage2);
        this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
        this.tabControl1.Location = new System.Drawing.Point(0, 0);
        this.tabControl1.Name = "tabControl1";
        this.tabControl1.SelectedIndex = 0;
        this.tabControl1.Size = new System.Drawing.Size(292, 266);
        this.tabControl1.TabIndex = 0;
        // 
        // tabPage1
        // 
        this.tabPage1.Location = new System.Drawing.Point(4, 22);
        this.tabPage1.Name = "tabPage1";
        this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
        this.tabPage1.Size = new System.Drawing.Size(284, 240);
        this.tabPage1.TabIndex = 0;
        this.tabPage1.Text = "tabPage1";
        this.tabPage1.UseVisualStyleBackColor = true;
        // 
        // tabPage2
        // 
        this.tabPage2.Location = new System.Drawing.Point(4, 22);
        this.tabPage2.Name = "tabPage2";
        this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
        this.tabPage2.Size = new System.Drawing.Size(245, 217);
        this.tabPage2.TabIndex = 1;
        this.tabPage2.Text = "tabPage2";
        this.tabPage2.UseVisualStyleBackColor = true;
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(292, 266);
        this.Controls.Add(this.tabControl1);
        this.Name = "Form1";
        this.Text = "Form1";
        this.tabControl1.ResumeLayout(false);
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.TabControl tabControl1;
    private System.Windows.Forms.TabPage tabPage1;
    private System.Windows.Forms.TabPage tabPage2;
}
公共类表单1:表单
{
公共表格1()
{
初始化组件();
//***编辑***
this.tabPage1.SuspendLayout();
this.tabPage2.SuspendLayout();
this.tabControl1.SuspendLayout();
这个.SuspendLayout();
FillTab(tabPage1,颜色为白色);
FillTab(tabPage2,颜色为黄色);
//***编辑***
此.tabPage1.ResumeLayout(false);
此.tabPage2.ResumeLayout(false);
this.tabControl1.ResumeLayout(false);
此选项为.resume布局(false);
}
专用静态空白填充选项卡(选项卡页选项卡页,颜色)
{
对于(int i=0;i<200;++i)
{
左整数=(i%5)*320;
int拓扑偏移=(i/5)*23;
添加(新标签{Left=Left,Top=topOffset,Width=100,Text=“Label”});
tabPage.Controls.Add(new TextBox(){BackColor=color,Left=Left+100,Top=topOffset,Wid