MFC中使用EN_REQUESTRESIZE调整RichEdit高度时文本被截断?
问题描述
设置ENM_REQUESTRESIZE后,本应触发EN_REQUESTRESIZE仅修改RichEdit控件的高度(而非宽度),但实际调用时宽高均被修改。保留控件原有宽度后,调整后的高度仍不足,导致文本被截断。
实现代码
void CDialogX::OnEnRequestResize( NMHDR* pNMHDR, LRESULT* pResult ) { _ASSERT( pNMHDR->code == EN_REQUESTRESIZE ); CRect rect; m_ctlRichEdit.GetWindowRect(rect); ScreenToClient(rect); CDebugPrint::DebugPrint(_T("existing size %i %i %i %i\n"), rect.left, rect.top, rect.right, rect.bottom); REQRESIZE* prr = (REQRESIZE*)pNMHDR; m_ctlRichEdit.SetWindowPos(NULL, 0, 0, rect.Width(), prr->rc.bottom - prr->rc.top, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE); CDebugPrint::DebugPrint(_T("requested size %i %i %i %i\n"), prr->rc.left, prr->rc.top, prr->rc.right, prr->rc.bottom); // get new size m_ctlRichEdit.GetWindowRect(rect); ScreenToClient(rect); CDebugPrint::DebugPrint(_T("new size %i %i %i %i\n"), rect.left, rect.top, rect.right, rect.bottom); // ... *pResult=0; }
调试输出
existing size 60 57 329 58 requested size 60 57 241 70 new size 60 57 329 70
补充细节
- 多行文本时最后一行会被截断
- 通过
GetWindowRect与GetClientRect计算边框为0 - 通过
GetRect(EM_GETRECT)与GetClientRect计算内部边框为1
解决方案
问题核心是未考虑RichEdit内部的文本区域边距,且误用了REQRESIZE结构体的尺寸含义。
错误点分析
REQRESIZE中的rc是控件需要的内部文本显示区域尺寸,不是整个窗口的尺寸。你直接用这个高度设置窗口高度,会导致实际文本显示区域因内部边距被压缩,空间不足。- 即便窗口边框为0,
EM_GETRECT得到的内部文本区域和客户区仍有1像素边距,这部分差值被你忽略,导致最终文本显示高度不够。
修正步骤
- 先计算控件内部的垂直边距总和:
CRect clientRect; m_ctlRichEdit.GetClientRect(clientRect); CRect textRect; m_ctlRichEdit.SendMessage(EM_GETRECT, 0, (LPARAM)&textRect); int verticalMargin = clientRect.Height() - textRect.Height(); - 将
REQRESIZE请求的文本区域高度,加上垂直边距,作为窗口的目标高度,同时保留原有宽度:int targetHeight = (prr->rc.bottom - prr->rc.top) + verticalMargin; m_ctlRichEdit.SetWindowPos(NULL, 0, 0, rect.Width(), targetHeight, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE); - 额外检查:确保RichEdit控件禁用
ES_AUTOHSCROLL样式,这样控件才会自动换行,仅触发高度调整的请求,避免宽度被修改。
修正后的示例代码
void CDialogX::OnEnRequestResize( NMHDR* pNMHDR, LRESULT* pResult ) { _ASSERT( pNMHDR->code == EN_REQUESTRESIZE ); CRect rect; m_ctlRichEdit.GetWindowRect(rect); ScreenToClient(rect); CDebugPrint::DebugPrint(_T("existing size %i %i %i %i\n"), rect.left, rect.top, rect.right, rect.bottom); REQRESIZE* prr = (REQRESIZE*)pNMHDR; CDebugPrint::DebugPrint(_T("requested text area size %i %i %i %i\n"), prr->rc.left, prr->rc.top, prr->rc.right, prr->rc.bottom); // 计算内部垂直边距 CRect clientRect; m_ctlRichEdit.GetClientRect(clientRect); CRect textRect; m_ctlRichEdit.SendMessage(EM_GETRECT, 0, (LPARAM)&textRect); int verticalMargin = clientRect.Height() - textRect.Height(); // 目标高度 = 请求的文本区域高度 + 垂直边距 int targetHeight = (prr->rc.bottom - prr->rc.top) + verticalMargin; m_ctlRichEdit.SetWindowPos(NULL, 0, 0, rect.Width(), targetHeight, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE); // 获取新尺寸 m_ctlRichEdit.GetWindowRect(rect); ScreenToClient(rect); CDebugPrint::DebugPrint(_T("new size %i %i %i %i\n"), rect.left, rect.top, rect.right, rect.bottom); *pResult=0; }
内容的提问来源于stack exchange,提问作者user3161924
相关产品推荐
相关产品推荐

