Option 1
In many ways, the "cleanest" solution would be to use the EM_GETSCROLLPOS
and EM_SETSCROLLPOS
messages:
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. If you display large RTF documents, this might be an issue (a showstopper, really).
Option 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
.
Option 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.