【问题标题】:Unicode RTF text in RichEditRichEdit 中的 Unicode RTF 文本
【发布时间】:2010-12-19 10:31:34
【问题描述】:

我无法让 RichEdit 控件显示 unicode RTF 文本。我的应用程序是 Unicode,所以所有字符串都是 wchar_t 字符串。
如果我将控件创建为“RichEdit20A”,我可以使用例如SetWindowText,并以正确的格式显示文本。如果我将控件创建为“RichEdit20W”,则使用 SetWindowText 逐字显示文本,即显示所有 RTF 代码。如果我使用 EM_SETTEXTEX 参数,指定代码页 1200,MSDN 告诉我用于指示 unicode,也会发生同样的情况。
我试过使用 StreamIn 函数,但这似乎只有在我以 ASCII 文本流式传输时才有效。如果我在widechars中流式传输,那么我会在控件中得到空文本。我使用 SF_RTF|SF_UNICODE 标志,而 MSDN 提示可能不允许这种组合。

那该怎么办?有什么方法可以在不丢失 RTF 解释的情况下将宽字符放入 RichEdit,还是我需要对其进行编码?我曾考虑尝试 UTF-8,或者可能使用 RTF 中的编码工具,但不确定最佳选择是什么。

【问题讨论】:

    标签: unicode mfc rtf richedit


    【解决方案1】:

    我最近不得不这样做,并注意到你正在做的相同类型的观察。

    看起来,尽管 MSDN 几乎建议,“RTF”解析器仅适用于 8 位编码。所以我最终做的是使用UTF-8,它是一种 8 位编码,但仍然可以表示所有 Unicode 字符。您可以通过WideCharToMultiByte() 从PWSTR 获取UTF-8:

    PWSTR WideString = /* Some string... */;
    DWORD WideLength = wcslen(WideString) + 1;
    PSTR Utf8;
    DWORD Length;
    INT ReturnedLength;
    
    // A utf8 representation shouldn't be longer than 4 times the size
    // of the utf16 one.
    Length = WideLength * 4;
    Utf8 = malloc(Length);
    if (!Utf8) { /* TODO: handle failure */ }
    
    ReturnedLength = WideCharToMultiByte(CP_UTF8,
                                         0,
                                         WideString,
                                         WideLength-1,
                                         Utf8,
                                         Length-1,
                                         NULL,
                                         NULL);
    if (ReturnedLength)
    {
       // Need to zero terminate...
       Utf8[ReturnedLength] = 0;
    }
    else { /* TODO: handle failure */ }
    

    一旦你有了 UTF-8 格式,你就可以这样做:

    SETTEXTEX TextInfo = {0};
    
    TextInfo.flags = ST_SELECTION;
    TextInfo.codepage = CP_UTF8;
    
    SendMessage(hRichText, EM_SETTEXTEX, (WPARAM)&TextInfo, (LPARAM)Utf8);
    

    当然(我最初忽略了这个,但是当我很明确时......):

    free(Utf8);
    

    【讨论】:

    • 完美运行。非常感谢!
    【解决方案2】:

    RTF 是 ASCII,ASCII 之外的任何字符都将使用转义序列进行编码。 RTF 1.9.1 specification (March 2008)

    【讨论】:

    • 文件格式规范可能会这样说,但您可以让 RichEdit 控件加载任何多字节编码的 RTF,包括我的回答中显示的 CP_UTF8。
    【解决方案3】:

    查看 rtf 规范中的 \uN 文字,因此您必须将宽字符串转换为 unicode 字符串,例如 \u902?\u300?\u888? http://www.biblioscape.com/rtf15_spec.htm#Heading9 在这种情况下,数字代表字符十进制代码,问号是如果 RichEdit 不支持 unicode (RichEdit v1.0) 将替换 unicode char 的字符。

    例如,对于 unicode 字符串 L"TIME",rtf 数据将为 "\u84?\u73?\u77?\u69?"

    【讨论】:

    • 它是我成功测试过的解决方案之一,但不是很方便。在这种情况下 rtf 字符串,例如“{\\rtf1 bla bla \\u931?}”(C++ 语言的语法用于编码反斜杠字符)可以用 UTF-16 编码并正确显示。当直接以 UTF-16 编码(无控制字 \uN)即“{\\rtf1 bla bla Σ}”时,希腊字母 sigma(代码 0x03A3)将显示为英镑 £(代码 0xA3)。
    猜你喜欢
    • 2014-04-01
    • 1970-01-01
    • 2014-05-17
    • 1970-01-01
    • 2011-06-01
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多