无法在richit中保留换行符
Unable to preserve newlines in RichEdit
我有问题,从一个RichEdit控件保存新闻行在字符串内。我要做的是:
- 从richit控件获取文本
- 拆分所有以空格分隔的内容
- 添加一些RTF格式
- "熔合"单词
- 发送文本到控件
我不确定是什么原因导致的,所以这里是最相关的部分:
int RichEdit::GetTextLength() const
{
GETTEXTLENGTHEX len;
len.codepage = 1200;
len.flags = GTL_NUMBYTES;
return (int)SendMessage(this->handle, EM_GETTEXTLENGTHEX, (WPARAM)&len, 0) + 1;
}
tstring RichEdit::GetText() const
{
auto len = this->GetTextLength();
GETTEXTEX str;
TCHAR* tmp = new TCHAR[len];
str.cb = len;
str.flags = GT_USECRLF;
str.codepage = 1200;
str.lpDefaultChar = NULL;
str.lpUsedDefChar = NULL;
(void)SendMessage(this->handle, EM_GETTEXTEX, (WPARAM)&str, (LPARAM)tmp);
tstring ret(tmp);
delete[] tmp;
return ret;
}
void RichEdit::SetRtfText(const tstring& text, int flags)
{
DWORD WideLength = text.length();
DWORD Length = WideLength * 4;
PSTR Utf8 = (PSTR)malloc(Length);
int ReturnedLength = WideCharToMultiByte(CP_UTF8,
0,
text.c_str(),
WideLength-1,
Utf8,
Length-1,
NULL,
NULL);
if (ReturnedLength)
Utf8[ReturnedLength] = 0;
SETTEXTEX st = {0};
st.flags = flags;
st.codepage = CP_UTF8;
(void)SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)Utf8 );
free(Utf8);
}
void split ( tstring input , tstring split_id, std::vector<std::pair<tstring,bool>>& res ) {
std::vector<std::pair<tstring,bool>> result;
int i = 0;
bool add;
tstring temp;
std::wstringstream ss;
size_t found;
tstring real;
int r = 0;
while ( i != input.length() )
{
add = false;
ss << input.at(i);
temp = ss.str();
found = temp.find(split_id);
if ( found != tstring::npos )
{
add = true;
real.append ( temp , 0 , found );
} else if ( r > 0 && ( i+1 ) == input.length() )
{
add = true;
real.append ( temp , 0 , found );
}
if ( add )
{
result.emplace_back(std::make_pair(real,false));
ss.str(tstring());
ss.clear();
temp.clear();
real.clear();
r = 0;
}
i++;
r++;
}
res = result;
}
ps: tstring只是std::wstring/std::string
的类型定义如何保留换行符?
你的代码有不少问题。
你的代码是基于TCHAR
的,但你实际上并没有正确地使用TCHAR
检索/设置RTF数据。
在检索文本时,您将换行符规范化为CRLF,但在检索文本长度时,您没有进行相同的规范化,因此它们将彼此不同步。
您正在使用UTF-8向richit写入数据,但是RTF是一种基于ascii的格式,它对Unicode数据使用转义序列。如果要以Unicode格式检索数据,那么也可以使用Unicode编写数据,并确保一开始就正确地执行了所有这些操作。让RichEdit控件为你处理Unicode。
您使用WideCharToMultiByte()
是错误的。您根本不应该从字符串长度中减去-1。您可能会尝试考虑空终止符,但是长度值一开始不包括空终止符。如果你要坚持使用UTF-8,那么你应该使用WideCharToMultiByte()
来计算正确的UTF-8长度,而不是硬编码它。
int Length = WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), NULL, 0, NULL, NULL);
char Utf8 = new char[Length+1];
WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), Utf8, Length, NULL, NULL);
Utf8[Length] = 0;
...
delete[] Utf8;
话虽如此,如果你打算坚持使用TCHAR
,那么试试这个:
#ifdef UNICODE
#define RTFCodePage 1200
#else
#define RTFCodePage CP_ACP
#endif
int RichEdit::GetTextLength() const
{
GETTEXTLENGTHEX len = {0};
len.codepage = RTFCodePage;
len.flags = GTL_NUMCHARS | GTL_USECRLF;
return SendMessage(this->handle, EM_GETTEXTLENGTHEX, (WPARAM)&len, 0);
}
tstring RichEdit::GetText() const
{
int len = this->GetTextLength() + 1;
GETTEXTEX str = {0};
str.cb = len * sizeof(TCHAR);
str.flags = GT_USECRLF;
str.codepage = RTFCodePage;
vector<TCHAR> tmp(len);
len = SendMessage(this->handle, EM_GETTEXTEX, (WPARAM)&str, (LPARAM)&tmp[0]);
return tstring(&tmp[0], len-1);
}
void RichEdit::SetRtfText(const tstring& text, int flags)
{
SETTEXTEX st = {0};
st.flags = flags;
st.codepage = RTFCodePage;
#ifdef UNICODE
st.flags |= ST_UNICODE;
#endif
SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)text.c_str());
}
最好放弃TCHAR
,只使用Unicode:
int RichEdit::GetTextLength() const
{
GETTEXTLENGTHEX len = {0};
len.codepage = 1200;
len.flags = GTL_NUMCHARS | GTL_USECRLF;
return SendMessage(this->handle, EM_GETTEXTLENGTHEX, (WPARAM)&len, 0);
}
wstring RichEdit::GetText() const
{
int len = this->GetTextLength() + 1;
GETTEXTEX str = {0};
str.cb = len * sizeof(WCHAR);
str.flags = GT_USECRLF;
str.codepage = 1200;
vector<WCHAR> tmp(len);
len = SendMessage(this->handle, EM_GETTEXTEX, (WPARAM)&str, (LPARAM)&tmp[0]);
return wstring(tmp, len-1);
}
void RichEdit::SetRtfText(const wstring& text, int flags)
{
SETTEXTEX st = {0};
st.flags = flags | ST_UNICODE;
st.codepage = 1200;
SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)text.c_str());
}
更新:如果你必须回到UTF-8的EM_SETTEXTEX
消息,然后尝试这个:
void RichEdit::SetRtfText(const tstring& text, int flags)
{
string Utf8;
int Length;
#ifdef UNICODE
Length = WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), NULL, 0, NULL, NULL);
if (Length > 0)
{
Utf8.resize(Length);
WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), &Utf8[0], Length, NULL, NULL);
}
#else
Length = MultiByteToWideChar(CP_ACP, 0, text.c_str(), text.length(), NULL, 0);
if (Length > 0)
{
vector<WCHAR> tmp(Length);
MultiByteToWideChar(CP_ACP, 0, text.c_str(), text.length(), &tmp[0], Length);
Length = WideCharToMultiByte(CP_UTF8, 0, tmp.c_str(), tmp.length(), NULL, 0, NULL, NULL);
if (Length > 0)
{
Utf8.resize(Length);
WideCharToMultiByte(CP_UTF8, 0, tmp.c_str(), tmp.length(), &Utf8[0], Length, NULL, NULL);
}
}
#endif
SETTEXTEX st = {0};
st.flags = flags & ~ST_UNICODE;
st.codepage = CP_UTF8;
SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)Utf8.c_str());
}
相关文章:
- 如何防止clang格式在流运算符调用之间添加换行符<<
- C/C++ - 查询平台相关的换行符(用于内存映射文件)
- 在 Stream C++ 文本之前有一个额外的换行符
- 流:CSV 文件中的换行符
- 如何在三元条件运算符中添加换行符和连接? :在 C++ 中
- Clang-格式:在多行语句之后的换行符上打开大括号
- 在输出流中插入换行符
- 防止控制台在通道字符(在 c++ 中)中输入空格(即空格、制表符和换行符)
- QProcess::readAllStandardOutput() 和换行符
- 如果有换行符,clang 格式不会附加大括号
- 提取后返回换行符的C++istream.get()
- 如何在出现换行符之前将多个整数作为输入?
- 正则表达式 获取两个换行符之间的文本
- 包含换行符分隔的单词的文件和C++中这些单词的字符串向量的大小是否相同?
- 在字符串中输入换行符
- 从文本文件中读取数据并删除所有换行符空格,并在 C++ 控制台中显示
- 使用 fgets() 从键盘读取时从以前的输入读取换行符
- C++保留换行符的预处理器字符串化
- Std::cin::以及为什么保留换行符
- 无法在richit中保留换行符