C# RichEditBox has extremely slow performance (4 minutes loading)

I downloaded the sourcecode of Wordpad (http://download.microsoft.com/download/4/0/9/40946FEC-EE5C-48C2-8750-B0F8DA1C99A8/MFC/ole/wordpad.zip.exe) and it has the same worst performance (4 minutes). But this sample is an old version of Wordpad.

So Microsoft has improved anything in Wordpad in the last years that is missing in the .NET framework.

Finally I found the solution:

The .NET framework uses the RichEdit20W class for the Richedit control as also the old Wordpad does. But the Wordpad of Windows XP uses the new RichEdit50W that has been highly improved by Microsoft.

So how do I tell the .NET framework to use RichEdit50W instead of RichEdit20W ?

This is very easy: Derive a class from RichTextBox and write a managed wrapper for LoadLibary.

The class RichEdit50W is created by MsftEdit.dll which is available since Windows XP SP1. I implemented a fallback to RichEdit20W for the very rare case that someone should still use XP without service pack.

And it works!

/// <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;
    }
}

NOTE: See also 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);
    }
}

Leave a Comment