简体   繁体   English

如何在 RichEdit 中保存然后恢复垂直滚动 position

[英]How to save and then restore vertical scroll position in RichEdit

I am trying to save and then restore the vertical scroll position in RichEdit.我正在尝试保存然后恢复 RichEdit 中的垂直滚动 position。

A global var to store scroll pos:用于存储滚动位置的全局变量:

SI: TScrollInfo;

This code saves the scroll position:此代码保存滚动 position:

FillChar( SI, SizeOf(SI), #0 );
SI.cbSize := SizeOf(SI);
SI.fMask  := SIF_POS;
GetScrollInfo( RichEdit1.Handle, SB_VERT, SI );

This code tries to restore it:此代码尝试恢复它:

RichEdit1.Perform( WM_VSCROLL, MakeLong(SB_THUMBTRACK, SI.nPos), 0 );

The text in RichEdit restores its older position OK. RichEdit 中的文本恢复其较旧的 position OK。 The problem is the vertical scrollbar won't jump to the older location.问题是垂直滚动条不会跳到旧位置。

My system: Win 7 64, Delphi 2009我的系统:Win 7 64,Delphi 2009

What am I doing wrong?我究竟做错了什么?

Option 1选项1

In many ways, the "cleanest" solution would be to use the EM_GETSCROLLPOS and EM_SETSCROLLPOS messages:在许多方面,“最干净”的解决方案是使用EM_GETSCROLLPOSEM_SETSCROLLPOS消息:

const
  EM_GETSCROLLPOS = $04DD;
  EM_SETSCROLLPOS = $04DE;

var
  P: TPoint;

procedure TForm1.btnSaveClick(Sender: TObject);
begin
  RichEdit1.Perform(EM_GETSCROLLPOS, 0, @P)
end;

procedure TForm1.btnRestoreClick(Sender: TObject);
begin
  RichEdit1.Perform(EM_SETSCROLLPOS, 0, @P)
end;

However , beware of the 16-bit limitation described in the documentation, which limits the vertical range you are able to represent using these messages.但是,请注意文档中描述的 16 位限制,它限制了您可以使用这些消息表示的垂直范围。 If you display large RTF documents, this might be an issue (a showstopper, really).如果您显示大型 RTF 文档,这可能是个问题(确实是个大问题)。

Option 2选项 2

Actually, your initial approach seems (to my surprise) not to suffer from this limitation.实际上,您最初的方法似乎(令我惊讶的是)不受此限制的影响。 You will lose in precision, not range.您将失去精度,而不是范围。 The problem you are observing with the scrollbar can be fixed by using SB_THUMBPOSITION instead of SB_THUMBTRACK .您使用滚动条观察到的问题可以通过使用SB_THUMBPOSITION而不是SB_THUMBTRACK来解决。

Option 3选项 3

var
  Y: Integer;

procedure TForm1.btnSaveClick(Sender: TObject);
begin
  y := RichEdit1.Perform(EM_GETFIRSTVISIBLELINE, 0, 0);
end;

procedure TForm1.btnRestoreClick(Sender: TObject);
var
  NewY: Integer;
begin
  NewY := RichEdit1.Perform(EM_GETFIRSTVISIBLELINE, 0, 0);
  RichEdit1.Perform(EM_LINESCROLL, 0, Y - NewY);
end;

might be a viable option.可能是一个可行的选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM