5

私は Visual Studio 2008、.NET C# 2.0 ~ 3.5、および Windows Forms を頻繁に使用していますが、GDI+ ではコントロールの描画が非常に遅いことに気付きました。私は画像 (JPG、GIF など) をあまり扱っていないことに注意してください。画像は、特定の場所のアイコンとしてのみ使用されます。これは実際には描画が遅いコントロール/フォーム/その他です。

問題は、コントロールが描画されているのを確認でき、一見簡単に見えるコントロールのセットが描画されるまでに数秒かかる場合があることです。つまり、その遅れと恐ろしい。

いくつかのラベル (40 ~ 50) をフォームに配置し、F5 キーを押して実行し、それらが描画されるのを待つ必要があるテストを行いました。繰り返しますが、ラグがあり、あまり良い経験ではありません。

したがって、この問題に対処する可能性のある WPF がありますが、私/私たちは WPF に移行する準備ができていません。そのため、回避策や修正を探していて、Direct2D に出くわし、他のライブラリを読んでいるときに見つけました。

私は少し困惑しているので、これらの質問をしてください:

1) まず、私が欲しいのは、GDI+ をより高速でハードウェア アクセラレーションされたアプローチに置き換えるための、かなりきちんとしたシンプルな方法です。WPF に移行せず、すべての Windows フォーム コードを書き直さなくても、それを行うことは可能ですか?

Direct2D で何かを読むときはいつでも、描画用のコードを手動で記述する方法を教えてくれる、通常はひどい C++ コードの長いブロックが表示されます。私はそれを望んでいません。

2) ネットで読んでいるときに、SlimDX に出くわしましたが、使い方がわかりません (書いている時点ではあまり試していません)。既に GUI アプリケーション (Windows フォーム、標準 C# コード) を持っているとしましょう。

私の問題は、既に作成した Windows Forms ソフトウェアで SlimDX、Direct2D、またはその他の類似のものを使用できるかどうか、また可能であればその方法を教えてくれる例やそのようなものが見つからないことです。

あいまいすぎないことを願っています=)

==編集== 2010-09-22

私は実際のアプリでいくつかのテストを行い、これに遅いものの1つを分離しました:

UserControl の一部のラベルにテキストを追加すると、テキストに合わせてコントロールのサイズが変更されます。たとえば、含まれている GroupControl は、ラベルの .Text プロパティに追加されたばかりのテキストのサイズに少し適応します。

約 10 個のラベル コントロールがあります。ラベルが初めて更新されてサイズが変更されると、プロセス全体に約 500 ミリ秒かかります。ラベルが 2 回目に更新され、サイズが変更されない場合、約 0 ミリ秒かかります。

==編集2== 2010-09-22

スローダウンの 1 つを見つけました。次に、文字列を Text-property に追加すると、追加されるテキストの文字列の長さが更新前のテキストと異なる場合、処理が遅くなります。

DevExpress ライブラリを使用しており、LabelControls を AutoSizeMode に設定できます。これを「なし」に設定すると、前のテキストとは長さが異なるテキストを追加するときにラグがなくなります。この問題は、AutoSize = true/false 設定もある通常の Label コントロールでも同じであると思います。

ただし、これは「回避策」ですが、それでも私の主張を証明しています。サイズ変更時に非常に遅く、かなり不自由です。

4

5 に答える 5

3

上記のポスターの多くには良い点があります。私自身、GDI+ で 3D CAD アプリケーションを作成しましたが、正しく実装されていれば十分に高速であることがわかりました。ただし、Controls を使用すると、非常に厄介な方法であることがすぐにわかります。Control はかなり大きなオブジェクトであり、この場合独自に作成する理由は数多くあります。

保持モードの描画システムを検討することをお勧めします。実装は簡単で、ほとんどの場合に状況をカバーします。自分で描画ロジックを作成する必要がありますが、それは楽しいだけでなく、より柔軟になります:)

于 2012-03-18T13:58:24.897 に答える
1

私は同じ問題のいくつかを見ています。一部のユーザーは10〜50のウィンドウを同時に開くことができるため、2Dグラフィックスを非常に効率的にレンダリングできる必要があるアプリケーションを作成しています。ここで他の誰も話していないことを考慮すべきことの1つは、direct2dはサービスパック2以降を搭載したVistaを搭載したコンピューターでのみ使用できるという事実です。また、このリンクによると:

http://www.tomshardware.com/news/msft-windows-xp-windows-7-market-share-win7,13876.html

2011年11月の時点で、すべてのWindowsユーザーの38.5%がまだXPを使用しています。したがって、まだXPを実行しているかなりの数のユーザーにアプリを販売することが懸念される場合(または、主にXPを使用している第三世界の国々にマーケットベースがある場合)、次に、次のいずれかを実行する必要があります。

  1. 新しいオペレーティングシステムの場合はDirect2d、XPシステムの場合はGDI+。

  2. XNA-XPと互換性があり、新しいオペレーティングシステムでも使用できます。このリンクを参照してください:http: //msdn.microsoft.com/en-us/library/bb203925.aspx

  3. SlimDX-最初の答えで言及されています。XPおよび新しいオペレーティングシステムをサポートします。参照: http ://slimdx.org/ および http://slimdx.org/features.php

  4. Windows、Linux、Maxなどの間の互換性が気になる場合はOpenTK。

また、GDI +にはバグがあり、最初にリリースされたときにパフォーマンスが非常に低下したことにも注意してください。一部の開発者が、MicrosoftがGDI+を使用するアプリのWindows7のGUIを破ったと主張する理由については、次のリンクを参照してください。

http://www.windows7taskforce.com/view/3607

または、次の文字列を使用して、お気に入りの検索エンジンからWeb検索を実行します:「Windows7ではgdi+のバグが遅い」。

于 2012-02-17T01:27:49.800 に答える
1

あなたの最初の質問では、GDI+ では時間がかかっていた画像処理を行うために GDI を使用する必要がありました。これは 4 ~ 5 年前のことで、マネージ C# を使用して GDI を操作するのは苦痛でした。現在、それがどの程度変化したかはわかりません。描画が非常に高速な BitBlt などの優れた高速関数が多数ありますが、リソース (ハンドル) とメモリの解放には細心の注意を払う必要があります。また、別の問題があり、結果を JPEG として保存していましたが、GDI には存在しないため、CxImage を使用して HBitmap を読み取ってから保存する必要がありました。

全体として、GDI は非常に高速で堅牢です。DirectX に優れた抽象化がある場合は、おそらくそれらを使用したほうがよいでしょう。

于 2010-09-17T12:24:24.307 に答える
0

マネージド directx を試すこともできますが、サポートされなくなりました (XNA に移行しました)。正直なところ、クソみたいなコンピューターや大量のコントロールを持っていない限り、なぜこんなに遅くなるのかわかりません。メイン スレッドで CPU を集中的に使用する処理を行っている場合は、別のスレッドに移動します。それが、そのような遅延を引き起こすと私が考えることができる唯一の他の理由です。

于 2010-09-17T18:32:43.707 に答える
0

私たちは C# アプリで SlimDX を使用しています....しかし、実際には 3D を行っています。簡単な 2D 描画ができるように、独自の 2D ライブラリを作成しました。SlimDX は、DirectX の軽量ラッパーです。したがって、DirectX の長所と短所をすべて把握できます。そのように、ビデオカードが存在しない場合にエミュレートするのはあなたの問題です。

オフスクリーンのビットマップに描画するものが必要な場合は、C# とうまく統合されていて、ほとんどどこでも動作し、ハードウェアが利用できる場合は高速化される WPF を選びます。出力をビットマップにコピーして、通常の 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;
}
于 2010-09-17T12:35:02.113 に答える