MFC:如何保存并恢复CEditView的滚动位置以正确滚动内容
问题原因
你调用CEditView::SetScrollPos仅会修改滚动条的UI显示位置,不会触发编辑控件内部的内容滚动逻辑,所以内容始终停留在左上角。点击滚动条时系统会自动发送对应的滚动消息通知控件更新内容位置,所以才会跳转正确。
解决方案
在你原有恢复滚动条位置的代码后,给编辑控件发送对应滚动消息,触发内容重绘即可。
修改后的代码
// hack to work around ceditview getting its window contents changed CView* pview=GetView(tabi); if (pview->IsKindOf(RUNTIME_CLASS(CEditView))) { CEditView* peditview=reinterpret_cast<CEditView*>(pview); CEdit& editctrl=peditview->GetEditCtrl(); int startchar, endchar; editctrl.GetSel(startchar, endchar); int nhorzpos=peditview->GetScrollPos(SB_HORZ); int nvertpos=peditview->GetScrollPos(SB_VERT); CString strexistingtext; pview->GetWindowText(strexistingtext); // change label tabctrl.SetTabLabel(tabi, strlabel); // put back text pview->SetWindowText(strexistingtext); // put back where we were peditview->SetScrollPos(SB_VERT, nvertpos); peditview->SetScrollPos(SB_HORZ, nhorzpos); // 新增:发送滚动消息触发编辑控件内容滚动 editctrl.SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, nvertpos), 0); editctrl.SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, nhorzpos), 0); editctrl.SetSel(startchar, endchar, TRUE); } else { // change label tabctrl.SetTabLabel(tabi, strlabel); }
补充说明
- 如果上述方法偶发不生效,可以在发完消息后加一句
editctrl.Invalidate()触发控件重绘即可,不需要调用整个窗口的RedrawWindow。 - 如果你不需要修改编辑内容,仅修改标签,也可以考虑直接挂接标签控件的绘制逻辑,避免重设CEdit内容带来的额外开销。
内容的提问来源于stack exchange,提问作者user3161924
相关产品推荐
相关产品推荐

