在单字符行上调用时 CRichEditCtrl::GetLine() 添加的虚假 '\r'?
Spurious '\r' added by CRichEditCtrl::GetLine() when called on single-character lines?
我尝试使用 CRichEditCtrl::GetLine()
在 Unicode 模式下使用 VS2015 构建的 MFC 应用程序中检索 rich-edit 控件的给定行的文本,并在 Windows 上使用 运行 10.
我写了这个辅助函数:
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()
returns 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;
}
但是,我不清楚这种特殊情况行为的原因。
P.S:调用的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 for EM_GETLINE
声明 "the return value is the number of TCHAR
s copied"(在我的例子中,wchar_t
)。对于一个字符行,return值是两个,而不是预期的一个。因此,在这种特殊情况下,rich-edit 控件听起来像是 return 后跟一个虚假 \r
的单个字符。
对于包含一个以上字符的行,returned 值是实际的字符数,正如预期的那样(我尝试使用简单的 English/ASCII 字符,以避免 Unicode 代理对和其他东西)。
我通过使用 CRichEditCtrl::GetLine()
的另一个重载使其在没有特殊外壳的情况下工作:
*(int*) buffer = lineLength;
lineLength = richEdit.GetLine(lineNum, buffer);
EM_GETLINE
的参考说你必须将缓冲区的大小写入缓冲区,而这实际上是数量您请求的字符。
发送EM_GETLINE
的宏Edit_GetLine()
的引用是否正确:
cchMax The maximum number of characters to be copied to the buffer.
宏在调用SendMessage()
之前将cchMax
参数写入缓冲区,这与我上面的代码完全相同。
我还认为 CRichEditCtrl::GetLine()
的 3 参数重载中的条件不正确,如果您请求少于 2 个字符,则会导致异常。
如果该行无效,return 值为 零 (0)。
如果该行为空,则缓冲区中的 return 1 和 '\r' 是有意义的。这意味着当行号有效时,'\r' 总是 returned。
函数参考说明缓冲区应至少为 4 个字节长,因为 WORD 在传递给 SendMessage 之前写入缓冲区。
ENSURE 函数中的 sizeof(nMaxLength) 是一个 int 或 WORD 的大小。
CRichEditCtrl::GetLineCount 有一些代码。
我尝试使用 CRichEditCtrl::GetLine()
在 Unicode 模式下使用 VS2015 构建的 MFC 应用程序中检索 rich-edit 控件的给定行的文本,并在 Windows 上使用 运行 10.
我写了这个辅助函数:
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()
returns 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;
}
但是,我不清楚这种特殊情况行为的原因。
P.S:调用的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 for EM_GETLINE
声明 "the return value is the number of TCHAR
s copied"(在我的例子中,wchar_t
)。对于一个字符行,return值是两个,而不是预期的一个。因此,在这种特殊情况下,rich-edit 控件听起来像是 return 后跟一个虚假 \r
的单个字符。
对于包含一个以上字符的行,returned 值是实际的字符数,正如预期的那样(我尝试使用简单的 English/ASCII 字符,以避免 Unicode 代理对和其他东西)。
我通过使用 CRichEditCtrl::GetLine()
的另一个重载使其在没有特殊外壳的情况下工作:
*(int*) buffer = lineLength;
lineLength = richEdit.GetLine(lineNum, buffer);
EM_GETLINE
的参考说你必须将缓冲区的大小写入缓冲区,而这实际上是数量您请求的字符。
发送EM_GETLINE
的宏Edit_GetLine()
的引用是否正确:
cchMax The maximum number of characters to be copied to the buffer.
宏在调用SendMessage()
之前将cchMax
参数写入缓冲区,这与我上面的代码完全相同。
我还认为 CRichEditCtrl::GetLine()
的 3 参数重载中的条件不正确,如果您请求少于 2 个字符,则会导致异常。
如果该行无效,return 值为 零 (0)。
如果该行为空,则缓冲区中的 return 1 和 '\r' 是有意义的。这意味着当行号有效时,'\r' 总是 returned。
函数参考说明缓冲区应至少为 4 个字节长,因为 WORD 在传递给 SendMessage 之前写入缓冲区。
ENSURE 函数中的 sizeof(nMaxLength) 是一个 int 或 WORD 的大小。
CRichEditCtrl::GetLineCount 有一些代码。