16

RichEditBoxC#のコントロール (私は VS 2005 を使用しています) のパフォーマンスが悪いです。45.000 行の色付きテキストを含む 2.5 MB の RTF ファイルをコントロールにロードすると、4 分かかります。Windows XP のワードパッドの RTF コントロールに同じ RTF をロードすると、2 秒でロードされます。

ワードパッドは、私のアプリケーションよりも 120 倍高速に実行されます。

何が原因で、どうすれば修正できますか?

4

1 に答える 1

23

Wordpad のソースコード ( http://download.microsoft.com/download/4/0/9/40946FEC-EE5C-48C2-8750-B0F8DA1C99A8/MFC/ole/wordpad.zip.exe ) をダウンロードしましたが、同じです。最悪のパフォーマンス (4 分)。ただし、このサンプルは古いバージョンのワードパッドです。

このように、Microsoft は過去数年間で、.NET フレームワークに欠けていたワードパッドのすべてを改善しました。

最後に、解決策を見つけました:

.NET フレームワークは、古いワードパッドと同様に、Richedit コントロールに RichEdit20W クラスを使用します。しかし、Windows XP のワードパッドは、Microsoft によって大幅に改良された新しい RichEdit50W を使用しています。

では、RichEdit20W の代わりに RichEdit50W を使用するように .NET フレームワークに指示するにはどうすればよいでしょうか。

これは非常に簡単です。RichTextBox からクラスを派生させ、LoadLibary のマネージ ラッパーを作成します。

クラス RichEdit50W は、Windows XP SP1 以降で使用可能な MsftEdit.dll によって作成されます。サービス パックなしで XP を使用する必要があるという非常にまれなケースのために、RichEdit20W へのフォールバックを実装しました。

そしてそれはうまくいきます!

/// <summary>
/// The framework uses by default "Richedit20W" in RICHED20.DLL.
/// This needs 4 minutes to load a 2,5MB RTF file with 45000 lines.
/// Richedit50W needs only 2 seconds for the same RTF document !!!
/// </summary>
protected override CreateParams CreateParams
{
    get
    {
        CreateParams i_Params = base.CreateParams;
        try
        {
            // Available since XP SP1
            Win32.LoadLibrary("MsftEdit.dll"); // throws

            // Replace "RichEdit20W" with "RichEdit50W"
            i_Params.ClassName = "RichEdit50W";
        }
        catch
        {
            // Windows XP without any Service Pack.
        }
        return i_Params;
    }
}

注: http://msdn.microsoft.com/en-us/library/windows/desktop/bb787873%28v=vs.85%29.aspxも参照してください。

public class Win32
{
    [DllImport("kernel32.dll", EntryPoint="LoadLibraryW", CharSet=CharSet.Unicode, SetLastError=true)]
    private static extern IntPtr LoadLibraryW(string s_File);

    public static IntPtr LoadLibrary(string s_File)
    {
        IntPtr h_Module = LoadLibraryW(s_File);
        if (h_Module != IntPtr.Zero)
            return h_Module;

        int s32_Error = Marshal.GetLastWin32Error();
        throw new Win32Exception(s32_Error);
    }
}
于 2013-09-07T01:59:49.243 に答える