1{%MainUnit ../forms.pp} 2 3{ 4 ***************************************************************************** 5 This file is part of the Lazarus Component Library (LCL) 6 7 See the file COPYING.modifiedLGPL.txt, included in this distribution, 8 for details about the license. 9 ***************************************************************************** 10} 11 12procedure TScrollingWinControl.SetAutoScroll(Value: Boolean); 13begin 14 if FAutoScroll = Value then Exit; 15 FAutoScroll := Value; 16 UpdateScrollBars; 17end; 18 19procedure TScrollingWinControl.CreateWnd; 20begin 21 DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TScrollingWinControl.CreateWnd'){$ENDIF}; 22 try 23 inherited CreateWnd; 24 UpdateScrollBars; 25 finally 26 EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TScrollingWinControl.CreateWnd'){$ENDIF}; 27 end; 28end; 29 30function TScrollingWinControl.GetClientScrollOffset: TPoint; 31begin 32 if (HorzScrollBar <> nil) and (VertScrollBar <> nil) then 33 begin 34 Result.X := HorzScrollBar.Position; 35 Result.Y := VertScrollBar.Position; 36 end else 37 begin 38 Result.X := 0; 39 Result.Y := 0; 40 end; 41end; 42 43function TScrollingWinControl.GetLogicalClientRect: TRect; 44begin 45 Result := ClientRect; 46 {if (FHorzScrollBar.Range>Result.Right) 47 or (FVertScrollBar.Range>Result.Bottom) then 48 DebugLn(['TScrollingWinControl.GetLogicalClientRect Client=',ClientWidth,'x',ClientHeight,' Ranges=',FHorzScrollBar.Range,'x',FVertScrollBar.Range]);} 49 if Assigned(FHorzScrollBar) and FHorzScrollBar.Visible 50 and (FHorzScrollBar.Range > Result.Right) then 51 Result.Right := FHorzScrollBar.Range; 52 if Assigned(FVertScrollBar) and FVertScrollBar.Visible 53 and (FVertScrollBar.Range > Result.Bottom) then 54 Result.Bottom := FVertScrollBar.Range; 55end; 56 57procedure TScrollingWinControl.DoOnResize; 58begin 59 inherited DoOnResize; 60 61 if AutoScroll then 62 begin 63 if (HorzScrollBar = nil) or (VertScrollBar = nil) then Exit; 64 if HorzScrollBar.Visible or VertScrollBar.Visible then 65 UpdateScrollBars; 66 end; 67 //debugln(['TScrollingWinControl.DoOnResize ',DbgSName(Self),' ',dbgs(BoundsRect),' ',dbgs(ClientRect),' ',dbgs(GetLogicalClientRect)]); 68end; 69 70procedure TScrollingWinControl.GetPreferredSizeClientFrame(out aWidth, 71 aHeight: integer); 72// return frame width independent of scrollbars (i.e. as if scrollbars not shown) 73begin 74 if AutoScroll and (VertScrollBar<>nil) then 75 aWidth:=Width-VertScrollBar.ClientSizeWithoutBar 76 else 77 aWidth:=Width-ClientWidth; 78 if AutoScroll and (HorzScrollBar<>nil) then 79 aHeight:=Height-HorzScrollBar.ClientSizeWithoutBar 80 else 81 aHeight:=Height-ClientHeight; 82end; 83 84procedure TScrollingWinControl.AlignControls(AControl: TControl; var ARect: TRect); 85begin 86 if AutoScroll then 87 begin 88 if (HorzScrollBar = nil) or (VertScrollBar = nil) then Exit; 89 inherited AlignControls(AControl, ARect); 90 91 UpdateScrollBars; 92 end 93 else 94 inherited AlignControls(AControl, ARect); 95end; 96 97function TScrollingWinControl.AutoScrollEnabled: Boolean; 98begin 99 Result := not (AutoSize or (DockSite and UseDockManager)); 100end; 101 102procedure TScrollingWinControl.CalculateAutoRanges; 103var 104 NeededClientW: Integer; 105 NeededClientH: Integer; 106 FrameWidth: integer; 107 FrameHeight: integer; 108begin 109 NeededClientW:=0; 110 NeededClientH:=0; 111 GetPreferredSize(NeededClientW,NeededClientH,true,false); 112 GetPreferredSizeClientFrame(FrameWidth,FrameHeight); 113 if NeededClientW>0 then 114 NeededClientW-=FrameWidth; 115 if NeededClientH>0 then 116 NeededClientH-=FrameHeight; 117 118 if HorzScrollBar.Visible then 119 HorzScrollBar.InternalSetRange(NeededClientW) 120 else 121 HorzScrollBar.InternalSetRange(0); 122 123 if VertScrollBar.Visible then 124 VertScrollBar.InternalSetRange(NeededClientH) 125 else 126 VertScrollBar.InternalSetRange(0); 127end; 128 129class function TScrollingWinControl.GetControlClassDefaultSize: TSize; 130begin 131 Result.CX := 150; 132 Result.CY := 150; 133end; 134 135procedure TScrollingWinControl.SetHorzScrollBar(Value: TControlScrollBar); 136begin 137 FHorzScrollbar.Assign(Value); 138end; 139 140procedure TScrollingWinControl.SetVertScrollBar(Value: TControlScrollBar); 141begin 142 FVertScrollbar.Assign(Value); 143end; 144 145procedure TScrollingWinControl.WMSize(var Message: TLMSize); 146var 147 NewState: TWindowState; 148begin 149 inherited; 150 if (Message.SizeType and SIZE_SourceIsInterface) <> 0 then 151 begin 152 NewState := wsNormal; 153 case (Message.SizeType xor SIZE_SourceIsInterface) of 154 SIZE_MINIMIZED: 155 NewState := wsMinimized; 156 SIZE_MAXIMIZED: 157 NewState := wsMaximized; 158 SIZE_FULLSCREEN: 159 NewState := wsFullScreen; 160 end; 161 Resizing(NewState); 162 end; 163end; 164 165procedure TScrollingWinControl.Resizing(State: TWindowState); 166begin 167 // 168end; 169 170procedure TScrollingWinControl.ComputeScrollbars; 171 procedure UpdateBar(aBar: TControlScrollBar; aClientSize: integer); 172 begin 173 // page (must be smaller than Range but at least 1) 174 aBar.FPage := Max(1,Min(Min(aBar.Range,aClientSize), High(HorzScrollbar.FPage))); 175 aBar.FAutoRange := Max(0, aBar.Range - aClientSize); 176 {$IFDEF VerboseScrollingWinControl} 177 debugln(['TScrollingWinControl.ComputeScrollbars ',DbgSName(Self),' ',dbgs(aBar.Kind),' Page=',aBar.Page,' Range=',aBar.Range,' ClientSize=',aClientSize]); 178 {$ENDIF} 179 end; 180 181var 182 ClientW: Integer; 183 ClientH: Integer; 184begin 185 CalculateAutoRanges; 186 187 ClientW:=VertScrollBar.ClientSizeWithoutBar; 188 ClientH:=HorzScrollBar.ClientSizeWithoutBar; 189 {$IFDEF VerboseScrollingWinControl} 190 debugln(['TScrollingWinControl.ComputeScrollbars ',DbgSName(Self),' Bounds=',dbgs(BoundsRect),' ClientRect=',dbgs(ClientRect),' ClientRectNoScrollBars=',ClientW,'x',ClientH]); 191 {$ENDIF} 192 193 if VertScrollBar.Range > ClientH then 194 begin 195 // vertical does not fit -> vertical scrollbar will be shown 196 ClientW:=VertScrollBar.ClientSizeWithBar; 197 end; 198 if HorzScrollBar.Range > ClientW then 199 begin 200 // horizontal does not fit -> horizontal scrollbar will be shown 201 ClientH:=HorzScrollBar.ClientSizeWithBar; 202 if VertScrollBar.Range > ClientH then 203 begin 204 // vertical does not fit, because of the other scrollbar 205 // -> vertical scrollbar will be shown too 206 ClientW:=VertScrollBar.ClientSizeWithBar; 207 end; 208 end; 209 210 UpdateBar(HorzScrollBar,ClientW); 211 UpdateBar(VertScrollBar,ClientH); 212end; 213 214procedure TScrollingWinControl.UpdateScrollbars; 215begin 216 if ([csLoading, csDestroying] * ComponentState <> []) then Exit; 217 if not HandleAllocated then Exit; 218 if (HorzScrollBar = nil) or (VertScrollBar = nil) then Exit; 219 220 if FIsUpdating then Exit; 221 222 FIsUpdating := True; 223 try 224 if AutoScroll then 225 ComputeScrollbars; // page, autorange, IsScrollBarVisible 226 FVertScrollbar.UpdateScrollbar; 227 FHorzScrollbar.UpdateScrollbar; 228 finally 229 FIsUpdating := False; 230 end; 231end; 232 233class procedure TScrollingWinControl.WSRegisterClass; 234begin 235 inherited WSRegisterClass; 236 RegisterScrollingWinControl; 237end; 238 239procedure TScrollingWinControl.ScrollBy(DeltaX, DeltaY: Integer); 240begin 241 ScrollBy_WS(DeltaX, DeltaY); 242end; 243 244procedure TScrollingWinControl.ScrollInView(AControl: TControl); 245var 246 xRect: TRect; 247begin 248 if AControl=nil then 249 Exit; 250 xRect := AControl.BoundsRect; 251 OffsetRect(xRect, -HorzScrollBar.Position, -VertScrollBar.Position); 252 if xRect.Left < 0 then 253 HorzScrollBar.Position := HorzScrollBar.Position + xRect.Left 254 else if xRect.Right > ClientWidth then 255 begin 256 if xRect.Right - xRect.Left > ClientWidth then 257 xRect.Right := xRect.Left + ClientWidth; 258 HorzScrollBar.Position := HorzScrollBar.Position + xRect.Right - ClientWidth; 259 end; 260 if xRect.Top < 0 then 261 VertScrollBar.Position := VertScrollBar.Position + xRect.Top 262 else if xRect.Bottom > ClientHeight then 263 begin 264 if xRect.Bottom - xRect.Top > ClientHeight then 265 xRect.Bottom := xRect.Top + ClientHeight; 266 VertScrollBar.Position := VertScrollBar.Position + xRect.Bottom - ClientHeight; 267 end; 268end; 269 270procedure TScrollingWinControl.Loaded; 271begin 272 inherited Loaded; 273 UpdateScrollbars; 274end; 275 276procedure TScrollingWinControl.SetAutoSize(Value: Boolean); 277begin 278 if AutoSize=Value then exit; 279 if Value then 280 ControlStyle:=ControlStyle-[csAutoSizeKeepChildLeft,csAutoSizeKeepChildTop] 281 else 282 ControlStyle:=ControlStyle+[csAutoSizeKeepChildLeft,csAutoSizeKeepChildTop]; 283 inherited SetAutoSize(Value); 284end; 285 286procedure TScrollingWinControl.WMVScroll(var Message : TLMVScroll); 287begin 288 VertScrollbar.ScrollHandler(Message); 289end; 290 291procedure TScrollingWinControl.WMHScroll(var Message : TLMHScroll); 292begin 293 //DebugLn(['TScrollingWinControl.WMHScroll ',dbgsName(Self)]); 294 HorzScrollbar.ScrollHandler(Message); 295end; 296 297constructor TScrollingWinControl.Create(TheOwner : TComponent); 298begin 299 Inherited Create(TheOwner); 300 301 FAutoScroll := False; 302 FVertScrollbar := TControlScrollBar.Create(Self, sbVertical); 303 FHorzScrollbar := TControlScrollBar.Create(Self, sbHorizontal); 304 305 ControlStyle := [csAcceptsControls, csClickEvents, csDoubleClicks, 306 csAutoSizeKeepChildLeft, csAutoSizeKeepChildTop]; 307 308 with GetControlClassDefaultSize do 309 SetInitialBounds(0, 0, CX, CY); 310end; 311 312destructor TScrollingWinControl.Destroy; 313begin 314 FreeThenNil(FHorzScrollBar); 315 FreeThenNil(FVertScrollBar); 316 inherited Destroy; 317end; 318 319function TScrollingWinControl.ScreenToClient(const APoint: TPoint): TPoint; 320var 321 P: TPoint; 322begin 323 P := GetClientScrollOffset; 324 Result := inherited; 325 Result.x := Result.x - P.x; 326 Result.y := Result.y - P.y; 327end; 328 329function TScrollingWinControl.ClientToScreen(const APoint: TPoint): TPoint; 330var 331 P: TPoint; 332begin 333 P := GetClientScrollOffset; 334 Result := inherited; 335 Result.x := Result.x + P.x; 336 Result.y := Result.y + P.y; 337end; 338 339// included by forms.pp 340