首页 > 解决方案 > 将文本设置为 RichEdit 控件时处理错误

问题描述

我可以将纯文本设置为带有标志的 RichEdit 控件SF_TEXT,但我不能设置带有标志的 RTF 文本SF_RTF

下面是控件的创建:

    LoadLibrary(TEXT("Riched20.dll"));

    richEdit = CreateWindowEx(
        0,
        RICHEDIT_CLASS,
        TEXT(""),
        ES_MULTILINE | WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP,
        x,
        y,
        width,
        height,
        hwndOwner,
        NULL,
        hInstance,
        NULL);
}

这是我设置文本的方式(我在 SO 的某处举了一个例子),导致“ERROR_INVALID_HANDLE”:

    DWORD CALLBACK EditStreamInCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
    {
        std::wstringstream *rtf = (std::wstringstream*) dwCookie;
        *pcb = rtf->readsome((wchar_t*)pbBuff, cb);
        return 0;
    }

    // ......
    // Setting text
    std::wstringstream rtf(L"{\rtf1Hello!\par{ \i This } is some { \b text }.\par}");
    EDITSTREAM es = { 0 };
    es.dwCookie = (DWORD_PTR)&rtf;
    es.pfnCallback = &EditStreamInCallback;

    if (SendMessage(richEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es) && es.dwError == 0)
    {
        // ...
    } else {
        auto error = GetLastError(); // error == 6
    }

标签: c++winapi

解决方案


RTF 字符串应该是"\\r \\p"etc. not "\r \p",或者使用原始字符串文字。字符串应具有兼容的字体。例如:

std::wstring wrtf = (LR"({\rtf1{\fonttbl\f0\fswiss Helvetica;} 
Hello world Привет Ελληνικά 日本語 { \b bold \b } regular.\par})");

EM_STREAMIN/EM_STREAMOUT期望BYTE输入/输出。

读写标准 RTF 文件时,只读取文件为char,不做任何转换为​​宽字符串,使用这种格式

format = SF_RTF; 

如果源是 UTF16 字符串文字,将其转换为 UTF8,其他一切都保持不变,除了格式更改为:

format = SF_RTF | SF_USECODEPAGE | (CP_UTF8 << 16); 

将 UTF16 字符串文字读取到 RichEdit 控件的示例:

std::string utf8(const std::wstring& wstr)
{
    if (wstr.empty()) return std::string();
    int sz = WideCharToMultiByte(CP_UTF8,0,wstr.c_str(),-1,0,0,0,0);
    std::string res(sz, 0);
    WideCharToMultiByte(CP_UTF8,0,wstr.c_str(),(int)wstr.size(),&res[0],sz,0,0);
    return res;
}

DWORD CALLBACK EditStreamInCallback(
    DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG* pcb)
{
    std::stringstream* rtf = (std::stringstream*)dwCookie;
    *pcb = rtf->readsome((char*)pbBuff, cb);
    return 0;
}

std::stringstream ss(utf8(wrtf));
EDITSTREAM es = { 0 };
es.dwCookie = (DWORD_PTR)&ss;
es.pfnCallback = &EditStreamInCallback;
SendMessage(richedit, EM_STREAMIN, 
    SF_RTF | SF_USECODEPAGE | (CP_UTF8 << 16), (LPARAM)&es);

推荐阅读