【问题标题】:Using newer RichEdit versions?使用较新的 RichEdit 版本?
【发布时间】:2015-04-06 15:08:40
【问题描述】:

我曾尝试在 C# 上使用 RichTextBox,但发现它太慢,无法处理数千行长的文本。经过一番谷歌搜索,我发现这是因为 .net 默认使用 RichEdit 2.0,而解决方案是改用 RichEdit 5.0。

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

效果很好,文本显示在几秒钟而不是几分钟。然而,作为一个不关心个人项目兼容性的人,我想找到更高版本的 RichEdit。我发现最新版本是 8.0,全部作为riched20.dll 发布,部分在 msftedit.dll 中。

http://blogs.msdn.com/b/murrays/archive/2006/10/14/richedit-versions.aspx

http://blogs.msdn.com/b/murrays/archive/2012/03/03/richedit-8-0-preview.aspx

但是,msdn 的文档在 4.1 中停止,(我假设是)该项目的开发人员声称他们不再在上面的博客中做公共文档。

https://msdn.microsoft.com/en-us/library/windows/desktop/bb787873(v=vs.85).aspx

到目前为止,我已经能够显式地运行 msftedit.dll 的 RichEdit 2.0 和 5.0,但所有其他版本都让我望而却步。例如,尽管 John Crenshaw 声称 RichEdit 6.0 工作正常,但我无法使用它。除了上面提到的 msftedit-2.0 和 5.0 组合之外的任何尝试都会在 Application.Run() 处导致“窗口类名称无效”错误。 (该程序是用 C# 编写的,但我没有标记它,因为我担心这个问题可能不是 C# 特定的问题。)代码是第一个链接中解决方案的几乎完全相同的副本,如下所示:

class Textbox : RichTextBox
{
[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 Exception("LoadLibrary Failed with: "+s32_Error);
}

protected override CreateParams CreateParams
{
    get
    {
        CreateParams i_Params = base.CreateParams;
        try
        {
            // Available since XP SP1
            LoadLibrary("MsftEdit.dll"); // throws

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

我所做的是将 ClassName 字符串更改为不同的数字,例如RichEdit60W。

我在 Windows 8.1 上,所以 msftedit.dll 应该有 RichEdit 7.0 或 8.0(博客文章中给出的措辞不清楚),但我无法联系到它们。有什么办法可以纠正这个问题,或者新版本是否保密?

【问题讨论】:

    标签: .net richtextbox richedit


    【解决方案1】:

    我的机器上有 RichEdit 8.0 版,类名 RICHEDIT60W。它存储在 C:\Program Files (x86)\Common Files\Microsoft Shared\OFFICE15\RICHED20.DLL 中。当我为它写一个包装器时它工作得很好:

    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    
    class RichEdit80 : RichTextBox {
        protected override CreateParams CreateParams {
            get {
                if (moduleHandle == IntPtr.Zero) {
                    string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86);
                    path = System.IO.Path.Combine(path, @"Microsoft Shared\OFFICE15\RICHED20.DLL");
                    moduleHandle = LoadLibrary(path);
                    if ((long)moduleHandle < 0x20) throw new Win32Exception(Marshal.GetLastWin32Error(), "RichEdit control appears to be missing");
                }
                CreateParams createParams = base.CreateParams;
                createParams.ClassName = "RichEdit60W";
                if (this.Multiline) {
                    if (((this.ScrollBars & RichTextBoxScrollBars.Horizontal) != RichTextBoxScrollBars.None) && !base.WordWrap) {
                        createParams.Style |= 0x100000;
                        if ((this.ScrollBars & ((RichTextBoxScrollBars)0x10)) != RichTextBoxScrollBars.None) {
                            createParams.Style |= 0x2000;
                        }
                    }
                    if ((this.ScrollBars & RichTextBoxScrollBars.Vertical) != RichTextBoxScrollBars.None) {
                        createParams.Style |= 0x200000;
                        if ((this.ScrollBars & ((RichTextBoxScrollBars)0x10)) != RichTextBoxScrollBars.None) {
                            createParams.Style |= 0x2000;
                        }
                    }
                }
                if ((BorderStyle.FixedSingle == base.BorderStyle) && ((createParams.Style & 0x800000) != 0)) {
                    createParams.Style &= -8388609;
                    createParams.ExStyle |= 0x200;
                }
                return createParams;
            }
        }
    
        private static IntPtr moduleHandle;
    
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr LoadLibrary(string lpFileName);
    }
    

    未经彻底测试。希望您对这段代码感到非常不舒服,它实际上仅足以用于测试目的,看看您是否领先。 DLL 的路径当然是大红旗,当您的机器上没有 Office 2013 时,您必须更改它。要求用户在他的机器上安装正确的 Office 版本,只有当你对运行程序的机器有适当的控制时才会有效。在 LoadLibrary() 失败时使用回退路径在技术上是可行的。

    这个特定版本的作用以及它可能与工具箱中的默认 RichTextBox 不兼容的原因很难进行逆向工程。粗略的猜测是“与 Word 更兼容”。 Later RichEdit versions 例如更好地支持数学方程。只有通过彻底的测试才能找到答案。最好坚持使用 msftedit.dll

    【讨论】:

    • 看起来我遇到了错误,因为我没有兼容的 MSO 版本。是MSO2013,但是riched20.dll存放在System32,不是你描述的那个目录,系统在里面找不到RichEdit60W。 (可能是因为我有东亚版本?或者可能是因为它是企业购买的?谁知道呢?)我猜我会坚持使用 msftedit.dll。感谢您的详细意见。
    • 我收到“窗口类名无效”。错误。你能告诉我如何获得班级名称吗?谢谢
    【解决方案2】:

    RichEdit 似乎主要是作为 Office 的一部分在 Microsoft 开发的,只有 1.0、2.0、3.0 和 4.1 版本包含在 Windows 中。

    其他更高版本的 RichEdit 可以在 Microsoft Office 安装中找到:如果安装了 Office,您必须从它们在“程序文件”下的位置显式 LoadLibrary()。如果没有安装 Office,那么您就不走运了:裸 Windows 中不存在这些其他版本,并且没有再分发许可证允许您以您编写的任何适当的方式分发它们。

    所以,基本上,你不走运。对不起。

    【讨论】:

      猜你喜欢
      • 2012-07-29
      • 2019-02-18
      • 2015-08-02
      • 2020-04-24
      • 1970-01-01
      • 2019-03-20
      • 1970-01-01
      • 2017-04-17
      • 2013-03-18
      相关资源
      最近更新 更多