Recent

Author Topic: Scrollbar not disabling.  (Read 2171 times)

Birger52

  • Full Member
  • ***
  • Posts: 126
Scrollbar not disabling.
« on: October 03, 2018, 04:38:46 pm »
I have this procedure that sets values for a scrollbar.

Code: Pascal  [Select]
  1. procedure TTableContainer.SetScrollValues;
  2. var
  3.   dataant, curpos : integer;
  4. begin
  5.   if FItems <> nil then dataant := FItems.Count
  6.   else dataant := 0;
  7.   curpos := FScroller.Position;
  8.   with FScroller do begin
  9.      Min := 0;
  10.      if dataant > FRowCount then Max := dataant - FRowCount
  11.      else Max := 0;
  12.      SmallChange := 1;
  13.      if dataant > 2 * FRowCount then LargeChange := FRowCount-1
  14.      else LargeChange := 1;
  15.      Position := curpos;
  16.      Enabled := Max > Min;
  17.   end;
  18. end;
  19.  

The line
     Enabled := Max > Min;
is supposed to disable the scrollbar, if scrolling isn't an option.
And it does. Sometimes. Sometimes it doesn't.

A littel cryptic perhaps, but it seems, that scrolling is actually disabled - but the scrollbar is not always drawn greyed out, and can still be "operated".
But OnScroll is not called, and slider just jumps back to the top, if its position is changed.


Anybody can offer an explanation or a workaround?

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: Scrollbar not disabling.
« Reply #1 on: October 03, 2018, 05:29:33 pm »
What is FScroller? It is TScrollBar instance anchored to TTableContainer?
If TTableContainer is derived from TCustomControl, it's better to use built-in scrolling features as it is usually done (in TStringGrid etc.).
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Birger52

  • Full Member
  • ***
  • Posts: 126
Re: Scrollbar not disabling.
« Reply #2 on: October 03, 2018, 06:57:19 pm »
Yes. ;)
TTableContainer is derived from CustomControl and FScroller  is a TScrollBar with Kind := TScrollBarKind.sbVertical; created programmatically when container is created.
And the scrollbar is used to control a number of other TCustomControl derived Components.
Actually, it doesn't do anything but redraw children when changed - and position determins how the children are redrawn.

Can you explain why you think using the build in functionality is "better" - and how I could implement it?


Snd I would still appreciate, if somebody can explain why the scrollbar is only sometimes drawn greyed out, when it is disabled.


Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: Scrollbar not disabling.
« Reply #3 on: October 03, 2018, 07:15:51 pm »
Well, if one scrollbar controls more components then it makes sense.

The easiest way to solve it is to look what happens:
Code: Pascal  [Select]
  1.      ...
  2.      writeln('Max, Min: ', Max, ', ', Min);
  3.      Enabled := Max > Min;
  4.    end;
  5.  
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

BrunoK

  • Full Member
  • ***
  • Posts: 191
  • Retired programmer
Re: Scrollbar not disabling.
« Reply #4 on: October 03, 2018, 09:23:38 pm »
Lazarus trunk r. 62137/27.10.2019 (+/- patches regarding TScrollBar, IntitalSetupDialog, Options.Environment options, SearchResults).  Lazarus 3.0.6 raw from svn.
FPC 3.0.4 32 bits. (+heaptrc with leaked ClassName+Revisited TList) , Windows 10 Pro x64 (v. 1903 / 18362.418)

Birger52

  • Full Member
  • ***
  • Posts: 126
Re: Scrollbar not disabling.
« Reply #5 on: October 04, 2018, 11:55:15 am »
Blaazen
Quote
Well, if one scrollbar controls more components then it makes sense.
How's that?
Redrawing children does not change Max or Min of the scrollbar...
It is alway disabled (enabled = false).
But it is not always drawn greyed out.
It actually functions as it should - it is "just" drawn wrong...

Birger52

  • Full Member
  • ***
  • Posts: 126
Re: Scrollbar not disabling.
« Reply #6 on: October 04, 2018, 03:53:32 pm »
Read the "issue" - bug report? - from @BrunoK ; what I could understand of it anyway.
(Do not agree, that it is "a minor problem" and that "no action required" is an acceptable solution, tho ;) )

Noticed the behavior in my own app - the first time, the ScrollBar is disabled (Enabled := false) when it was enabled (Enable = true), it is also drawn grayed out - but every time it is already disabled (Enabled = false) when enabled is set to false (Enabled := false), the scrollbar will be drawn not greyed out (as if it was enabled).

So I changed my code to check that changes are actually needed, before passing them to the scrollbar - which actually make the scrolbar visually appear as it (imho) should.

Code: Pascal  [Select]
  1. procedure TTableContainer.SetScrollValues;
  2. var
  3.   dataant, curpos : integer;
  4.   tMax : integer;
  5. begin
  6.   if FItems <> nil then dataant := FItems.Count
  7.   else dataant := 0;
  8.   with FScroller do begin
  9.     if dataant > FRowCount then tMax := dataant - FRowCount
  10.     else tMax := 0;
  11.     if tMax <> Max then Max := tMax;
  12.     SmallChange := 1;
  13.     if dataant > 2 * FRowCount then LargeChange := FRowCount-1
  14.     else LargeChange := 1;
  15.     Enabled := (Max > Min);
  16.   end;
  17. end;
  18.  

I experimented a little - ao. by simply testing Enabled before setting it:
Code: Pascal  [Select]
  1. if (Max > Min) and Enabled then Enabled := false;
But the problem still "shows".
So the only way to avoid it, is to not set Max, Min and Position, if they already have the correct values.

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: Scrollbar not disabling.
« Reply #7 on: October 04, 2018, 04:18:30 pm »
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

jamie

  • Hero Member
  • *****
  • Posts: 2174
Re: Scrollbar not disabling.
« Reply #8 on: October 05, 2018, 12:50:38 am »
try doing a "Invalidate"  on the parent control after things have changed..
Number 1 at blue screen app creations!

BrunoK

  • Full Member
  • ***
  • Posts: 191
  • Retired programmer
Re: Scrollbar not disabling.
« Reply #9 on: October 05, 2018, 11:35:21 am »
I you use windows LCL or QT5 (I didn't test any other widgetset), you can try to patch yourself $(LazarusDir)\lcl\StdCtrls and $(LazarusDir)\lcl\include\scrollbar.inc following these instructions; AFTER A BACKUP of course.

StdCtrls, TCustomScrollBar : after line 89 (procedure WMEraseBkgnd), add a new message procedure :
Code: Pascal  [Select]
  1.     procedure CMEnabledChanged(var Message: TLMessage); message CM_ENABLEDCHANGED; // ~bk

then in scrollbar.inc completely replace procedure ~line 93
Code: Pascal  [Select]
  1. procedure TCustomScrollBar.SetParams(APosition, AMin, AMax, APageSize: Integer);
with
Code: Pascal  [Select]
  1. procedure TCustomScrollBar.SetParams(APosition, AMin, AMax, APageSize: Integer);
  2. var
  3.   ScrollInfo: TScrollInfo;
  4.   lEnabled : boolean;
  5.   lfMask : UINT = 0;
  6. begin
  7.   if AMax < AMin then
  8.     raise EInvalidOperation.Create(rsScrollBarOutOfRange);
  9.  
  10.   { Test if SetParams was called thru a .SetPosition, before eventual adjustment }
  11.   if (FPosition <> APosition) then
  12.     lfMask := lfMask or SIF_POS;
  13.  
  14.   { Check position within range }
  15.   if APosition < AMin then APosition := AMin;
  16.   if APosition > AMax then APosition := AMax;
  17.  
  18.   if APageSize < 0 then APageSize := 0;
  19.  
  20.   { Test values that changed }
  21.   if (FMin <> AMin) then begin
  22.     FMin := AMin;
  23.     lfMask := lfMask or SIF_Range;
  24.   end;
  25.   if (FMax <> AMax) then begin
  26.     FMax := AMax;
  27.     lfMask := lfMask or SIF_Range;
  28.   end;
  29.   if (lfMask and SIF_POS)<>0 then begin // Only if position change requested
  30.     if not NotRightToLeft then          // Review this code for correctness
  31.       APosition := FMax - APosition;
  32.     FPosition := APosition;
  33.   end;
  34.   if (FPageSize <> APageSize) then begin // ? problem if APageSize > (max-min) ?
  35.     lfMask := lfMask or SIF_Range;
  36.     FPageSize := APageSize;
  37.   end;
  38.   if HandleAllocated then begin
  39.     lEnabled := IsWindowEnabled(Handle); // Dont use IsEnabled, because Form could
  40.                                          // be disabled due to form Disabled.
  41.     if ((lfMask and (SIF_PAGE or SIF_Range or SIF_POS))<>0) then begin
  42.       ScrollInfo.fMask := lfMask;
  43.       ScrollInfo.nMin := AMin;
  44.       ScrollInfo.nMax := AMax;
  45.       ScrollInfo.nPos := APosition;
  46.       ScrollInfo.nPage := APageSize;
  47.       APosition := SetScrollInfo(Handle, SB_CTL, ScrollInfo, lEnabled);
  48.       { Was position changed as a consequence of SetScrollInfo }
  49.       if (APosition<>FPosition) then begin
  50.         if ((lfMask and SIF_POS) = 0) then // SIF_POS not requested, Ping-Pong
  51.           Position := APosition  // actualisation of Position to force .Change
  52.         else begin               // Ajust FPosition to new position
  53.           if not NotRightToLeft then       // Review this code for correctness
  54.             APosition := FMax - APosition;
  55.           FPosition := APosition;
  56.         end;
  57.       end;
  58.     end;
  59.   end;
  60.  
  61. {~bk not needed in windows, qt5}
  62. {$IF not defined(LCLWin32) and not defined(LCLQT)}
  63.   if (FPosition <> APosition) then begin
  64.     if HandleAllocated then begin
  65.       ScrollInfo.fMask := SIF_POS;
  66.       if NotRightToLeft then
  67.         ScrollInfo.nPos := APosition
  68.       else
  69.         ScrollInfo.nPos := FMax - FPosition;
  70.       FPosition := SetScrollInfo(Handle, SB_CTL, ScrollInfo, lEnabled);
  71.     end
  72.     else
  73.       FPosition := APosition;
  74.   end;
  75.   if HandleAllocated then
  76.     TWSScrollBarClass(WidgetSetClass).SetParams(Self);
  77. {$ENDIF}
  78. end;
replace the procedures ~line 200 handling change of scroll bar min/max/position/page size with
Code: Pascal  [Select]
  1. { FMin, FMax, FPosition and FPage updated by SetParams ~bk }
  2. procedure TCustomScrollBar.SetPosition(Value: Integer);
  3. begin
  4.   if Value<>FPosition then begin
  5.     SetParams(Value, FMin, FMax, FPageSize);
  6.     Change;  // Do it only when position changed
  7.   end;
  8. end;
  9.  
  10. procedure TCustomScrollBar.SetPageSize(Value: Integer);
  11. begin
  12.   if Value<>FPageSize then
  13.     SetParams(FPosition, FMin, FMax, Value);
  14. end;
  15.  
  16. procedure TCustomScrollBar.SetMin(Value: Integer);
  17. begin
  18.   if Value<>FMin then
  19.     SetParams(FPosition, Value, FMax, FPageSize);
  20. end;
  21.  
  22. procedure TCustomScrollBar.SetMax(Value: Integer);
  23. begin
  24.   if Value<>FMax then
  25.     SetParams(FPosition, FMin, Value, FPageSize);
  26. end;
Before class procedure TCustomScrollBar.WSRegisterClass;  add
Code: Pascal  [Select]
  1. { When enabling, need to resync client application ~bk }
  2. procedure TCustomScrollBar.CMEnabledChanged(var Message: TLMessage);
  3. begin
  4.   inherited;
  5.   Change;
  6. end;

Rebuild lazarus and use.
Lazarus trunk r. 62137/27.10.2019 (+/- patches regarding TScrollBar, IntitalSetupDialog, Options.Environment options, SearchResults).  Lazarus 3.0.6 raw from svn.
FPC 3.0.4 32 bits. (+heaptrc with leaked ClassName+Revisited TList) , Windows 10 Pro x64 (v. 1903 / 18362.418)

Birger52

  • Full Member
  • ***
  • Posts: 126
Re: Scrollbar not disabling.
« Reply #10 on: November 22, 2019, 06:08:38 pm »
Same problem in another context.
Scrollbar is drawn enabled, even when enabled is false.

Tried implementing BrunoK's patch - it makes no difference at all.

Win7 64bit
Lazarus #2.04 FPC 3.0.4