Recent

Author Topic: [SOLVED] Set horizontal scroll position in a TMemo does not work (Windows only)  (Read 7582 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 1131
I'm not sure if scrolling is selectable. But for me, when I put the cursor on the second line and scrolled to the right with the cursor, so with keyboard, there comes a point where the complete view scrolls. And for me it scrolled about 10 characters so the 1234qwert was completely out of view. Scrolling back, it came back in view all the way. So the only way I could get 1234 out of view and qwert inside the view was with my mouse.

Could you reproduce this without touching your mouse? If you scroll on the second line, how much does the scrollbar jump in your example you uploaded?
It could be that your own program has different sizes for the component. That will also give different behavior and maybe there you can get it to 1234 out of view and qwert inside, with just the keyboard.
Now I see where we misunderstood. When I scrolled, I always did it via mouse on the horizontal scrollbar itself. Sorry I did not mention this.

When I set the cursor in the 2nd line and move the cursor rightwards via right arrow key, then, when the cursor reaches the right margin of the Memo, which for me is at "x" in "unixutil.LocalToEpoch", then the Memo content "jumps" near to the end of the 2nd line: on the right I see "LocalToEpoch()", but the ": ]" after it I don't see. So the "jump" is about 20 characters. I attached a screenshot directly after the "jump".

rvk

  • Hero Member
  • *****
  • Posts: 6989
Now I see where we misunderstood. When I scrolled, I always did it via mouse on the horizontal scrollbar itself. Sorry I did not mention this.
Ha, Ok. Then we are on the same page (or at least on the same line  ;) :D )

Hartmut

  • Hero Member
  • *****
  • Posts: 1131
Updated version with selected text and vertical scroll (Windows only):

Code: Pascal  [Select][+][-]
  1. uses Windows;
  2.  
  3. procedure TForm1.FormKeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
  4. var
  5.   ScrollPos: TPoint;
  6.   OldSelStart, OldSelLength: Integer;
  7. begin
  8.   if Key <> VK_F5 then exit;
  9.  
  10.   Memo1.Lines.BeginUpdate;
  11.   try
  12.     ScrollPos.Y := GetScrollPos(Memo1.Handle, SB_VERT);
  13.     ScrollPos.X := GetScrollPos(Memo1.Handle, SB_HORZ);
  14.     OldSelStart := Memo1.SelStart;
  15.     OldSelLength := Memo1.SelLength;
  16.     Memo1.Text := Memo1.Text + 'hello' + LineEnding; {simulate changed Memo content}
  17.     Memo1.SelStart := OldSelStart;
  18.     Memo1.SelLength := OldSelLength;
  19.     SendMessage(Memo1.Handle, WM_VSCROLL, MakeLong(SB_THUMBPOSITION, ScrollPos.Y), 0);
  20.     SendMessage(Memo1.Handle, WM_VSCROLL, SB_ENDSCROLL, 0);
  21.     SendMessage(Memo1.Handle, WM_HSCROLL, MakeLong(SB_THUMBPOSITION, ScrollPos.X), 0);
  22.     SendMessage(Memo1.Handle, WM_HSCROLL, SB_ENDSCROLL, 0);
  23.   finally
  24.     Memo1.Lines.EndUpdate;
  25.   end;
  26. end;

Unfortunately I found out, that this solution only works for line numbers <= 32767.
If ScrollPos.Y is > 32767 then I get a Runtime-Error 201 (Range Error) in line
Code: Pascal  [Select][+][-]
  1. SendMessage(Memo1.Handle, WM_VSCROLL, MakeLong(SB_THUMBPOSITION, ScrollPos.Y), 0);

If we look in function MAKELONG in file ...\fpc\3.2.2\source\rtl\win\wininc\base.inc
Code: Pascal  [Select][+][-]
  1.   { was #define dname(params) def_expr }
  2.   { argument types are unknown }
  3.   function MAKELONG(a,b : longint) : LONG;
  4.     begin
  5.        MAKELONG:=LONG((WORD(a)) or ((DWORD(WORD(b))) shl 16));
  6.     end;
  7.  
we see, that from parameter 'b' only WORD(b) is used and this value is shifted left 16 times and must fit into LONG, so 'b' may not be > 32767.

Has someone a solution for bigger line numbers?
I would like to have > 65536 if anyhow possible.

rvk

  • Hero Member
  • *****
  • Posts: 6989
Unfortunately I found out, that this solution only works for line numbers <= 32767.
If ScrollPos.Y is > 32767 then I get a Runtime-Error 201 (Range Error) in line
Code: Pascal  [Select][+][-]
  1. SendMessage(Memo1.Handle, WM_VSCROLL, MakeLong(SB_THUMBPOSITION, ScrollPos.Y), 0);
Mmm, I can't reproduce this.

32767 shl 16 is 2.147.418.112. So this shouldn't be a problem for a LONG (longint).

It's just that above 32767 the value swaps to negative.
But LParam for SendMessage is a Int64 (at least on Windows) so it should work.

Just tried with small empty project with just a TMemo on the form...
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. var
  3.   ScrollPos: TPoint;
  4.   MyLONG: LONG;
  5.   a, b: longint;
  6. begin
  7.   ScrollPos.Y := 32767;
  8.   a := SB_THUMBPOSITION;
  9.   a := 0; // to test the swap
  10.   b := ScrollPos.Y;
  11.  
  12.   MyLONG := MAKELONG(a, b);
  13.   SendMessage(Memo1.Handle, WM_VSCROLL, MyLONG, 0);
  14.  
  15.   MyLONG := LONG((word(a)) or ((DWORD(word(b))) shl 16));
  16.   SendMessage(Memo1.Handle, WM_VSCROLL, MyLONG, 0);
  17.  
  18. end;

I enabled debugging (Range check, I/O error etc) but didn't get an error.

rvk

  • Hero Member
  • *****
  • Posts: 6989
Has someone a solution for bigger line numbers?
I would like to have > 65536 if anyhow possible.
BTW. Although Sendmessage will work for values up to 65536... it you have a use-case where you need even bigger numbers, then you need to switch back to SetScrollInfo.

A LParam is 32 bits wide but the Windows api uses 16 bits for SB_THUMBPOSITION and the other 16 bits for the value, limiting it to 65536.

You can set the position with higher values with SetScrollInfo, and then sending a WM_VSCROLL with SB_THUMBPOSITION and value 0 to force the component to read the set value with SetScrollInfo.

Hartmut

  • Hero Member
  • *****
  • Posts: 1131
Thanks a lot rvk for your help.

Meanwhile I found out a very strange thing. If I call
Code: Pascal  [Select][+][-]
  1. writeln(MakeLong(SB_THUMBPOSITION,32768));
then I get a positive value of 4294967295 and if I pass this value to SendMessage() then I get this Range Check Error, which is no surprise.

But if I make an exact copy of MakeLong():
Code: Pascal  [Select][+][-]
  1. function myMAKELONG(a,b : longint) : LONG;
  2.   begin
  3.      myMAKELONG:=LONG((WORD(a)) or ((DWORD(WORD(b))) shl 16));
  4.   end;
and call
Code: Pascal  [Select][+][-]
  1. writeln(myMakeLong(SB_THUMBPOSITION,32768));
then I get a negative value of -2147483648 (as it should be) and if I pass this value to SendMessage() then I get no Range Check Error and SendMessage() works. Have no idea why... I'm on Win7 32-bit with Lazarus 3.6.0 and FPC 3.2.2.

But when I call
Code: Pascal  [Select][+][-]
  1. writeln(MakeLong(SB_THUMBPOSITION,32768));
from within another unit, then I get a negative value of -2147483648 (as it should be).
Maybe an issue with Unit ordering... (had no time to check this already).

But meanwhile a faced a 2nd issue with
Code: Pascal  [Select][+][-]
  1. SendMessage(Memo1.Handle, WM_VSCROLL, MakeLong(SB_THUMBPOSITION, ScrollPos.Y), 0);
If the Momo has >= 65534 lines, then SendMessage() fails (does nothing and no error), even if ScrollPos.Y has very small values like 50!

So I want to try your suggestion with SetScrollInfo(), but I found it twice:
Code: Pascal  [Select][+][-]
  1. // ...\lcl\include\winapih.inc has:
  2. function SetScrollInfo(Handle: HWND; SBStyle: Integer; ScrollInfo: TScrollInfo; Redraw : Boolean): Integer; {$IFDEF IF_BASE_MEMBER}virtual;{$ENDIF}
  3. // ...\fpc\3.2.2\source\rtl\win\wininc\redef.inc has:
  4. function SetScrollInfo(hWnd: HWND; BarFlag: Integer; const ScrollInfo: TScrollInfo; Redraw: BOOL): Integer; external 'user32' name 'SetScrollInfo';

Which of them should I use?
And did I understand you correctly: I should
 - always 1st call SetScrollInfo(...);
 - and always after call SendMessage(Memo1.Handle, WM_VSCROLL, MakeLong(SB_THUMBPOSITION,0), 0);
Correct?

rvk

  • Hero Member
  • *****
  • Posts: 6989
Meanwhile I found out a very strange thing. If I call
Code: Pascal  [Select][+][-]
  1. writeln(MakeLong(SB_THUMBPOSITION,32768));
then I get a positive value of 4294967295 and if I pass this value to SendMessage() then I get this Range Check Error, which is no surprise.
That's wierd. When I do this in a LCL form with Showmessage(MakeLong(SB_THUMBPOSITION,32768).ToString);
I get -2147483644

But if I make an exact copy of MakeLong():
Code: Pascal  [Select][+][-]
  1. writeln(myMakeLong(SB_THUMBPOSITION,32768));
then I get a negative value of -2147483648 (as it should be) and if I pass this value to SendMessage() then I get no Range Check Error and SendMessage() works. Have no idea why... I'm on Win7 32-bit with Lazarus 3.6.0 and FPC 3.2.2.
Yeah, that's how it supposed to work.
Can you see which MakeLong is called in your first example?

Even with a console program I get -2147483644.
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$mode objfpc}{$H+}
  3. uses Windows, Classes;
  4. begin
  5.   writeln(MakeLong(SB_THUMBPOSITION,32768));
  6.   readln;
  7. end.

But when I call
Code: Pascal  [Select][+][-]
  1. writeln(MakeLong(SB_THUMBPOSITION,32768));
from within another unit, then I get a negative value of -2147483648 (as it should be).
Maybe an issue with Unit ordering... (had no time to check this already).
From another unit? Yes, then you need to look at your complete source to see which MakeLong is actually used.

O, WAIT. There is one in winapi.inc and one in base.inc. Both different (one with DWORD as result, the other with LONG).
winapih.inc = LONG is longint, base.inc = DWORD is LongWord.    LongWord can't hold negative value.

But meanwhile a faced a 2nd issue with
[...]
So I want to try your suggestion with SetScrollInfo(), but I found it twice:
Code: Pascal  [Select][+][-]
  1. // ...\lcl\include\winapih.inc has:
  2. function SetScrollInfo(Handle: HWND; SBStyle: Integer; ScrollInfo: TScrollInfo; Redraw : Boolean): Integer; {$IFDEF IF_BASE_MEMBER}virtual;{$ENDIF}
  3. // ...\fpc\3.2.2\source\rtl\win\wininc\redef.inc has:
  4. function SetScrollInfo(hWnd: HWND; BarFlag: Integer; const ScrollInfo: TScrollInfo; Redraw: BOOL): Integer; external 'user32' name 'SetScrollInfo';
Which of them should I use?
Shouldn't matter which.
The first is through LCL (winapi.inc is included in uses lclintf).
The second is a direct call through the windows unit.
Both call the same SetScrollInfo from user32 eventually. (The LCL is there for cross-platform use)

And did I understand you correctly: I should
 - always 1st call SetScrollInfo(...);
 - and always after call SendMessage(Memo1.Handle, WM_VSCROLL, MakeLong(SB_THUMBPOSITION,0), 0);
Correct?
Yes, that's how I understand it from the documentation (i.e. Google AI and corroborated by the Microsoft Docs itself ;) ).

Quote
Note that the WM_VSCROLL message carries only 16 bits of scroll box position data. Thus, applications that rely solely on WM_VSCROLL (and WM_HSCROLL) for scroll position data have a practical maximum position value of 65,535.

However, because the SetScrollInfo, SetScrollPos, SetScrollRange, GetScrollInfo, GetScrollPos, and GetScrollRange functions support 32-bit scroll bar position data, there is a way to circumvent the 16-bit barrier of the WM_HSCROLL and WM_VSCROLL messages. See GetScrollInfo for a description of the technique.

The final SendMessage was a suggestion from Google AI so I'm not certain if it's actually needed. But if it doesn't work without, you know what to try  ;)

Hartmut

  • Hero Member
  • *****
  • Posts: 1131
Can you see which MakeLong is called in your first example?
...
From another unit? Yes, then you need to look at your complete source to see which MakeLong is actually used.

O, WAIT. There is one in winapi.inc and one in base.inc. Both different (one with DWORD as result, the other with LONG).
winapih.inc = LONG is longint, base.inc = DWORD is LongWord.    LongWord can't hold negative value.

In both cases (from where I get a positive and from where I get a negative result) if I click with CRTR-LeftMouse on function MAKELONG file \fpc\3.2.2\source\rtl\win\wininc\base.inc is opened:
Code: Pascal  [Select][+][-]
  1. function MAKELONG(a,b : longint) : LONG;
  2.    begin
  3.    MAKELONG:=LONG((WORD(a)) or ((DWORD(WORD(b))) shl 16));
  4.    end;
DWORD() should return a positive value, but I would assume, that because the function result is 'LONG', that it would be interpreted from any caller as longint and so always be negative...

The documentation https://lazarus-ccr.sourceforge.io/docs/lcl/lclintf/setscrollinfo.html I found is as often too short for me. Do you know, which values for SBStyle and ScrollInfo I need in my case?
If yes, you could save me a lot of time (and probably a couple of try-and-errors).
If no, you should not investigate for it, in that case this would be my job.

rvk

  • Hero Member
  • *****
  • Posts: 6989
The documentation https://lazarus-ccr.sourceforge.io/docs/lcl/lclintf/setscrollinfo.html I found is as often too short for me. Do you know, which values for SBStyle and ScrollInfo I need in my case?
If yes, you could save me a lot of time (and probably a couple of try-and-errors).
If no, you should not investigate for it, in that case this would be my job.
I made a little example from the use-case from page 1.

I found a few quirks in the Windows Api... (which is always the case when dealing with Windows Api  :D )

Create a clean project with a TMemo on screen.
Double click for FormCreate and create FormShow and TMemo OnKeyDown.
Paste code below over the complete unit (or recreate your own from this code).

It seems GetScrollPos does support 32 bit values. Maybe SetScrollPos too but I didn't test that.
When setting the vertical scroll you need to do an extra SB_THUMBPOSITION with value 0.
I thought that that should also be used for vertical but that didn't work.
Seems that you only need to use 0 when using values above 65535.

(This code kinda worked for me, except on start I need to press a key to let the cursor in view but pressing F5 kept the cursor in position)

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Memo1: TMemo;
  16.     procedure FormCreate(Sender: TObject);
  17.     procedure FormShow(Sender: TObject);
  18.     procedure Memo1KeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
  19.   private
  20.  
  21.   public
  22.  
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33. uses Windows, StrUtils;
  34.  
  35. const TestLines = 70000;
  36.  
  37. procedure TForm1.FormCreate(Sender: TObject);
  38. var
  39.   I: integer;
  40. begin
  41.   Memo1.ScrollBars := ssBoth;
  42.   Memo1.WordWrap := false;
  43.   Memo1.Lines.BeginUpdate;
  44.   try
  45.     for I := 1 to TestLines do
  46.       Memo1.Lines.Add('Line ' + DupeString(' - ' + I.ToString, 30));
  47.   finally
  48.     Memo1.Lines.EndUpdate;
  49.   end;
  50. end;
  51.  
  52. procedure TForm1.FormShow(Sender: TObject);
  53. begin
  54.   Memo1.VertScrollBar.Position := TestLines - 50;
  55.   Memo1.SelStart := Length(Memo1.Text) - 50 * Length(Memo1.Lines[Memo1.Lines.Count - 2]);
  56.   Memo1.SelStart := Memo1.SelStart + 50;
  57. end;
  58.  
  59. procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
  60. var
  61.   si: TScrollInfo;
  62.   ScrollPos: TPoint;
  63.   OldSelStart, OldSelLength: Integer;
  64. begin
  65.   if Key <> VK_F5 then exit;
  66.  
  67.   Memo1.Lines.BeginUpdate;
  68.   try
  69.  
  70.     ScrollPos.X := GetScrollPos(Memo1.Handle, SB_HORZ);
  71.     ScrollPos.Y := GetScrollPos(Memo1.Handle, SB_VERT);
  72.  
  73.     OldSelStart := Memo1.SelStart;
  74.     OldSelLength := Memo1.SelLength;
  75.     Memo1.Text := Memo1.Text + 'hello' + LineEnding; {simulate changed Memo content}
  76.     Memo1.SelStart := OldSelStart;
  77.     Memo1.SelLength := OldSelLength;
  78.  
  79.     { OLD METHOD FOR < 65535
  80.     SendMessage(Memo1.Handle, WM_VSCROLL, MakeLong(SB_THUMBPOSITION, ScrollPos.Y), 0);
  81.     SendMessage(Memo1.Handle, WM_VSCROLL, SB_ENDSCROLL, 0);
  82.     SendMessage(Memo1.Handle, WM_HSCROLL, MakeLong(SB_THUMBPOSITION, ScrollPos.X), 0);
  83.     SendMessage(Memo1.Handle, WM_HSCROLL, SB_ENDSCROLL, 0);
  84.     exit;
  85.     }
  86.  
  87.     FillChar(si, SizeOf(si), 0);
  88.     si.cbSize := SizeOf(si);
  89.     si.fMask := SIF_POS;
  90.  
  91.     Self.Caption := format('Setting x = %d and y = %d', [ScrollPos.X, ScrollPos.Y]);
  92.  
  93.     si.nPos := ScrollPos.Y;
  94.     SetScrollInfo(Memo1.Handle, SB_VERT, si, true);
  95.     if ScrollPos.Y > 65535 then ScrollPos.Y := 0;
  96.     SendMessage(Memo1.Handle, WM_VSCROLL, MakeWParam(SB_THUMBPOSITION, ScrollPos.X), 0);
  97.  
  98.     si.nPos := ScrollPos.X;
  99.     SetScrollInfo(Memo1.Handle, SB_HORZ, si, true);
  100.     if ScrollPos.X > 65535 then ScrollPos.X := 0; // seems like below 65535 you do need valie for reset
  101.     SendMessage(Memo1.Handle, WM_HSCROLL, MakeWParam(SB_THUMBPOSITION, ScrollPos.X), 0);
  102.  
  103.   finally
  104.     Memo1.Lines.EndUpdate;
  105.   end;
  106. end;
  107.  
  108. end.

BTW. If you want more information about using certain Windows Api calls it's always best to (also) look at the Microsoft docs:
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setscrollinfo
« Last Edit: April 01, 2026, 04:39:40 pm by rvk »

Hartmut

  • Hero Member
  • *****
  • Posts: 1131
Hello rvk, there is a small typo in line 96:
Code: Pascal  [Select][+][-]
  1. SendMessage(Memo1.Handle, WM_VSCROLL, MakeWParam(SB_THUMBPOSITION, ScrollPos.X), 0);
which I fixed (should be 'ScrollPos.Y').

I have a good news and a bad news: the good one is, that vertical scroll now seems to work perfectly, even if the text has > 100000 lines. The bad news is: horizontal scroll does not work, if the text has >= 65534 lines (with <= 65533 lines it works). Assure your lines are long enough, that horizontal scroll is possible.

In this case, horizontal scroll position is set to wrong values, even if ScrollPos.X and ScrollPos.Y both are < 300. The very strange thing is: in this case horizontal scroll position is set to the value of ScrollPos.Y (instead of ScrollPos.X). Of course I assumed a typo, but I checked "100" times that there is no and I printed all used values and checked that they are correct. And: with exactly the same *.exe file the issue occurs only, if the text (which I read from a textfile) has >= 65534 lines (with <= 65533 lines it works). So it can't be a typo. Temporarily I added line
Code: Pascal  [Select][+][-]
  1. SendMessage(Memo1.Handle, WM_HSCROLL, SB_ENDSCROLL, 0);
from your reply #10, which is not included in reply #23, but this made no difference.

I tested on Win7 32-bit with Lazarus/FPC 3.6.0/3.2.2 and 2.0.10/3.2.0 and on Win10 64-bit with the same 32-bit *.exe file of 3.6.0/3.2.2 and got always the same results.

Can you reproduce this?

Hartmut

  • Hero Member
  • *****
  • Posts: 1131
Yesterday I tested your suggestion in my real program, where horizontal scroll position failed, as described. Today I tested your demo from reply #23 and there horizontal scroll position works perfectly with > 65534 lines!
Will investigate why it fails in my real program.
Please stop any further effort... sorry for confusion.

Thanks for Microsoft docs link. I had checked it and several associated links.

rvk

  • Hero Member
  • *****
  • Posts: 6989
Yesterday I tested your suggestion in my real program, where horizontal scroll position failed, as described. Today I tested your demo from reply #23 and there horizontal scroll position works perfectly with > 65534 lines!
Will investigate why it fails in my real program.
Please stop any further effort... sorry for confusion.
My efforts are no problem  :)

After some further investigation I found out why it might fail.
We are trying to set the X position of the scrollbar back to a certain setting.
But... the X position might not set correctly if nMin and nMax for the scrollbar are different from the previous state.
And here is the kicker... if the first line (where the memo resets to) has a different line length, all things fall apart.

Let me explain...
When you save the X on line 50000, this might have a value, because the line length of line 50000 is 900 for example.
When the memo resets to line 1, that might have length 20.
The Horizontal and Vertical scrollbars get their nMin/nMax values set.

Then we do a force to position Y again (line 50000) BUT.... the nMin/nMax for the VERTICAL bar are not reset to the needed values.
If we then set the X for the invalid vertical bar, the result is unpredictable (i.e. you might set the X value outside the mMin/mMax range from line 1).

So... we need to UPDATE the VERTICAL bar values after we set the horizontal position but before we set the vertical position.
(I hope that makes sense)

Attached I have a small example where I added UpdateWindow, to update after horizontal and before vertical positions.
It's note quite completely correct, I still get a wrong scrollbar position sometimes, but it only happened one.

O... I also found out that SetScrollInfo only works correctly if nMax > 65535. Below it just always resets to 0 and you need WM_VSCROLL with value.
(you see I coded that in the example)

Hartmut

  • Hero Member
  • *****
  • Posts: 1131
Thank you very much rvk for your continuous help.

Meanwhile I did a lot of changes to my real program to make it similar to your demo from reply #23 (including copying your procedure TForm1.Memo1KeyDown() into my real program and using it) but the horizontal scroll position issue still occurs.

And I did a lot of changes to your demo from reply #23 to make it similar to my real program (including copying and calling 2 procedures from there which read and restore the cursor and scroll positions), but the horizontal scroll issue does not occur there. Even not with exactly the same textfile, which I read and exactly the same Memo size (width and height).

Because of the last 2 points (same textfile and same Memo size) I doubt, whether your new suspicion will be the reason. But I will try and report the result (might be tomorrow).

rvk

  • Hero Member
  • *****
  • Posts: 6989
Because of the last 2 points (same textfile and same Memo size) I doubt, whether your new suspicion will be the reason. But I will try and report the result (might be tomorrow).
You can easily test this... try your program with a file with ALL lines of the same length.
In that case, the horizontal scrollbar should be the same on ALL lines and the code should work.

If it does work, try the same with the first 100 lines very short (like 20 characters) from line 100 onwards larger lines.
Then... everything you try, should result in a maximum X bar position of below 20.

Hartmut

  • Hero Member
  • *****
  • Posts: 1131
Because of the last 2 points (same textfile and same Memo size) I doubt, whether your new suspicion will be the reason. But I will try and report the result (might be tomorrow).
You can easily test this... try your program with a file with ALL lines of the same length.
In that case, the horizontal scrollbar should be the same on ALL lines and the code should work.

Just a short intermediate info: I tested a file with ALL lines of the same length (80 characters, 65550 lines) and in my real program the horizontal scroll issue occurs the same as always :-((
Will try further...

 

TinyPortal © 2005-2018