CEditEx调用SetWindowText后无法触发撤销(CTRL+Z)问题咨询
问题描述
我在派生的CEditEx类中使用:
SetWindowText(strText);
这段代码能正常更新控件内容,但无法支持撤销操作(CTRL + Z)。手动输入修改时撤销功能正常,请问有没有办法让这类代码修改也被纳入撤销追踪?
示例函数:
void CEditEx::Encode(const CString strTagOpen, const CString strTagClose) { int iStartIndex{}; int iEndIndex{}; GetSel(iStartIndex, iEndIndex); if (iEndIndex > iStartIndex) { CString strText; GetWindowText(strText); strText.Insert(iStartIndex, strTagOpen); strText.Insert(iEndIndex + strTagOpen.GetLength(), strTagClose); SetWindowText(strText); SetSel(iStartIndex, iEndIndex + strTagOpen.GetLength() + strTagClose.GetLength()); } }
解决方案
要让代码修改支持撤销,核心是不要用SetWindowText直接替换全部内容,而是用控件认可的编辑操作接口,让它自动记录撤销步骤。
推荐方法:用ReplaceSel替代SetWindowText
ReplaceSel内部调用EM_REPLACESEL消息,这个操作会被编辑控件视为用户手动编辑,自动纳入撤销追踪。调整你的示例函数如下:
void CEditEx::Encode(const CString strTagOpen, const CString strTagClose) { int iStartIndex{}; int iEndIndex{}; GetSel(iStartIndex, iEndIndex); if (iEndIndex > iStartIndex) { CString strSelected; GetSelText(strSelected); // 构造要替换的内容:标签+选中文本+标签 CString strReplacement = strTagOpen + strSelected + strTagClose; // 替换选中内容,此操作会被记录到撤销栈 ReplaceSel(strReplacement); // 调整选中范围,保持选中原来的文本部分 int newStart = iStartIndex + strTagOpen.GetLength(); int newEnd = newStart + strSelected.GetLength(); SetSel(newStart, newEnd); } }
原理说明
SetWindowText是直接覆盖控件的全部内容,属于“批量替换”,不会触发编辑控件的撤销追踪逻辑;而EM_REPLACESEL是模拟用户的选中替换操作,控件会自动把这个操作记录到撤销栈,所以CTRL+Z就能撤销。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

