diff --git a/docs/xml/lcl/forms.xml b/docs/xml/lcl/forms.xml index d4d0f020cb..d3000503a0 100644 --- a/docs/xml/lcl/forms.xml +++ b/docs/xml/lcl/forms.xml @@ -809,8 +809,10 @@ Reads or writes a flag to determine paging increment; default value is 80 pixels - Is the scroll bar visible? - Reads or writes flag to determine visibility, and sets a flag if the property is stored + Can the scroll bar be made visible? + Reads or writes flag to determine visibility, and sets a flag if the property is stored. +The Handle object (widget) is made visible if (Visible=true) and (Range>Page). +To get the current visible state of the widget use the method IsScrollBarVisible. diff --git a/lcl/forms.pp b/lcl/forms.pp index ae1a40ce1e..26c41d72d4 100644 --- a/lcl/forms.pp +++ b/lcl/forms.pp @@ -86,7 +86,7 @@ type TControlScrollBar = class(TPersistent) private - FAutoRange : Longint; + FAutoRange : Longint; // = FRange - ClientSize, >=0 FIncrement: TScrollBarInc; FKind: TScrollBarKind; FPage: TScrollBarInc; @@ -107,7 +107,6 @@ type function GetRange: Integer; virtual; function GetSize: integer; virtual; function GetSmooth: Boolean; virtual; - function GetVisible: Boolean; virtual; function HandleAllocated: boolean; virtual; function IsRangeStored: boolean; virtual; procedure AutoCalcRange; virtual; @@ -130,10 +129,12 @@ type {$endif} function GetHorzScrollBar: TControlScrollBar; virtual; function GetVertScrollBar: TControlScrollBar; virtual; + protected + function ScrollBarShouldBeVisible: Boolean; virtual; // should the widget be made visible? public constructor Create(AControl: TWinControl; AKind: TScrollBarKind); procedure Assign(Source: TPersistent); override; - function IsScrollBarVisible: Boolean; virtual; + function IsScrollBarVisible: Boolean; virtual; // returns current widget state function ScrollPos: Integer; virtual; property Kind: TScrollBarKind read FKind; function GetOtherScrollBar: TControlScrollBar; @@ -148,7 +149,7 @@ type property Position: Integer read GetPosition write SetPosition default 0; // 0..Range-Page property Range: Integer read GetRange write SetRange stored IsRangeStored default 0; // >=Page property Tracking: Boolean read FTracking write SetTracking default False; - property Visible: Boolean read GetVisible write SetVisible default True; + property Visible: Boolean read FVisible write SetVisible default True; end; { TScrollingWinControl } @@ -182,7 +183,6 @@ type constructor Create(TheOwner : TComponent); override; destructor Destroy; override; procedure UpdateScrollbars; - function HasVisibleScrollbars: boolean; virtual; class function GetControlClassDefaultSize: TSize; override; procedure ScrollBy(DeltaX, DeltaY: Integer); published @@ -1590,6 +1590,7 @@ function WindowStateToStr(const State: TWindowState): string; function StrToWindowState(const Name: string): TWindowState; function dbgs(const State: TWindowState): string; overload; function dbgs(const Action: TCloseAction): string; overload; +function dbgs(const Kind: TScrollBarKind): string; overload; type TFocusState = Pointer; @@ -1772,6 +1773,14 @@ begin Result:=GetEnumName(TypeInfo(TCloseAction),ord(Action)); end; +function dbgs(const Kind: TScrollBarKind): string; +begin + if Kind=sbVertical then + Result:='sbVertical' + else + Result:='sbHorizontal'; +end; + //------------------------------------------------------------------------------ function GetParentForm(Control: TControl): TCustomForm; begin diff --git a/lcl/include/controlscrollbar.inc b/lcl/include/controlscrollbar.inc index 7dfef2a48e..738787dd2b 100644 --- a/lcl/include/controlscrollbar.inc +++ b/lcl/include/controlscrollbar.inc @@ -93,7 +93,7 @@ begin ScrollInfo.fMask := SIF_POS; ScrollInfo.nPos := FPosition; - FPosition := SetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo, FVisible); + FPosition := SetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo, ScrollBarShouldBeVisible); end; end; @@ -110,8 +110,11 @@ begin begin ScrollInfo.fMask := SIF_PAGE; GetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo); - InvalidateScrollInfo; - FPage := ScrollInfo.nPage; + if FPage<>ScrollInfo.nPage then + begin + FPage := ScrollInfo.nPage; + InvalidateScrollInfo; + end; end; Result := FPage; end; @@ -124,8 +127,11 @@ begin begin ScrollInfo.fMask := SIF_POS; GetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo); - InvalidateScrollInfo; - FPosition := ScrollInfo.nPos; + if FPosition<>ScrollInfo.nPos then + begin + FPosition := ScrollInfo.nPos; + InvalidateScrollInfo; + end; end; Result := FPosition; end; @@ -133,13 +139,18 @@ end; function TControlScrollBar.GetRange: Integer; var ScrollInfo: TScrollInfo; + NewRange: Integer; begin if HandleAllocated and (not (FControl is TScrollingWinControl)) then begin ScrollInfo.fMask := SIF_Range + SIF_Page; GetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo); - InvalidateScrollInfo; - FRange := ScrollInfo.nMax - ScrollInfo.nMin; + NewRange := ScrollInfo.nMax - ScrollInfo.nMin; + if NewRange<>FRange then + begin + FRange:=NewRange; + InvalidateScrollInfo; + end; end; Result := FRange; end; @@ -149,16 +160,6 @@ begin Result := FSmooth; end; -function TControlScrollBar.GetVisible: Boolean; -begin - if HandleAllocated and (not (FControl is TScrollingWinControl)) then - begin - InvalidateScrollInfo; - FVisible := GetScrollbarVisible(Controlhandle, IntfBarKind[Kind]); - end; - Result := FVisible; -end; - procedure TControlScrollBar.SetIncrement(const AValue: TScrollBarInc); begin // This value is only used by the ScrollHandler procedure @@ -181,10 +182,8 @@ begin else KindID := SM_CXVSCROLL; if HandleAllocated then - begin - Result := LCLIntf.GetScrollBarSize(ControlHandle,KindID); - InvalidateScrollInfo; - end else + Result := LCLIntf.GetScrollBarSize(ControlHandle,KindID) + else Result := GetSystemMetrics(KindID); end; @@ -226,13 +225,18 @@ procedure TControlScrollBar.AutoCalcRange; end; procedure GetPreferredClientRect(out PreferredWidth, PreferredHeight: integer); + var + CurClientRect: TRect; begin PreferredWidth:=0; PreferredHeight:=0; - FControl.GetPreferredSize(PreferredWidth,PreferredHeight,true); - //DebugLn(['GetPreferredClientRect ',DbgSName(FControl),' Pref=',PreferredWidth,'x',PreferredHeight]); - if PreferredWidth<0 then PreferredWidth:=0; - if PreferredHeight<0 then PreferredHeight:=0; + FControl.GetPreferredSize(PreferredWidth,PreferredHeight,true,false); + CurClientRect := FControl.ClientRect; + if PreferredWidth>0 then + PreferredWidth:=Max(0,PreferredWidth-(FControl.Width-CurClientRect.Right)); + if PreferredHeight>0 then + PreferredHeight:=Max(0,PreferredHeight-(FControl.Height-CurClientRect.Bottom)); + //DebugLn(['GetPreferredClientRect ',DbgSName(FControl),' PrefClient=',PreferredWidth,'x',PreferredHeight]); end; procedure AutoCalcVRange; @@ -252,7 +256,7 @@ procedure TControlScrollBar.AutoCalcRange; begin GetPreferredClientRect(PreferredWidth,PreferredHeight); //if FControl.ClassName='TEditorCodetoolsOptionsFrame' then - // DebugLn(['AutoCalcHRange ',DbgSName(FControl),' AutoSize=',FControl.AutoSize,' Bounds=',dbgs(FControl.BoundsRect),' Client=',dbgs(FControl.ClientRect),' pref=',PreferredWidth,'x',PreferredHeight]); + //DebugLn(['AutoCalcHRange ',DbgSName(FControl),' AutoSize=',FControl.AutoSize,' Bounds=',dbgs(FControl.BoundsRect),' Client=',dbgs(FControl.ClientRect),' pref=',PreferredWidth,'x',PreferredHeight]); InternalSetRange(PreferredWidth); end; @@ -282,21 +286,21 @@ begin ScrollInfo.nPos := FPosition; ScrollInfo.nPage := FPage; ScrollInfo.nTrackPos := FPosition; + NewVisible := ScrollBarShouldBeVisible; if (not FOldScrollInfoValid) or (not CompareMem(@ScrollInfo, @FOldScrollInfo, SizeOf(TScrollInfo))) then begin FOldScrollInfo := ScrollInfo; FOldScrollInfoValid := True; - SetScrollInfo(FControl.Handle, IntfBarKind[Kind], ScrollInfo, FVisible); + SetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo, NewVisible); // update policy too ScrollInfo.fMask := SIF_UPDATEPOLICY; ScrollInfo.nTrackPos := TrackToPolicyMap[FTracking]; - SetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo, FVisible); + SetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo, NewVisible); end; - NewVisible := Visible and (ScrollInfo.nMax > ScrollInfo.nPage); ShowScrollBar(FControl.Handle, IntfBarKind[Kind], NewVisible); {$IFDEF VerboseScrollingWinControl} if DebugCondition then - DebugLn(['TControlScrollBar.UpdateScrollBar ',DbgSName(FControl),' ',DbgSName(Self),' FVisible=',FVisible,' Range=',FRange,' FPosition=',FPosition,' FPage=',FPage,' FAutoRange=',FAutoRange]); + DebugLn(['TControlScrollBar.UpdateScrollBar ',DbgSName(FControl),' ',DbgSName(Self),' FVisible=',FVisible,' Range=',FRange,' FPosition=',FPosition,' FPage=',FPage,' FAutoRange=',FAutoRange,' ShouldVisible=',NewVisible]); {$ENDIF} end; @@ -399,8 +403,8 @@ begin Exit; FRange := AValue; {$IFDEF VerboseScrollingWinControl} - if DebugCondition then - DebugLn(['TControlScrollBar.SetRange ',Self,' fRange=',FRange]); + //if DebugCondition then + DebugLn(['TControlScrollBar.SetRange ',dbgs(Kind),' ',Self,' fRange=',FRange]); {$ENDIF} ControlUpdateScrollBars; end; @@ -427,7 +431,7 @@ begin ScrollInfo.cbSize := SizeOf(ScrollInfo); ScrollInfo.fMask := SIF_UPDATEPOLICY; ScrollInfo.nTrackPos := TrackToPolicyMap[FTracking]; - SetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo, FVisible); + SetScrollInfo(ControlHandle, IntfBarKind[Kind], ScrollInfo, ScrollBarShouldBeVisible); end; function TControlScrollBar.ControlHandle: HWnd; @@ -470,8 +474,9 @@ end; function TControlScrollBar.IsScrollBarVisible: Boolean; begin - Result := (FControl <> nil) and FControl.HandleAllocated and - FControl.IsControlVisible and Visible; + Result:=FVisible; + if Result and HandleAllocated then + Result := GetScrollbarVisible(ControlHandle, IntfBarKind[Kind]); end; function TControlScrollBar.ScrollPos: Integer; @@ -501,14 +506,14 @@ end; function TControlScrollBar.ClientSizeWithBar: integer; begin Result:=ClientSize; - if not Visible then + if not IsScrollBarVisible then dec(Result,GetSize); end; function TControlScrollBar.ClientSizeWithoutBar: integer; begin Result:=ClientSize; - if Visible then + if IsScrollBarVisible then inc(Result,GetSize); end; @@ -528,4 +533,9 @@ begin Result:=nil; end; +function TControlScrollBar.ScrollBarShouldBeVisible: Boolean; +begin + Result:=FVisible and (FRange>FPage); +end; + // included by forms.pp diff --git a/lcl/include/scrollingwincontrol.inc b/lcl/include/scrollingwincontrol.inc index ec401de0ed..94d7e03702 100644 --- a/lcl/include/scrollingwincontrol.inc +++ b/lcl/include/scrollingwincontrol.inc @@ -110,14 +110,15 @@ end; function TScrollingWinControl.ComputeScrollbars: Boolean; // true if something changed -// update Page, AutoRange, Visible +// update Page, AutoRange, IsScrollBarVisible - procedure UpdateRange(p_Bar: TControlScrollBar); + function UpdateRange(p_Bar: TControlScrollBar): Boolean; var SBSize: Longint; OtherScrollbar: TControlScrollBar; OldAutoRange: LongInt; begin + Result:=false; OldAutoRange := p_Bar.FAutoRange; p_Bar.FAutoRange := 0; OtherScrollbar := p_Bar.GetOtherScrollBar; @@ -139,7 +140,7 @@ var begin Result := False; - // page (must be smaller than Range and at least 1) + // page (must be smaller than Range but at least 1) NewPage := Max(1,Min(VertScrollbar.ClientSize, High(HorzScrollbar.FPage))); if NewPage <> HorzScrollbar.FPage then begin @@ -153,8 +154,8 @@ begin Result := True; end; // range - UpdateRange(HorzScrollbar); - UpdateRange(VertScrollbar); + if UpdateRange(HorzScrollbar) then Result:=true; + if UpdateRange(VertScrollbar) then Result:=true; end; procedure TScrollingWinControl.UpdateScrollbars; @@ -168,7 +169,7 @@ begin FIsUpdating := True; try if AutoScroll then - ComputeScrollbars; // page, autorange, visible + ComputeScrollbars; // page, autorange, IsScrollBarVisible FVertScrollbar.UpdateScrollbar; FHorzScrollbar.UpdateScrollbar; finally @@ -176,12 +177,6 @@ begin end; end; -function TScrollingWinControl.HasVisibleScrollbars: boolean; -begin - Result := (VertScrollBar <> nil) and VertScrollBar.Visible and - (HorzScrollBar <> nil) and HorzScrollBar.Visible; -end; - function TScrollingWinControl.StoreScrollBars : Boolean; begin Result := not AutoScroll; diff --git a/lcl/include/wincontrol.inc b/lcl/include/wincontrol.inc index 5259d8e407..8644b2ea4a 100644 --- a/lcl/include/wincontrol.inc +++ b/lcl/include/wincontrol.inc @@ -7899,11 +7899,17 @@ begin finally Layout.Free; end; - + + NewWidth:=0; + NewHeight:=0; // add the control border around the client area CurClientRect := GetClientRect; - NewWidth:=Width-CurClientRect.Right+NewClientWidth; - NewHeight:=Height-CurClientRect.Bottom+NewClientHeight; + if (NewClientWidth>0) + or ((NewClientWidth=0) and (csAutoSize0x0 in ControlStyle)) then + NewWidth:=Width-CurClientRect.Right+NewClientWidth; + if (NewClientHeight>0) + or ((NewClientHeight=0) and (csAutoSize0x0 in ControlStyle)) then + NewHeight:=Height-CurClientRect.Bottom+NewClientHeight; {$IF defined(VerboseAutoSize) or defined(VerboseAllAutoSize)} debugln(['TWinControl.CalculatePreferredSize ',DbgSName(Self), ' HandleAllocated=',HandleAllocated, @@ -7915,9 +7921,11 @@ begin PreferredWidth:=Max(PreferredWidth,NewWidth); PreferredHeight:=Max(PreferredHeight,NewHeight); end; - if (PreferredWidth>0) then + if (PreferredWidth>0) + or ((PreferredWidth=0) and (csAutoSize0x0 in ControlStyle)) then inc(PreferredWidth,BorderSpacing.InnerBorder*2); - if PreferredHeight>0 then + if (PreferredHeight>0) + or ((PreferredHeight=0) and (csAutoSize0x0 in ControlStyle)) then inc(PreferredHeight,BorderSpacing.InnerBorder*2); {$IFDEF VerboseAutoSize} debugln('TWinControl.CalculatePreferredSize ',DbgSName(Self),