将文本设置为 RichEdit 控件时句柄错误
Wrong handle while setting text to RichEdit control
我可以使用 SF_TEXT
标志将纯文本设置为 RichEdit 控件,但我不能使用 SF_RTF
标志将 RTF 文本设置为 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
}
RTF 字符串应该是 "\r \p"
等而不是 "\r \p"
,或者使用原始字符串文字。该字符串应具有兼容的字体。例如:
std::wstring wrtf = (LR"({\rtf1{\fonttbl\f0\fswiss Helvetica;}
Hello world Привет Ελληνικά 日本語 { \b bold \b } regular.\par})");
EM_STREAMIN/EM_STREAMOUT
期待 BYTE
input/output.
当reading/writing标准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);
我可以使用 SF_TEXT
标志将纯文本设置为 RichEdit 控件,但我不能使用 SF_RTF
标志将 RTF 文本设置为 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
}
RTF 字符串应该是 "\r \p"
等而不是 "\r \p"
,或者使用原始字符串文字。该字符串应具有兼容的字体。例如:
std::wstring wrtf = (LR"({\rtf1{\fonttbl\f0\fswiss Helvetica;}
Hello world Привет Ελληνικά 日本語 { \b bold \b } regular.\par})");
EM_STREAMIN/EM_STREAMOUT
期待 BYTE
input/output.
当reading/writing标准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);