Under Win32 scrolling TScrollBox is not possible now when AutoScroll := true
Scrollbox area jumps a little and then all window freeze (the only way
is to wait or switch focus to another application and back to unfreeze)
TScrollBox.Range is calculated on each click on scrollbar !
Attached is my proposition of fix.Please analyze it.
There are still two problems which remain after applying this patch :
1.When controls placed on TScrollBox and aligned , they are scrolled
down instead of up (I feel that it was caused by changes done 2007-11-01)
2. When TScrollBox is scrolled a little and then parent window is
resized - controls placed on scrollbox are moved (usually a little but
sometimes more) - I feel that it worked once I tested but still today
was so many changes in that area :-(
In other cases it works like a charm , for example check lazreport
designer :-)
Regards
Bogusław Brandys
Index: lcl/forms.pp
===================================================================
--- lcl/forms.pp (revision 12682)
+++ lcl/forms.pp (working copy)
@@ -89,8 +89,6 @@
FRange: Integer;
FSmooth : Boolean;
FVisible: Boolean;
- FOldScrollInfo: TScrollInfo;
- FOldScrollInfoValid: Boolean;
protected
FControl: TWinControl;
function ControlAutoScroll: boolean; virtual;
@@ -116,7 +114,6 @@
procedure SetSmooth(const Value: Boolean); virtual;
procedure SetVisible(const Value: Boolean); virtual;
procedure UpdateScrollBar; virtual;
- procedure InvalidateScollInfo;
{$ifdef VerboseScrollingWinControl}
function DebugCondition: Boolean;
{$endif}
@@ -1821,3 +1818,6 @@
+
+
+
Index: lcl/include/controlscrollbar.inc
===================================================================
--- lcl/include/controlscrollbar.inc (revision 12682)
+++ lcl/include/controlscrollbar.inc (working copy)
@@ -68,13 +68,10 @@
// scroll content of FControl
OldPosition := FPosition;
FPosition := Value;
- if FControl is TScrollingWinControl then
- TScrollingWinControl(FControl).ScrollbarHandler(Kind, OldPosition);
// check that the new position is also set on the scrollbar
if HandleAllocated and (GetScrollPos(ControlHandle, IntfBarKind[Kind]) <>
FPosition) then
begin
- InvalidateScollInfo;
{$IFDEF VerboseScrollingWinControl}
if DebugCondition then
DebugLn(['TControlScrollBar.SetPosition FPosition=',FPosition]);
@@ -82,6 +79,13 @@
// send position to interface and store it back to FPosition (this way LCL
will have actual position value)
FPosition := SetScrollPos(ControlHandle, IntfBarKind[Kind], FPosition,
Visible);
end;
+
+ if OldPosition = FPosition then Exit;
+
+
+ if (FControl is TScrollingWinControl) then
+ TScrollingWinControl(FControl).ScrollbarHandler(Kind, OldPosition);
+
end;
function TControlScrollBar.SmoothIsStored: boolean;
@@ -102,7 +106,6 @@
begin
ScrollInfo.fMask := SIF_PAGE;
GetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo);
- InvalidateScollInfo;
FPage := ScrollInfo.nPage;
end;
Result := FPage;
@@ -116,7 +119,6 @@
begin
ScrollInfo.fMask := SIF_POS;
GetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo);
- InvalidateScollInfo;
FPosition := ScrollInfo.nPos;
end;
Result := FPosition;
@@ -130,7 +132,6 @@
begin
ScrollInfo.fMask := SIF_Range + SIF_Page;
GetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo);
- InvalidateScollInfo;
FRange := ScrollInfo.nMax - ScrollInfo.nMin - integer(ScrollInfo.nPage);
end;
Result := FRange;
@@ -144,10 +145,7 @@
function TControlScrollBar.GetVisible: Boolean;
begin
if HandleAllocated and (not (FControl is TScrollingWinControl)) then
- begin
- InvalidateScollInfo;
FVisible := GetScrollbarVisible(Controlhandle, IntfBarKind[Kind]);
- end;
Result := FVisible;
end;
@@ -178,10 +176,8 @@
else
KindID := SM_CXVSCROLL;
if HandleAllocated then
- begin
- Result := LCLIntf.GetScrollBarSize(ControlHandle,KindID);
- InvalidateScollInfo;
- end else
+ Result := LCLIntf.GetScrollBarSize(ControlHandle,KindID)
+ else
Result := GetSystemMetrics(KindID);
end;
@@ -295,12 +291,8 @@
ScrollInfo.nPos := FPosition;
ScrollInfo.nPage := FPage;
ScrollInfo.nTrackPos := FPosition;
- if (not FOldScrollInfoValid) or (not
CompareMem(@ScrollInfo,@FOldScrollInfo,SizeOf(TScrollInfo))) then
- begin
- FOldScrollInfo:=ScrollInfo;
- FOldScrollInfoValid := true;
- SetScrollInfo(FControl.Handle, IntfBarKind[Kind], ScrollInfo, FVisible);
- end;
+ SetScrollInfo(FControl.Handle, IntfBarKind[Kind], ScrollInfo, FVisible);
+
{$IFDEF VerboseScrollingWinControl}
if DebugCondition then
DebugLn(['TControlScrollBar.UpdateScrollBar ',DbgSName(FControl),'
',DbgSName(Self),' FVisible=',FVisible,' Range=',FRange,'
FPosition=',FPosition,' FPage=',FPage,' FAutoRange=',FAutoRange]);
@@ -318,10 +310,6 @@
end;
end;
-procedure TControlScrollBar.InvalidateScollInfo;
-begin
- FOldScrollInfoValid:=false;
-end;
{$ifdef VerboseScrollingWinControl}
function TControlScrollBar.DebugCondition: Boolean;
@@ -372,7 +360,6 @@
NewPos := 0;
if NewPos > FRange then
NewPos := FRange;
- InvalidateScollInfo;
SetPosition(NewPos);
end;
Index: lcl/include/scrollingwincontrol.inc
===================================================================
--- lcl/include/scrollingwincontrol.inc (revision 12682)
+++ lcl/include/scrollingwincontrol.inc (working copy)
@@ -52,20 +52,25 @@
procedure TScrollingWinControl.AlignControls(AControl: TControl;
var ARect: TRect);
begin
+ inherited AlignControls(AControl, ARect);
if (HorzScrollBar=nil) or (VertScrollBar=nil) then exit;
- inherited AlignControls(AControl, ARect);
- HorzScrollBar.AutoCalcRange;
- VertScrollBar.AutoCalcRange;
if not AutoScroll then
UpdateScrollBars;
+
end;
procedure TScrollingWinControl.DoOnResize;
begin
inherited DoOnResize;
+ if (HorzScrollBar=nil) or (VertScrollBar=nil) then exit;
if AutoScroll or HorzScrollBar.Visible or VertScrollBar.Visible
then
+ begin
+ HorzScrollBar.AutoCalcRange;
+ VertScrollBar.AutoCalcRange;
UpdateScrollBars;
+ end;
+
end;
class function TScrollingWinControl.GetControlClassDefaultSize: TPoint;