我尝试CRichEditCtrl::GetLine()
在使用 VS2015 以 Unicode 模式构建并在 Windows 10 上运行的 MFC 应用程序中检索富编辑控件的给定行的文本。
我写了这个辅助函数:
CString GetLine(CRichEditCtrl& richEdit, const int lineNum)
{
int lineLength = richEdit.LineLength(richEdit.LineIndex(lineNum));
if (lineLength == 0)
{
// Empty line
return CString();
}
const int kMinBufferLength = sizeof(int) / sizeof(wchar_t);
const int bufferLength = max(kMinBufferLength, lineLength);
CString line;
wchar_t* buffer = line.GetBuffer(bufferLength);
lineLength = richEdit.GetLine(lineNum, buffer, bufferLength);
line.ReleaseBuffer(lineLength);
return line;
}
这段代码工作正常,除了只包含一个字符的行。在这种情况下,CRichEditCtrl::GetLine()
返回2(而不是预期的 1),并且输出缓冲区包含正确的字符,后跟一个\r
.
这是为什么?为什么\r
只为单字符行添加而不为包含更多字符的行添加?
我能够解决这个问题,添加一个if
像这样的特殊情况:
// Code inserted after the richEdit.GetLine() call, before the line.ReleaseBuffer() call:
// *** Special Case ***
// It seems that when there's only one character (e.g. 'C') in the line,
// CRichEditCtrl::GetLine() returns 2, and appends a '\r' after
// the read character in the output buffer.
if ((lineLength == 2) && (buffer[1] == L'\r'))
{
// Chop off the spurious '\r'
lineLength = 1;
}
但是,我不清楚这种特殊情况行为的原因。
PS:调用的CRichEditCtrl::GetLine()
MFC代码是:
int CRichEditCtrl::GetLine(_In_ int nIndex, _Out_writes_to_(nMaxLength, return) LPTSTR lpszBuffer, _In_ int nMaxLength) const
{
ASSERT(::IsWindow(m_hWnd));
ENSURE(sizeof(nMaxLength)<=nMaxLength*sizeof(TCHAR)&&nMaxLength>0);
*(LPINT)lpszBuffer = nMaxLength;
return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
}
所以这似乎只是EM_GETLINE
消息的一个小包装。
MSDN doc forEM_GETLINE
声明“返回值是TCHAR
复制的 s 数”(在我的例子中是wchar_t
s)。对于一个字符的行,返回值是二,而不是预期的一。\r
因此,在这种特殊情况下,听起来富编辑控件实际上是在返回单个字符后跟一个虚假字符。
对于包含多个字符的行,返回值是实际的字符数,正如预期的那样(我尝试使用简单的英文/ASCII 字符,以避免 Unicode 代理对和其他东西的复杂性)。