fcscrollbar.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:26k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit fcScrollBar;
  2. {
  3. //
  4. // Components : TfcScrollBar
  5. //
  6. // Copyright (c) 1999 by Woll2Woll Software
  7. }
  8. interface
  9. {$include fcifdef.pas}
  10. uses
  11.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  12.   {$ifdef fcDelphi7Up}
  13.   Themes,
  14.   {$endif}
  15.   {$ifdef ThemeManager}
  16.   thememgr, themesrv, uxtheme,
  17.   {$endif}
  18.   fcCommon, ExtCtrls;
  19. type
  20.   TfcCustomScrollBar = class;
  21.   TfcScrollBarHitTest = (htNone, htIncBtn, htDecBtn, htPageUp, htPageDown, htThumb);
  22.   TfcScrollPosChangeEvent = procedure(Sender: TfcCustomScrollBar; PriorValue, NewValue: Integer) of object;
  23. TfcScrollbarRepeatInterval = class(TPersistent)
  24. private
  25.   FInitialDelay: Integer;
  26.   FRepeatInterval: Integer;
  27. public
  28.   constructor Create;
  29. published
  30.   property InitialDelay: Integer read FInitialDelay write FInitialDelay;
  31.   property Interval: Integer read FRepeatInterval write FRepeatInterval;
  32. end;
  33.   TfcCustomScrollBar = class(TGraphicControl)
  34.   private
  35.     // Property Storage Variables
  36.     FOnChange: TfcScrollPosChangeEvent;
  37.     FKind: TScrollBarKind;
  38.     FMax: Integer;
  39.     FMin: Integer;
  40.     FPageSize: Integer;
  41.     FPosition: Integer;
  42.     FSmallChange: TScrollBarInc;
  43.     FTimer: TTimer;
  44. //    FTimerClear: boolean;
  45.     FFixedThumbSize: boolean;
  46.     // Other Storage Variables
  47.     FClickedPos: TfcScrollBarHitTest;
  48.     FRepeatInterval: TfcScrollbarRepeatInterval;
  49.     DragOffset: integer;
  50.     DragOrigPosition: integer;
  51.     FContinuousDrag: boolean;
  52.     FMinThumbSize: integer;
  53.     FPriorPosition: integer;
  54.     FLastMouseMovePos: TfcScrollBarHitTest;
  55.     // Property Access Methods
  56.     procedure SetKind(Value: TScrollBarKind);
  57.     procedure SetMax(Value: Integer);
  58.     procedure SetMin(Value: Integer);
  59.     procedure SetPageSize(Value: Integer);
  60.     procedure SetPosition(Value: Integer);
  61.     procedure SetSmallChange(Value: TScrollBarInc);
  62. //    procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
  63.     procedure CMDesignHitTest(var Message: TCMDesignHitTest); message CM_DESIGNHITTEST;
  64.     procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
  65.     procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  66.     procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBkgnd;
  67.   protected
  68.     // Overridden Methods
  69.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  70.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  71.     procedure Paint; override;
  72.     procedure PaintScrollRegion(All: boolean); overload; virtual;
  73.     // Virtual Methods
  74.     function GetSectionRect(Section: TfcScrollBarHitTest;
  75.          DeltaX: integer = 0; DeltaY: integer = 0): TRect;
  76.     procedure MouseLoop(X, Y: Integer); virtual;
  77.     procedure MouseLoop_MouseUp(X, Y: Integer; ACursorPos: TPoint); virtual;
  78.     procedure ScrollPosChange(OldPos, NewPos: Integer); virtual;
  79.     procedure TimerEvent(Sender: TObject);
  80.     procedure Scroll(ScrollCode: integer; Position: integer); virtual;
  81.     procedure WndProc(var Message: TMessage); override;
  82.     function ScrollScreenRange: integer;
  83.     procedure AdjustThumb(var ThumbSize: integer); virtual;
  84.   public
  85.     Patch: Variant;
  86.     constructor Create(AOwner: TComponent); override;
  87.     destructor Destroy; override;
  88.     function HasScrollRange: boolean; virtual;
  89.     // Public Methods
  90. //    procedure PaintScrollRegion(dc: HDC; ARect: TRect); overload; virtual;
  91.     function GetHitTestInfo(X, Y: Integer): TfcScrollBarHitTest; virtual;
  92.     procedure Invalidate; override;
  93.     procedure MoveScrollPos;
  94.     procedure SetParams(APosition, AMax, AMin: Integer); virtual;
  95. //    procedure InvalidateThumb;
  96.     // Public Properties
  97.     property MinThumbSize: integer read FMinThumbSize write FMinThumbSize default 8;
  98.     property FixedThumbSize: boolean read FFixedThumbSize write FFixedThumbSize;
  99.     property Kind: TScrollBarKind read FKind write SetKind;
  100.     property Max: Integer read FMax write SetMax;
  101.     property Min: Integer read FMin write SetMin;
  102.     property PageSize: Integer read FPageSize write SetPageSize;
  103.     property PriorPosition: integer read FPriorPosition;
  104.     property Position: Integer read FPosition write SetPosition;
  105.     property SmallChange: TScrollBarInc read FSmallChange write SetSmallChange;
  106.     property ContinuousDrag: boolean read FContinuousDrag write FContinuousDrag;
  107.     property RepeatInterval: TfcScrollBarRepeatInterval read FRepeatInterval write FRepeatInterval;
  108.     property OnChange: TfcScrollPosChangeEvent read FOnChange write FOnChange;
  109.   end;
  110.   TfcScrollBar = class(TfcCustomScrollBar)
  111.   published
  112.     property Kind;
  113.     property Max;
  114.     property Min;
  115.     property PageSize;
  116.     property Position;
  117.     property SmallChange;
  118.     property OnChange;
  119.   end;
  120. procedure Register;
  121. implementation
  122. //const incr=0;
  123. const incr=1;  // Incr of 0 causes child detail not to work in fcdbtreeview
  124. procedure Register;
  125. begin
  126. //  RegisterComponents('First Class', [TfcScrollBar]);
  127. end;
  128. constructor TfcScrollbarRepeatInterval.Create;
  129. begin
  130.   FInitialDelay := 500;
  131.   FRepeatInterval := 50;
  132. end;
  133. destructor TfcCustomScrollBar.Destroy;
  134. begin
  135.    FRepeatInterval.Free;
  136.    inherited;
  137. end;
  138. constructor TfcCustomScrollBar.Create(AOwner: TComponent);
  139. begin
  140.   inherited;
  141.   FKind := sbVertical;
  142.   Width := GetSystemMetrics(SM_CXVSCROLL);
  143.   Height := 100;
  144.   FMin := 0;
  145.   FMax := 100;
  146.   FSmallChange := 1;
  147.   FPageSize := 10; //Width;
  148.   FRepeatInterval := TfcScrollbarRepeatInterval.Create;
  149.   FTimer := TTimer.Create(self);
  150.   FTimer.Interval := RepeatInterval.InitialDelay;
  151.   FTimer.OnTimer := TimerEvent;
  152.   DragOrigPosition:= -1;
  153.   FMinThumbSize:= 8;
  154.   FLastMouseMovePos:= htNone;
  155. end;
  156. procedure TfcCustomScrollBar.TimerEvent(Sender: TObject);
  157. var ACursor: TPoint;
  158. begin
  159.   if GetKeyState(VK_LBUTTON) >= 0 then
  160.   begin
  161.     FTimer.Enabled := False;
  162. //    FTimerClear:= True;
  163.     invalidate; { Repaint so pageUp/pageDown area repainted }
  164. //    Update;
  165. //    FTimerClear:= False;
  166.     Exit;
  167.   end;
  168.   FTimer.Interval := RepeatInterval.Interval;
  169.   GetCursorPos(ACursor);
  170.   ACursor := ScreenToClient(ACursor);
  171.   if GetHitTestInfo(ACursor.X, ACursor.Y)=FClickedPos then
  172.   begin
  173.      MoveScrollPos;
  174.   end;
  175.   Invalidate;
  176. //  PaintScrollRegion(False); { Don't invalidate whole region to prevent flicker }
  177. end;
  178. procedure TfcCustomScrollBar.SetKind(Value: TScrollBarKind);
  179. begin
  180.   if FKind <> Value then
  181.   begin
  182.     FKind := Value;
  183.   end;
  184. end;
  185. procedure TfcCustomScrollBar.SetMax(Value: Integer);
  186. begin
  187.   if FMax <> Value then
  188.   begin
  189.     FMax := Value;
  190.   end;
  191. end;
  192. procedure TfcCustomScrollBar.SetMin(Value: Integer);
  193. begin
  194.   if FMin <> Value then
  195.   begin
  196.     FMin := Value;
  197.   end;
  198. end;
  199. procedure TfcCustomScrollBar.SetPageSize(Value: Integer);
  200. begin
  201.   if FPageSize <> Value then
  202.   begin
  203.     FPageSize := Value;
  204.   end;
  205. end;
  206. procedure TfcCustomScrollBar.SetPosition(Value: Integer);
  207. begin
  208.   if FPosition <> Value then
  209.   begin
  210.     FPosition := Value;
  211.     if FPosition > Max-PageSize+1 then FPosition := Max-PageSize+1;
  212.     if FPosition < Min then FPosition := Min;
  213.   end;
  214. end;
  215. procedure TfcCustomScrollBar.SetSmallChange(Value: TScrollBarInc);
  216. begin
  217.   if FSmallChange <> Value then
  218.   begin
  219.     FSmallChange := Value;
  220.   end;
  221. end;
  222. procedure TfcCustomScrollBar.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  223. begin
  224.   inherited;
  225.   FClickedPos := GetHitTestInfo(X, Y);
  226.   if FClickedPos in [htIncBtn, htDecBtn, htPageUp, htPageDown] then
  227.   begin
  228.      MoveScrollPos;
  229.      FTimer.Interval := RepeatInterval.InitialDelay;
  230.      FTimer.Enabled := True;
  231.      Invalidate;
  232.   end;
  233.   MouseLoop(X, Y);
  234. end;
  235. procedure TfcCustomScrollBar.Invalidate;
  236. var r: TRect;
  237. begin
  238.   r := BoundsRect;
  239.   if Parent <> nil then InvalidateRect(Parent.Handle, @r, False);
  240. end;
  241. {procedure TfcCustomScrollBar.InvalidateThumb;
  242. var r,br: TRect;
  243. begin
  244.    if Parent <> nil then begin
  245.       r:= GetSectionRect(htThumb);
  246.       r.Left:= Left + r.Left;
  247.       r.Top:= Top + r.Top;
  248.       r.right:= Left + r.Right;
  249.       r.Bottom:= Top + r.Bottom;
  250.       InvalidateRect(Parent.Handle, @r, False);
  251.       r:= GetSectionRect(htPageUp);
  252.       r.Left:= Left + r.Left;
  253.       r.Top:= Top + r.Top;
  254.       r.right:= Left + r.Right;
  255.       r.Bottom:= Top + r.Bottom;
  256.       InvalidateRect(Parent.Handle, @r, False);
  257.       r:= GetSectionRect(htPageDown);
  258.       r.Left:= Left + r.Left;
  259.       r.Top:= Top + r.Top;
  260.       r.right:= Left + r.Right;
  261.       r.Bottom:= Top + r.Bottom;
  262.       InvalidateRect(Parent.Handle, @r, False);
  263.    end;
  264. end;
  265. }
  266. procedure TfcCustomScrollBar.MouseLoop(X, Y: Integer);
  267. var ACursor: TPoint;
  268.     Msg: TMsg;
  269.     FirstTimeMouseMove: boolean;
  270. begin
  271.   SetCapture(Parent.Handle);
  272.   FirstTimeMouseMove:= True;
  273.   DragOffset:= 0;
  274.   try
  275.     while GetCapture = Parent.Handle do
  276.     begin
  277.       GetCursorPos(ACursor);
  278.       case Integer(GetMessage(Msg, 0, 0, 0)) of
  279.         -1: Break;
  280.         0: begin
  281.           PostQuitMessage(Msg.WParam);
  282.           Break;
  283.         end;
  284.       end;
  285.       case Msg.Message of
  286.         WM_MOUSEMOVE: begin
  287.            if FClickedPos in [htIncBtn, htDecBtn, htPageUp, htPageDown] then
  288.               continue;
  289.            if FirstTimeMouseMove then DragOrigPosition:= Position;
  290.            ACursor := ScreenToClient(ACursor);
  291.            if ACursor.X<0 then continue;
  292.            if ACursor.Y<0 then continue;
  293.            if Kind = sbVertical then
  294.            begin
  295.               DragOffset:= Acursor.y-y;
  296.               if FirstTimeMouseMove then begin
  297.                 if (Y=ACursor.Y) then continue;
  298.                 FirstTimeMouseMove:= False;
  299.               end
  300.            end
  301.            else begin
  302.               DragOffset:= Acursor.x-x;
  303.               if FirstTimeMouseMove then begin
  304.                 if (X=ACursor.X) then continue;
  305.                 FirstTimeMouseMove:= False;
  306.               end
  307.            end;
  308.            if ContinuousDrag and (FClickedPos in [htThumb]) then begin
  309.               FPriorPosition:= position;
  310.               position:= Trunc(DragOrigPosition + DragOffset/ScrollScreenRange * (Max-Min+incr-PageSize));
  311.               Scroll(SB_THUMBPOSITION, position);
  312.            end;
  313.            PaintScrollRegion(False); { Don't invalidate whole region to prevent flicker }
  314.         end;
  315.         WM_LBUTTONUP: begin
  316.           MouseLoop_MouseUp(X, Y, ACursor);
  317.           TranslateMessage(Msg);   // So OnMouseUp fires
  318.           DispatchMessage(Msg);
  319.           if GetCapture = Parent.Handle then ReleaseCapture;
  320.         end;
  321.         else begin
  322.           TranslateMessage(Msg);   // So OnMouseUp fires
  323.           DispatchMessage(Msg);
  324.         end;
  325.       end;
  326.     end;
  327.   finally
  328.     if GetCapture = Parent.Handle then ReleaseCapture;
  329.     DragOffset:= 0;
  330.     DragOrigPosition:= -1;
  331.   end;
  332. end;
  333. procedure TfcCustomScrollBar.MouseLoop_MouseUp(X, Y: Integer; ACursorPos: TPoint);
  334. begin
  335.   if FClickedPos in [htIncBtn, htDecBtn, htPageUp, htPageDown] then
  336.   begin
  337.      FTimer.Enabled := False;
  338.      FClickedPos := htNone;
  339.      Invalidate;
  340.   end
  341.   else begin
  342.      if (DragOrigPosition>=0) and (DragOffset<>0) then
  343.      begin
  344.         position:= Trunc(DragOrigPosition + DragOffset/ScrollScreenRange * (Max-Min+incr-PageSize));
  345.         Scroll(SB_THUMBPOSITION, position);
  346.      end;
  347.      if fcUseThemes(self) and (FClickedPos = htThumb) then
  348.      begin
  349.         invalidate;
  350.         FClickedPos := htNone;
  351.      end;
  352.   end;
  353. end;
  354. procedure TfcCustomScrollBar.ScrollPosChange(OldPos, NewPos: Integer);
  355. begin
  356.   if Assigned(FOnChange) then FOnChange(self, OldPos, NewPos);
  357. end;
  358. type TfcDirection = (sbLeft, sbRight, sbUp, sbDown);
  359. procedure TfcCustomScrollBar.Paint;
  360. begin
  361.    PaintScrollRegion(True);
  362. end;
  363. procedure TfcCustomScrollBar.PaintScrollRegion(All: boolean);
  364.   procedure PaintButton(Rect: TRect; Direction: TfcDirection; Down: Boolean);
  365.   const
  366.     SCROLLDIRECTIONS: array[TfcDirection] of Integer = (DFCS_SCROLLLEFT, DFCS_SCROLLRIGHT,
  367.       DFCS_SCROLLDOWN, DFCS_SCROLLUP);
  368.     {$ifdef fcUseThemeManager}
  369.     THEMEDSCROLLDIRECTIONS: array[TfcDirection] of TThemedScrollBar = (tsArrowBtnLeftNormal, tsArrowBtnRightNormal,
  370.       tsArrowBtnDownNormal, tsArrowBtnUpNormal);
  371.     THEMEDHOTSCROLLDIRECTIONS: array[TfcDirection] of TThemedScrollBar = (tsArrowBtnLeftHot, tsArrowBtnRightHot,
  372.       tsArrowBtnDownHot, tsArrowBtnUpHot);
  373.     THEMEDPRESSEDSCROLLDIRECTIONS: array[TfcDirection] of TThemedScrollBar = (tsArrowBtnLeftPressed, tsArrowBtnRightPressed,
  374.       tsArrowBtnDownPressed, tsArrowBtnUpPressed);
  375.     {$endif}
  376.     PUSHED: array[Boolean] of Integer = (0, DFCS_FLAT or DFCS_PUSHED);
  377.     {$ifdef fcUseThemeManager}
  378.   var
  379.      Details: TThemedElementDetails;
  380.      pt: TPoint;
  381.      Hot: boolean;
  382.      {$endif}
  383.   begin
  384.      if fcUseThemes(self) then //ThemeServices.ThemesEnabled then
  385.      begin
  386.        {$ifdef fcUseThemeManager}
  387.         GetCursorPos(pt);
  388.         pt := ScreenToClient(pt);
  389.         Hot:= (PtInRect(Rect,pt));
  390.         if Down then
  391.            Details := ThemeServices.GetElementDetails(ThemedPressedScrollDirections[Direction])
  392.         else if not Hot then
  393.            Details := ThemeServices.GetElementDetails(ThemedScrollDirections[Direction])
  394.         else
  395.            Details := ThemeServices.GetElementDetails(ThemedHotScrollDirections[Direction]);
  396.         ThemeServices.DrawElement(Canvas.Handle, Details, Rect);
  397.        {$endif}
  398.      end
  399.      else begin
  400.         DrawFrameControl(Canvas.Handle, Rect, DFC_SCROLL, SCROLLDIRECTIONS[Direction] or PUSHED[Down]);
  401.      end;
  402.   end;
  403.   procedure PaintClient(Rect: TRect; Down: Boolean);
  404.   var ACursor: TPoint;
  405.       {$ifdef fcUseThemeManager}
  406.       Details: TThemedElementDetails;
  407.       {$endif}
  408.   begin
  409.       GetCursorPos(ACursor);
  410.       ACursor := ScreenToClient(ACursor);
  411.       if Down and (GetHitTestInfo(ACursor.X, ACursor.Y)=FClickedPos) then
  412.       begin
  413.          if fcUseThemes(self) then //ThemeServices.ThemesEnabled then
  414.          begin
  415.            {$ifdef fcUseThemeManager}
  416.             if Kind=sbVertical then
  417.               Details := ThemeServices.GetElementDetails(tsLowerTrackVertPressed)
  418.             else
  419.               Details := ThemeServices.GetElementDetails(tsLowerTrackHorzPressed);
  420.             ThemeServices.DrawElement(Canvas.Handle, Details, Rect);
  421.             {$endif}
  422.          end
  423.          else begin
  424.             fcDither(Canvas, Rect, clBlack, RGB(64,64,64));
  425.          end;
  426.          exit;
  427.       end
  428.       else if fcUseThemes(self) then //ThemeServices.ThemesEnabled then
  429.       begin
  430.         {$ifdef fcUseThemeManager}
  431.          if Kind=sbVertical then
  432.             Details := ThemeServices.GetElementDetails(tsLowerTrackVertNormal)
  433.          else
  434.             Details := ThemeServices.GetElementDetails(tsLowerTrackHorzNormal);
  435.          ThemeServices.DrawElement(Canvas.Handle, Details, Rect);
  436.          {$endif}
  437.       end
  438.       else fcDither(Canvas, Rect, clBtnFace, clWhite);
  439.   end;
  440.   procedure PaintThumb(Rect: TRect);
  441.     {$ifdef fcUseThemeManager}
  442.   var
  443.      Details: TThemedElementDetails;
  444.      pt: TPoint;
  445.      Hot: boolean;
  446.      {$endif}
  447.   begin
  448.      if fcUseThemes(self) then //ThemeServices.ThemesEnabled then
  449.      begin
  450.        {$ifdef fcUseThemeManager}
  451.         if Kind=sbVertical then
  452.            Rect.Top:= Rect.Top - 1
  453.         else begin
  454.            Rect.Left:= Rect.Left - 1;
  455.         end;
  456.         GetCursorPos(pt);
  457.         pt := ScreenToClient(pt);
  458.         Hot:= (PtInRect(Rect,pt));
  459.         if Kind=sbVertical then
  460.         begin
  461.           if FClickedPos=htThumb then
  462.              Details := ThemeServices.GetElementDetails(tsThumbBtnVertPressed)
  463.           else if not Hot then
  464.              Details := ThemeServices.GetElementDetails(tsThumbBtnVertNormal)
  465.           else
  466.              Details := ThemeServices.GetElementDetails(tsThumbBtnVertHot);
  467.           ThemeServices.DrawElement(Canvas.Handle, Details, Rect);
  468.           if FClickedPos=htThumb then
  469.              Details := ThemeServices.GetElementDetails(tsGripperVertPressed)
  470.           else if not Hot then
  471.              Details := ThemeServices.GetElementDetails(tsGripperVertNormal)
  472.           else
  473.              Details := ThemeServices.GetElementDetails(tsGripperVertHot);
  474.           ThemeServices.DrawElement(Canvas.Handle, Details, Rect);
  475.         end
  476.         else begin
  477.           if FClickedPos=htThumb then
  478.              Details := ThemeServices.GetElementDetails(tsThumbBtnHorzPressed)
  479.           else if not Hot then
  480.              Details := ThemeServices.GetElementDetails(tsThumbBtnHorzNormal)
  481.           else
  482.              Details := ThemeServices.GetElementDetails(tsThumbBtnHorzHot);
  483.           ThemeServices.DrawElement(Canvas.Handle, Details, Rect);
  484.           if FClickedPos=htThumb then
  485.              Details := ThemeServices.GetElementDetails(tsGripperHorzPressed)
  486.           else if not Hot then
  487.              Details := ThemeServices.GetElementDetails(tsGripperHorzNormal)
  488.           else
  489.              Details := ThemeServices.GetElementDetails(tsGripperHorzHot);
  490.           ThemeServices.DrawElement(Canvas.Handle, Details, Rect);
  491.         end;
  492. //    tsGripperHorzNormal, tsGripperHorzHot, tsGripperHorzPressed, tsGripperHorzDisabled,
  493. //    tsGripperVertNormal, tsGripperVertHot, tsGripperVertPressed, tsGripperVertDisabled,
  494.         {$endif}
  495.      end
  496.      else begin
  497.         if Kind=sbVertical then
  498.            Rect.Left:= Rect.Left + 1
  499.         else Rect.Top:= Rect.Top + 1;
  500.         DrawFrameControl(Canvas.Handle, Rect, DFC_BUTTON, DFCS_BUTTONPUSH);
  501.         with Rect, Canvas do begin
  502.            Pen.Color := clBtnFace;
  503.            Polyline([Point(Left-1, Bottom-1), Point(Left-1, Top-1), Point(Right+1, Top-1)]);
  504.         end;
  505.      end;
  506.   end;
  507. var IncDir, DecDir: TfcDirection;
  508. begin
  509.   if Kind = sbVertical then
  510.   begin
  511.     IncDir := sbUp;
  512.     DecDir := sbDown;
  513.   end else begin
  514.     IncDir := sbRight;
  515.     DecDir := sbLeft;
  516.   end;
  517. //  if fClickedPos = htPageUp then
  518. //    Screen.cursor:= crArrow;
  519.   if All then
  520.   begin
  521.      PaintButton(GetSectionRect(htIncBtn), IncDir, FClickedPos = htIncBtn);
  522.      PaintButton(GetSectionRect(htDecBtn), DecDir, FClickedPos = htDecBtn);
  523.   end;
  524.   PaintClient(GetSectionRect(htPageUp), FClickedPos=htPageUp);
  525.   PaintClient(GetSectionRect(htPageDown), FClickedPos=htPageDown);
  526.   PaintThumb(GetSectionRect(htThumb));
  527. end;
  528. { Number of pixels in scroll area, thumb region excluded }
  529. Function TfcCustomScrollBar.ScrollScreenRange: integer;
  530. var ThumbSize: integer;
  531. begin
  532.    if Kind = sbVertical then begin
  533.       if FixedThumbSize then
  534.          ThumbSize:= 16
  535.       else begin
  536.          ThumbSize:= Trunc(PageSize/(Max-Min+incr) * (Height-(GetSectionRect(htDecBtn).Bottom)*2));
  537.          ThumbSize:= fcmax(ThumbSize, MinThumbSize);
  538.       end;
  539.       result:= Height-(GetSectionRect(htDecBtn).Bottom)*2-ThumbSize;
  540.    end
  541.    else begin
  542.       ThumbSize:= Trunc(PageSize/(Max-Min+incr) * (Width-(GetSectionRect(htDecBtn).Right)*2));
  543.       result:= Width-(GetSectionRect(htDecBtn).Right)*2-ThumbSize
  544.    end;
  545.    if result=0 then result:= 1;  { Don't allow 0 }
  546. end;
  547. function TfcCustomScrollBar.HasScrollRange: boolean;
  548. begin
  549.    result:= PageSize<Max-Min+incr;
  550. end;
  551. function TfcCustomScrollBar.GetSectionRect(Section: TfcScrollBarHitTest;
  552.          DeltaX: integer = 0; DeltaY: integer = 0): TRect;
  553. var ThumbSize, StartPos: integer;
  554.     Function ScrollScreenRange: integer;
  555.     begin
  556.        if Kind = sbVertical then
  557.           result:= Height-(GetSectionRect(htDecBtn).Bottom)*2-ThumbSize
  558.        else
  559.           result:= Width-(GetSectionRect(htDecBtn).Right)*2-ThumbSize;
  560.     end;
  561. begin
  562.   if PageSize>=Max-Min+incr then exit;
  563.   case Section of
  564.     htNone: result := Rect(0, 0, 0, 0);
  565.     htThumb: begin
  566.       if FixedThumbSize then
  567.          ThumbSize:= 16
  568.       else begin
  569.          if Kind = sbVertical then begin
  570.             ThumbSize:=
  571.               Trunc(PageSize/(Max-Min+incr) * (Height-(GetSectionRect(htDecBtn).Bottom)*2));
  572.             ThumbSize:= fcmax(ThumbSize, MinThumbSize);
  573.          end
  574.          else
  575.             ThumbSize:= Trunc(PageSize/(Max-Min+incr) * (Width-(GetSectionRect(htDecBtn).Right)*2));
  576.       end;
  577.       if DragOrigPosition>=0 then
  578.          StartPos:= Trunc(((DragOrigPosition-Min)/(Max-Min+incr-PageSize)) * ScrollScreenRange)
  579.       else
  580.          StartPos:= Trunc(((Position-Min)/(Max-Min+incr-PageSize)) * ScrollScreenRange);
  581.       // if Other ScrollBar showing then skip the following line
  582.       AdjustThumb(ThumbSize);
  583.       StartPos:= fcLimit(StartPos+DragOffset, 1, ScrollScreenRange);
  584.       if Kind = sbVertical then
  585.       begin
  586.         if StartPos=1 then begin
  587.           StartPos:= StartPos + GetSectionRect(htDecBtn).bottom;
  588.           result := Rect(0, StartPos, Width, StartPos + ThumbSize-1);
  589.         end
  590.         else begin
  591.           StartPos:= StartPos + GetSectionRect(htDecBtn).bottom;
  592.           result := Rect(0, StartPos, Width, StartPos + ThumbSize);
  593.         end;
  594.       end
  595.       else begin
  596.         if StartPos=1 then begin
  597.           StartPos:= StartPos + GetSectionRect(htDecBtn).Right;
  598.           result := Rect(StartPos, 0, StartPos + ThumbSize-1, Height)
  599.         end
  600.         else begin
  601.           StartPos:= StartPos + GetSectionRect(htDecBtn).Right;
  602.           result := Rect(StartPos, 0, StartPos + ThumbSize, Height)
  603.         end
  604.       end;
  605.     end;
  606.     htIncBtn:
  607.       if Kind = sbVertical then
  608.       begin
  609.          if Height<3*GetSystemMetrics(SM_CYVSCROLL) then
  610.             result := Rect(0,
  611.                        Height-fcMin(GetSystemMetrics(SM_CYVSCROLL), Height div 2),
  612.                        Width, Height)
  613.          else
  614.             result := Rect(0,
  615.                        Height-fcMin(GetSystemMetrics(SM_CYVSCROLL), Height div 3),
  616.                        Width, Height)
  617.       end
  618.       else result := Rect(
  619.                        Width-fcMin(GetSystemMetrics(SM_CXHSCROLL), Width div 3), 0,
  620.                        Width, Height);
  621.     htDecBtn:
  622.       if Kind = sbVertical then
  623.          if Height<3*GetSystemMetrics(SM_CYVSCROLL) then
  624.             result := Rect(0, 0, Width,
  625.                   fcMin(GetSystemMetrics(SM_CYVSCROLL), Height div 2))
  626.          else
  627.             result := Rect(0, 0, Width,
  628.                   fcMin(GetSystemMetrics(SM_CYVSCROLL), Height div 3))
  629.       else result := Rect(0, 0,
  630.                   fcMin(GetSystemMetrics(SM_CXHSCROLL), Width div 3),
  631.                   Height);
  632.     htPageUp:
  633.       if Kind = sbVertical then
  634.         result := Rect(0, GetSectionRect(htThumb).Bottom, Width, GetSectionRect(htIncBtn).Top)
  635.       else result := Rect(GetSectionRect(htThumb).Right, 0, GetSectionRect(htIncBtn).Left, Height);
  636.     htPageDown:
  637.       if Kind = sbVertical then
  638.         result := Rect(0, GetSectionRect(htDecBtn).Bottom, Width, GetSectionRect(htThumb).Top)
  639.       else result := Rect(GetSectionRect(htDecBtn).Right, 0, GetSectionRect(htThumb).Left, Height);
  640.   end;
  641.   result.left:= result.left + deltax;
  642.   result.top:= result.top + deltay;
  643.   result.right:= result.right + deltax;
  644.   result.bottom:= result.bottom + deltay;
  645. end;
  646. function TfcCustomScrollBar.GetHitTestInfo(X, Y: Integer): TfcScrollBarHitTest;
  647. begin
  648.   for result := Low(TfcScrollBarHitTest) to High(TfcScrollBarHitTest) do
  649.     if PtInRect(GetSectionRect(result), Point(x, y)) then Break;
  650. end;
  651. procedure TfcCustomScrollBar.MoveScrollPos;
  652. var OldPos, NewPos: Integer;
  653. begin
  654.   OldPos := FPosition;
  655.   FPriorPosition:= FPosition;
  656.   case FClickedPos of
  657.     htIncBtn: begin
  658.        Position := Position + SmallChange;
  659.        {if OldPos<>Position then }Scroll(SB_LINEDOWN, Position);
  660.     end;
  661.     htDecBtn: begin
  662.        Position := Position - SmallChange;
  663.        {if OldPos<>Position then} Scroll(SB_LINEUP, Position);
  664.     end;
  665.     htPageUp: begin
  666.        Position := Position + PageSize;
  667.        {if OldPos<>Position then }Scroll(SB_PAGEDOWN, Position);
  668.     end;
  669.     htPageDown: begin
  670.        Position := Position - PageSize;
  671.        {if OldPos<>Position then }Scroll(SB_PAGEUP, Position);
  672.     end;
  673.   end;
  674.   NewPos := FPosition;
  675.   ScrollPosChange(OldPos, NewPos);
  676. end;
  677. procedure TfcCustomScrollBar.SetParams(APosition, AMax, AMin: Integer);
  678. begin
  679.   FPosition := APosition;
  680.   FMax := AMax;
  681.   FMin := AMin;
  682. end;
  683. procedure TfcCustomScrollBar.Scroll(ScrollCode: integer; Position: integer);
  684. begin
  685. end;
  686. {procedure TfcCustomScrollBar.WMNCHitTest(var Message: TWMNCHitTest);
  687. begin
  688.   DefaultHandler(Message);
  689. end;
  690. }
  691. procedure TfcCustomScrollBar.CMDesignHitTest(var Message: TCMDesignHitTest);
  692. //var HitTest: TfcHitTests;
  693. begin
  694. {   HitTest:= GetHitTestInfoAt(Message.xPos, Message.yPos);
  695.    if fchtToRight in HitTest then begin
  696.       Message.Result:= 1;
  697.    end
  698.    else }
  699.    message.result:= 1;
  700. //   inherited;
  701. end;
  702. procedure TfcCustomScrollBar.AdjustThumb(var ThumbSize: integer);
  703. begin
  704. end;
  705. procedure TfcCustomScrollBar.WndProc(var Message: TMessage);
  706. begin
  707.   inherited;
  708. end;
  709. procedure TfcCustomScrollBar.MouseMove(Shift: TShiftState; X, Y: Integer);
  710. var MouseMovePos: TfcScrollBarHitTest;
  711. begin
  712.   inherited;
  713.    // Later optimize to only invalidate portion that mouse is over
  714.    // ..And only if we have moved to a new location
  715.   if fcUseThemes(self) then //ThemeServices.ThemesEnabled then
  716.   begin
  717.      MouseMovePos:= GetHitTestInfo(X, Y);
  718.      if FLastMouseMovePos<>MouseMovePos then
  719.      begin
  720.         invalidate;
  721.      end;
  722.      FLastMouseMovePos:= MouseMovePos;
  723.   end;
  724. end;
  725. procedure TfcCustomScrollBar.CMMouseEnter(var Message: TMessage);
  726. begin
  727.   inherited;
  728.   if fcuseThemes(self) then //ThemeServices.ThemesEnabled then
  729.   begin
  730.     FLastMouseMovePos:= htNone;
  731.     invalidate;
  732.   end;
  733. end;
  734. procedure TfcCustomScrollBar.CMMouseLeave(var Message: TMessage);
  735. begin
  736.   inherited;
  737.   if fcUseThemes(self) then //ThemeServices.ThemesEnabled then
  738.   begin
  739.     FLastMouseMovePos:= htNone;
  740.     invalidate;
  741.   end;
  742. end;
  743. procedure TfcCustomScrollBar.WMEraseBkgnd(var Message: TWmEraseBkgnd);
  744. begin
  745. {   if fcUseThemes(self) then
  746.    begin
  747.      Message.result:= 1
  748.    end
  749.    else }inherited;
  750. end;
  751. end.