unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure Memo1KeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
uses Windows, StrUtils;
const TestLines = 70000;
procedure TForm1.FormCreate(Sender: TObject);
var
I: integer;
begin
Memo1.ScrollBars := ssBoth;
Memo1.WordWrap := false;
Memo1.Lines.BeginUpdate;
try
for I := 1 to TestLines do
Memo1.Lines.Add('Line ' + DupeString(' - ' + I.ToString, 30));
finally
Memo1.Lines.EndUpdate;
end;
end;
procedure TForm1.FormShow(Sender: TObject);
begin
Memo1.VertScrollBar.Position := TestLines - 50;
Memo1.SelStart := Length(Memo1.Text) - 50 * Length(Memo1.Lines[Memo1.Lines.Count - 2]);
Memo1.SelStart := Memo1.SelStart + 50;
end;
procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
var
si: TScrollInfo;
ScrollPos: TPoint;
OldSelStart, OldSelLength: Integer;
begin
if Key <> VK_F5 then exit;
Memo1.Lines.BeginUpdate;
try
ScrollPos.X := GetScrollPos(Memo1.Handle, SB_HORZ);
ScrollPos.Y := GetScrollPos(Memo1.Handle, SB_VERT);
OldSelStart := Memo1.SelStart;
OldSelLength := Memo1.SelLength;
Memo1.Text := Memo1.Text + 'hello' + LineEnding; {simulate changed Memo content}
Memo1.SelStart := OldSelStart;
Memo1.SelLength := OldSelLength;
{ OLD METHOD FOR < 65535
SendMessage(Memo1.Handle, WM_VSCROLL, MakeLong(SB_THUMBPOSITION, ScrollPos.Y), 0);
SendMessage(Memo1.Handle, WM_VSCROLL, SB_ENDSCROLL, 0);
SendMessage(Memo1.Handle, WM_HSCROLL, MakeLong(SB_THUMBPOSITION, ScrollPos.X), 0);
SendMessage(Memo1.Handle, WM_HSCROLL, SB_ENDSCROLL, 0);
exit;
}
FillChar(si, SizeOf(si), 0);
si.cbSize := SizeOf(si);
si.fMask := SIF_POS;
Self.Caption := format('Setting x = %d and y = %d', [ScrollPos.X, ScrollPos.Y]);
si.nPos := ScrollPos.Y;
SetScrollInfo(Memo1.Handle, SB_VERT, si, true);
if ScrollPos.Y > 65535 then ScrollPos.Y := 0;
SendMessage(Memo1.Handle, WM_VSCROLL, MakeWParam(SB_THUMBPOSITION, ScrollPos.X), 0);
si.nPos := ScrollPos.X;
SetScrollInfo(Memo1.Handle, SB_HORZ, si, true);
if ScrollPos.X > 65535 then ScrollPos.X := 0; // seems like below 65535 you do need valie for reset
SendMessage(Memo1.Handle, WM_HSCROLL, MakeWParam(SB_THUMBPOSITION, ScrollPos.X), 0);
finally
Memo1.Lines.EndUpdate;
end;
end;
end.