GR32_RangeBars.pas 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135
  1. unit GR32_RangeBars;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Alex A. Denisov
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2009
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. * Andre Beckedorf <[email protected]>
  32. * Marc Lafon
  33. *
  34. * ***** END LICENSE BLOCK ***** *)
  35. interface
  36. {$include GR32.inc}
  37. uses
  38. {$IFDEF FPC}
  39. LCLIntf, LMessages, LCLType, Graphics, Controls, Forms, Dialogs, ExtCtrls,
  40. {$ifdef MSWINDOWS} Windows, {$ENDIF}
  41. {$ELSE}
  42. Windows, Messages, {$IFDEF USEINLINING}Types,{$ENDIF}
  43. Graphics, Controls, Forms, Dialogs, ExtCtrls,
  44. {$ENDIF}
  45. {$ifdef MSWINDOWS}
  46. UxTheme,
  47. {$endif}
  48. SysUtils, Classes, GR32;
  49. type
  50. TRBDirection = (drLeft, drUp, drRight, drDown);
  51. TRBDirections = set of TRBDirection;
  52. TRBZone = (zNone, zBtnPrev, zTrackPrev, zHandle, zTrackNext, zBtnNext);
  53. TRBStyle = (rbsDefault, rbsMac);
  54. TRBBackgnd = (bgPattern, bgSolid);
  55. TRBGetSizeEvent = procedure(Sender: TObject; var Size: Integer) of object;
  56. TArrowBar = class(TCustomControl)
  57. private
  58. FBackgnd: TRBBackgnd;
  59. FBorderStyle: TBorderStyle;
  60. FButtonSize: Integer;
  61. FHandleColor: TColor;
  62. FButtoncolor:TColor;
  63. FHighLightColor:TColor;
  64. FShadowColor:TColor;
  65. FBorderColor:TColor;
  66. FKind: TScrollBarKind;
  67. FShowArrows: Boolean;
  68. FShowHandleGrip: Boolean;
  69. FStyle: TRBStyle;
  70. FOnChange: TNotifyEvent;
  71. FOnUserChange: TNotifyEvent;
  72. FLockUpdate: integer;
  73. procedure SetButtonSize(Value: Integer);
  74. procedure SetHandleColor(Value: TColor);
  75. procedure SetHighLightColor(Value: TColor);
  76. procedure SetShadowColor(Value: TColor);
  77. procedure SetButtonColor(Value: TColor);
  78. procedure SetBorderColor(Value: TColor);
  79. procedure SetKind(Value: TScrollBarKind);
  80. procedure SetShowArrows(Value: Boolean);
  81. procedure SetShowHandleGrip(Value: Boolean);
  82. procedure SetStyle(Value: TRBStyle);
  83. procedure SetBackgnd(Value: TRBBackgnd);
  84. {$IFDEF FPC}
  85. procedure CMEnabledChanged(var Message: TLMessage); message CM_ENABLEDCHANGED;
  86. procedure CMMouseLeave(var Message: TLMessage); message CM_MOUSELEAVE;
  87. procedure WMNCCalcSize(var Message: TLMNCCalcSize); message LM_NCCALCSIZE;
  88. procedure WMEraseBkgnd(var Message: TLmEraseBkgnd); message LM_ERASEBKGND;
  89. {$ifdef MSWINDOWS}
  90. procedure WMNCPaint(var Message: TWMNCPaint); message LM_NCPAINT;
  91. {$ENDIF}
  92. {$ELSE}
  93. procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  94. procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  95. procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
  96. procedure WMNCPaint(var Message: TWMNCPaint); message WM_NCPAINT;
  97. procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
  98. {$ENDIF}
  99. protected
  100. FGenChange: Boolean;
  101. FDragZone: TRBZone;
  102. FHotZone: TRBZone;
  103. FTimer: TTimer;
  104. FTimerMode: Integer;
  105. FStored: TPoint;
  106. FPosBeforeDrag: Single;
  107. {$ifdef MSWINDOWS}
  108. protected
  109. FScrollBarTheme: HTHEME;
  110. function GetScrollBarTheme: HTHEME;
  111. property ScrollBarTheme: HTHEME read GetScrollBarTheme;
  112. {$endif}
  113. protected
  114. procedure BeginLockUpdate;
  115. procedure EndLockUpdate;
  116. property LockUpdate: integer read FLockUpdate;
  117. procedure DoChange; virtual;
  118. procedure DoDrawButton(R: TRect; Direction: TRBDirection; Pushed, Enabled, Hot: Boolean); virtual;
  119. procedure DoDrawHandle(R: TRect; Horz: Boolean; Pushed, Hot: Boolean); virtual;
  120. procedure DoDrawTrack(R: TRect; Direction: TRBDirection; Pushed, Enabled, Hot: Boolean); virtual;
  121. function DrawEnabled: Boolean; virtual;
  122. function GetBorderSize: Integer;
  123. function GetHandleRect: TRect; virtual;
  124. function GetButtonSize: Integer;
  125. function GetTrackBoundary: TRect;
  126. function GetZone(X, Y: Integer): TRBZone;
  127. function GetZoneRect(Zone: TRBZone): TRect;
  128. procedure MouseLeft; virtual;
  129. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  130. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  131. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  132. procedure Paint; override;
  133. procedure SetBorderStyle(Value: TBorderStyle); {$IFDEF FPC} override; {$ENDIF}
  134. procedure StartDragTracking;
  135. procedure StartHotTracking;
  136. procedure StopDragTracking;
  137. procedure StopHotTracking;
  138. procedure TimerHandler(Sender: TObject); virtual;
  139. public
  140. constructor Create(AOwner: TComponent); override;
  141. destructor Destroy; override;
  142. property Color default clScrollBar;
  143. property Backgnd: TRBBackgnd read FBackgnd write SetBackgnd;
  144. property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
  145. property ButtonSize: Integer read FButtonSize write SetButtonSize default 0;
  146. property HandleColor: TColor read FHandleColor write SetHandleColor default clBtnShadow;
  147. property ButtonColor: TColor read FButtonColor write SetButtonColor default clBtnFace;
  148. property HighLightColor: TColor read FHighLightColor write SetHighLightColor default clBtnHighlight;
  149. property ShadowColor: TColor read FShadowColor write SetShadowColor default clBtnShadow;
  150. property BorderColor: TColor read FBorderColor write SetBorderColor default clWindowFrame;
  151. property Kind: TScrollBarKind read FKind write SetKind default sbHorizontal;
  152. property ShowArrows: Boolean read FShowArrows write SetShowArrows default True;
  153. property ShowHandleGrip: Boolean read FShowHandleGrip write SetShowHandleGrip;
  154. property Style: TRBStyle read FStyle write SetStyle default rbsDefault;
  155. property OnChange: TNotifyEvent read FOnChange write FOnChange;
  156. property OnUserChange: TNotifyEvent read FOnUserChange write FOnUserChange;
  157. end;
  158. TRBIncrement = 1..32768;
  159. TRangeBarChangingEvent = procedure(Sender: TObject; ANewPosition: Single; var Handled: boolean) of object;
  160. TCustomRangeBar = class(TArrowBar)
  161. private
  162. FCentered: Boolean;
  163. FEffectiveWindow: Integer;
  164. FIncrement: TRBIncrement;
  165. FPosition: Single;
  166. FRange: Integer;
  167. FWindow: Integer;
  168. FOnUserChanging: TRangeBarChangingEvent;
  169. function IsPositionStored: Boolean;
  170. procedure SetPosition(Value: Single);
  171. procedure SetRange(Value: Integer);
  172. procedure SetWindow(Value: Integer);
  173. protected
  174. procedure DoChanging(ANewPosition: Single; var Handled: boolean); virtual;
  175. procedure AdjustPosition; overload;
  176. procedure AdjustPosition(var APosition: Single); overload;
  177. function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  178. MousePos: TPoint): Boolean; override;
  179. function DrawEnabled: Boolean; override;
  180. function GetHandleRect: TRect; override;
  181. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  182. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  183. procedure TimerHandler(Sender: TObject); override;
  184. procedure UpdateEffectiveWindow;
  185. property EffectiveWindow: Integer read FEffectiveWindow;
  186. public
  187. constructor Create(AOwner: TComponent); override;
  188. procedure Resize; override;
  189. procedure SetParams(NewRange, NewWindow: Integer);
  190. property Centered: Boolean read FCentered write FCentered;
  191. property Increment: TRBIncrement read FIncrement write FIncrement default 8;
  192. property Position: Single read FPosition write SetPosition stored IsPositionStored;
  193. property Range: Integer read FRange write SetRange default 0;
  194. property Window: Integer read FWindow write SetWindow default 0;
  195. property OnUserChanging: TRangeBarChangingEvent read FOnUserChanging write FOnUserChanging;
  196. end;
  197. TRangeBar = class(TCustomRangeBar)
  198. published
  199. property Align;
  200. property Anchors;
  201. property Constraints;
  202. property Color;
  203. property Backgnd;
  204. property BorderStyle;
  205. property ButtonSize;
  206. property Enabled;
  207. property HandleColor;
  208. property ButtonColor;
  209. property HighLightColor;
  210. property ShadowColor;
  211. property BorderColor;
  212. property Increment;
  213. property Kind;
  214. property Range;
  215. property Style;
  216. property Visible;
  217. property Window;
  218. property ShowArrows;
  219. property ShowHandleGrip;
  220. property Position; // this should be located after the Range property
  221. property OnChange;
  222. property OnDragDrop;
  223. property OnDragOver;
  224. property OnEndDrag;
  225. property OnMouseDown;
  226. property OnMouseMove;
  227. property OnMouseUp;
  228. property OnMouseWheelUp;
  229. property OnMouseWheelDown;
  230. property OnStartDrag;
  231. property OnUserChange;
  232. property OnUserChanging;
  233. end;
  234. TGaugeBarChangingEvent = procedure(Sender: TObject; ANewPosition: integer; var Handled: boolean) of object;
  235. TCustomGaugeBar = class(TArrowBar)
  236. private
  237. FHandleSize: Integer;
  238. FLargeChange: Integer;
  239. FMax: Integer;
  240. FMin: Integer;
  241. FPosition: Integer;
  242. FSmallChange: Integer;
  243. FOnUserChanging: TGaugeBarChangingEvent;
  244. procedure SetHandleSize(Value: Integer);
  245. procedure SetMax(Value: Integer);
  246. procedure SetMin(Value: Integer);
  247. procedure SetPosition(Value: Integer);
  248. procedure SetLargeChange(Value: Integer);
  249. procedure SetSmallChange(Value: Integer);
  250. protected
  251. procedure DoChanging(ANewPosition: integer; var Handled: boolean); virtual;
  252. procedure AdjustPosition; overload;
  253. procedure AdjustPosition(var APosition: integer); overload;
  254. function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  255. MousePos: TPoint): Boolean; override;
  256. function GetHandleRect: TRect; override;
  257. function GetHandleSize: Integer;
  258. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  259. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  260. procedure TimerHandler(Sender: TObject); override;
  261. public
  262. constructor Create(AOwner: TComponent); override;
  263. property HandleSize: Integer read FHandleSize write SetHandleSize default 0;
  264. property LargeChange: Integer read FLargeChange write SetLargeChange default 1;
  265. property Max: Integer read FMax write SetMax default 100;
  266. property Min: Integer read FMin write SetMin default 0;
  267. property Position: Integer read FPosition write SetPosition;
  268. property SmallChange: Integer read FSmallChange write SetSmallChange default 1;
  269. property OnChange;
  270. property OnUserChange;
  271. property OnUserChanging: TGaugeBarChangingEvent read FOnUserChanging write FOnUserChanging;
  272. end;
  273. TGaugeBar = class(TCustomGaugeBar)
  274. published
  275. property Align;
  276. property Anchors;
  277. property Constraints;
  278. property Color;
  279. property Backgnd;
  280. property BorderStyle;
  281. property ButtonSize;
  282. property Enabled;
  283. property HandleColor;
  284. property ButtonColor;
  285. property HighLightColor;
  286. property ShadowColor;
  287. property BorderColor;
  288. property HandleSize;
  289. property Kind;
  290. property LargeChange;
  291. property Max;
  292. property Min;
  293. property ShowArrows;
  294. property ShowHandleGrip;
  295. property Style;
  296. property SmallChange;
  297. property Visible;
  298. property Position;
  299. property OnChange;
  300. property OnDragDrop;
  301. property OnDragOver;
  302. property OnEndDrag;
  303. property OnMouseDown;
  304. property OnMouseMove;
  305. property OnMouseUp;
  306. property OnStartDrag;
  307. property OnUserChange;
  308. end;
  309. { TArrowBarAccess }
  310. { This class is designed to facilitate access to
  311. properties of TArrowBar class when creating custom controls, which
  312. incorporate TArrowBar. It allows controlling up to two arrow bars.
  313. Master is used to read and write properties, slave - only to write.
  314. Well, maybe it is not so useful itself, but it is a common ancestor
  315. for TRangeBarAccess and TGaugeBarAccess classes, which work much the
  316. same way.
  317. When writing a new control, which uses TArrowBar, declare the bar as
  318. protected member, TArrowBarAccess as published property, and assign
  319. its Master to the arrow bar }
  320. TArrowBarAccess = class(TPersistent)
  321. private
  322. FMaster: TArrowBar;
  323. FSlave: TArrowBar;
  324. function GetBackgnd: TRBBackgnd;
  325. function GetButtonSize: Integer;
  326. function GetColor: TColor;
  327. function GetHandleColor: TColor;
  328. function GetHighLightColor: TColor;
  329. function GetButtonColor: TColor;
  330. function GetBorderColor: TColor;
  331. function GetShadowColor: TColor;
  332. function GetShowArrows: Boolean;
  333. function GetShowHandleGrip: Boolean;
  334. function GetStyle: TRBStyle;
  335. procedure SetBackgnd(Value: TRBBackgnd);
  336. procedure SetButtonSize(Value: Integer);
  337. procedure SetColor(Value: TColor);
  338. procedure SetHandleColor(Value: TColor);
  339. procedure SetShowArrows(Value: Boolean);
  340. procedure SetShowHandleGrip(Value: Boolean);
  341. procedure SetStyle(Value: TRBStyle);
  342. procedure SetHighLightColor(Value: TColor);
  343. procedure SetShadowColor(Value: TColor);
  344. procedure SetButtonColor(Value: TColor);
  345. procedure SetBorderColor(Value: TColor);
  346. public
  347. property Master: TArrowBar read FMaster write FMaster;
  348. property Slave: TArrowBar read FSlave write FSlave;
  349. published
  350. property Color: TColor read GetColor write SetColor default clScrollBar;
  351. property Backgnd: TRBBackgnd read GetBackgnd write SetBackgnd default bgPattern;
  352. property ButtonSize: Integer read GetButtonSize write SetButtonSize default 0;
  353. property HandleColor: TColor read GetHandleColor write SetHandleColor default clBtnShadow;
  354. property ButtonColor:TColor read GetButtonColor write SetButtonColor default clBtnFace;
  355. property HighLightColor:TColor read GetHighLightColor write SetHighLightColor default clBtnHighlight;
  356. property ShadowColor:TColor read GetShadowColor write SetShadowColor default clBtnShadow;
  357. property BorderColor:TColor read GetBorderColor write SetBorderColor default clWindowFrame;
  358. property ShowArrows: Boolean read GetShowArrows write SetShowArrows default True;
  359. property ShowHandleGrip: Boolean read GetShowHandleGrip write SetShowHandleGrip;
  360. property Style: TRBStyle read GetStyle write SetStyle;
  361. end;
  362. implementation
  363. uses
  364. Math;
  365. const
  366. OppositeDirection: array [TRBDirection] of TRBDirection = (drRight, drDown, drLeft, drUp);
  367. tmScrollFirst = 1;
  368. tmScroll = 2;
  369. tmHotTrack = 3;
  370. function ClrLighten(C: TColor; Amount: Integer): TColor;
  371. var
  372. R, G, B: Integer;
  373. begin
  374. {$ifdef MSWINDOWS}
  375. if C < 0 then C := GetSysColor(C and $000000FF);
  376. {$ELSE}
  377. C := ColorToRGB(C);
  378. {$ENDIF}
  379. R := C and $FF + Amount;
  380. G := C shr 8 and $FF + Amount;
  381. B := C shr 16 and $FF + Amount;
  382. if R < 0 then R := 0 else if R > 255 then R := 255;
  383. if G < 0 then G := 0 else if G > 255 then G := 255;
  384. if B < 0 then B := 0 else if B > 255 then B := 255;
  385. Result := R or (G shl 8) or (B shl 16);
  386. end;
  387. function MixColors(C1, C2: TColor; W1: Integer): TColor;
  388. var
  389. W2: Cardinal;
  390. begin
  391. Assert(W1 in [0..255]);
  392. W2 := W1 xor 255;
  393. {$ifdef MSWINDOWS}
  394. if Integer(C1) < 0 then C1 := GetSysColor(C1 and $000000FF);
  395. if Integer(C2) < 0 then C2 := GetSysColor(C2 and $000000FF);
  396. {$ELSE}
  397. C1 := ColorToRGB(C1);
  398. C2 := ColorToRGB(C2);
  399. {$ENDIF}
  400. Result := Integer(
  401. ((Cardinal(C1) and $FF00FF) * Cardinal(W1) +
  402. (Cardinal(C2) and $FF00FF) * W2) and $FF00FF00 +
  403. ((Cardinal(C1) and $00FF00) * Cardinal(W1) +
  404. (Cardinal(C2) and $00FF00) * W2) and $00FF0000) shr 8;
  405. end;
  406. procedure DitherRect(Canvas: TCanvas; const R: TRect; C1, C2: TColor);
  407. var
  408. {$IFDEF FPC}
  409. Brush: TBrush;
  410. OldBrush: TBrush;
  411. {$ELSE}
  412. B: TBitmap;
  413. Brush: HBRUSH;
  414. {$ENDIF}
  415. begin
  416. if GR32.IsRectEmpty(R) then Exit;
  417. {$IFDEF FPC}
  418. Brush := TBrush.Create;
  419. try
  420. Brush.Color := ColorToRGB(C1);
  421. if C1 <> C2 then
  422. begin
  423. Brush.Bitmap := Graphics.TBitmap.Create;
  424. with Brush.Bitmap do
  425. begin
  426. Height := 2;
  427. Width := 2;
  428. Canvas.Pixels[0,0] := C1;
  429. Canvas.Pixels[1,0] := C2;
  430. Canvas.Pixels[0,1] := C2;
  431. Canvas.Pixels[1,1] := C1;
  432. end;
  433. Brush.Color := ColorToRGB(C1);
  434. end;
  435. OldBrush := TBrush.Create;
  436. try
  437. OldBrush.Assign(Canvas.Brush);
  438. Canvas.Brush.Assign(Brush);
  439. Canvas.FillRect(R);
  440. Canvas.Brush.Assign(OldBrush);
  441. finally
  442. OldBrush.Free;
  443. end;
  444. finally
  445. if Assigned(Brush.Bitmap) then
  446. Brush.Bitmap.Free;
  447. Brush.Free;
  448. end;
  449. {$ELSE}
  450. if C1 = C2 then
  451. Brush := CreateSolidBrush(ColorToRGB(C1))
  452. else
  453. begin
  454. B := AllocPatternBitmap(C1, C2);
  455. B.HandleType := bmDDB;
  456. Brush := CreatePatternBrush(B.Handle);
  457. end;
  458. FillRect(Canvas.Handle, R, Brush);
  459. DeleteObject(Brush);
  460. {$ENDIF}
  461. end;
  462. procedure DrawRectEx(Canvas: TCanvas; var R: TRect; Sides: TRBDirections; C: TColor);
  463. begin
  464. if Sides <> [] then with Canvas, R do
  465. begin
  466. Pen.Color := C;
  467. if drUp in Sides then
  468. begin
  469. MoveTo(Left, Top); LineTo(Right, Top); Inc(Top);
  470. end;
  471. if drDown in Sides then
  472. begin
  473. Dec(Bottom); MoveTo(Left, Bottom); LineTo(Right, Bottom);
  474. end;
  475. if drLeft in Sides then
  476. begin
  477. MoveTo(Left, Top); LineTo(Left, Bottom); Inc(Left);
  478. end;
  479. if drRight in Sides then
  480. begin
  481. Dec(Right); MoveTo(Right, Top); LineTo(Right, Bottom);
  482. end;
  483. end;
  484. end;
  485. procedure Frame3D(Canvas: TCanvas; var ARect: TRect; TopColor, BottomColor: TColor; AdjustRect: Boolean = True);
  486. var
  487. TopRight, BottomLeft: TPoint;
  488. begin
  489. with Canvas, ARect do
  490. begin
  491. Pen.Width := 1;
  492. Dec(Bottom); Dec(Right);
  493. TopRight.X := Right;
  494. TopRight.Y := Top;
  495. BottomLeft.X := Left;
  496. BottomLeft.Y := Bottom;
  497. Pen.Color := TopColor;
  498. PolyLine([BottomLeft, TopLeft, TopRight]);
  499. Pen.Color := BottomColor;
  500. Dec(Left);
  501. PolyLine([TopRight, BottomRight, BottomLeft]);
  502. if AdjustRect then
  503. begin
  504. Inc(Top); Inc(Left, 2);
  505. end
  506. else
  507. begin
  508. Inc(Left); Inc(Bottom); Inc(Right);
  509. end;
  510. end;
  511. end;
  512. procedure DrawHandle(Canvas: TCanvas; R: TRect; Color: TColor;
  513. Pushed, ShowGrip, IsHorz: Boolean; ColorBorder: TColor);
  514. var
  515. CHi, CLo: TColor;
  516. I, S: Integer;
  517. begin
  518. CHi := ClrLighten(Color, 24);
  519. CLo := ClrLighten(Color, -24);
  520. Canvas.Brush.Color := ColorBorder;
  521. FrameRect(Canvas.Handle, R, Canvas.Brush.Handle);
  522. GR32.InflateRect(R, -1, -1);
  523. if Pushed then Frame3D(Canvas, R, CLo, Color)
  524. else Frame3D(Canvas, R, CHi, MixColors(ColorBorder, Color, 96));
  525. Canvas.Brush.Color := Color;
  526. Canvas.FillRect(R);
  527. if ShowGrip then
  528. begin
  529. if Pushed then GR32.OffsetRect(R, 1, 1);
  530. if IsHorz then
  531. begin
  532. S := R.Right - R.Left;
  533. R.Left := (R.Left + R.Right) div 2 - 5;
  534. R.Right := R.Left + 2;
  535. Inc(R.Top); Dec(R.Bottom);
  536. if S > 10 then Frame3D(Canvas, R, CHi, CLo, False);
  537. Inc(R.Left, 3); Inc(R.Right, 3);
  538. Frame3D(Canvas, R, CHi, CLo, False);
  539. Inc(R.Left, 3); Inc(R.Right, 3);
  540. Frame3D(Canvas, R, CHi, CLo, False);
  541. Inc(R.Left, 3); Inc(R.Right, 3);
  542. if S > 10 then Frame3D(Canvas, R, CHi, CLo, False);
  543. end
  544. else
  545. begin
  546. I := (R.Top + R.Bottom) div 2;
  547. S := R.Bottom - R.Top;
  548. R.Top := I - 1;
  549. R.Bottom := I + 1;
  550. Dec(R.Right);
  551. Inc(R.Left);
  552. GR32.OffsetRect(R, 0, -4);
  553. if S > 10 then Frame3D(Canvas, R, CHi, CLo, False);
  554. GR32.OffsetRect(R, 0, 3);
  555. Frame3D(Canvas, R, CHi, CLo, False);
  556. GR32.OffsetRect(R, 0, 3);
  557. Frame3D(Canvas, R, CHi, CLo, False);
  558. if S > 10 then
  559. begin
  560. GR32.OffsetRect(R, 0, 3);
  561. Frame3D(Canvas, R, CHi, CLo, False);
  562. end;
  563. end;
  564. end;
  565. end;
  566. procedure DrawArrow(Canvas: TCanvas; R: TRect; Direction: TRBDirection; Color: TColor);
  567. var
  568. X, Y, Sz, Shift: Integer;
  569. begin
  570. X := (R.Left + R.Right - 1) div 2;
  571. Y := (R.Top + R.Bottom - 1) div 2;
  572. Sz := (Min(X - R.Left, Y - R.Top)) * 3 div 4 - 1;
  573. if Sz = 0 then Sz := 1;
  574. if Direction in [drUp, drLeft] then Shift := (Sz + 1) * 1 div 3
  575. else Shift := Sz * 1 div 3;
  576. Canvas.Pen.Color := Color;
  577. Canvas.Brush.Color := Color;
  578. case Direction of
  579. drUp:
  580. begin
  581. Inc(Y, Shift);
  582. Canvas.Polygon([Point(X + Sz, Y), Point(X, Y - Sz), Point(X - Sz, Y)]);
  583. end;
  584. drDown:
  585. begin
  586. Dec(Y, Shift);
  587. Canvas.Polygon([Point(X + Sz, Y), Point(X, Y + Sz), Point(X - Sz, Y)]);
  588. end;
  589. drLeft:
  590. begin
  591. Inc(X, Shift);
  592. Canvas.Polygon([Point(X, Y + Sz), Point(X - Sz, Y), Point(X, Y - Sz)]);
  593. end;
  594. drRight:
  595. begin
  596. Dec(X, Shift);
  597. Canvas.Polygon([Point(X, Y + Sz), Point(X + Sz, Y), Point(X, Y - Sz)]);
  598. end;
  599. end;
  600. end;
  601. const
  602. FIRST_DELAY = 600;
  603. SCROLL_INTERVAL = 100;
  604. HOTTRACK_INTERVAL = 150;
  605. MIN_SIZE = 17;
  606. { TArrowBar }
  607. {$IFDEF FPC}
  608. procedure TArrowBar.CMEnabledChanged(var Message: TLMessage);
  609. {$ELSE}
  610. procedure TArrowBar.CMEnabledChanged(var Message: TMessage);
  611. {$ENDIF}
  612. begin
  613. inherited;
  614. Invalidate;
  615. end;
  616. {$IFDEF FPC}
  617. procedure TArrowBar.CMMouseLeave(var Message: TLMessage);
  618. {$ELSE}
  619. procedure TArrowBar.CMMouseLeave(var Message: TMessage);
  620. {$ENDIF}
  621. begin
  622. MouseLeft;
  623. inherited;
  624. end;
  625. constructor TArrowBar.Create(AOwner: TComponent);
  626. begin
  627. inherited;
  628. ControlStyle := ControlStyle - [csAcceptsControls, csDoubleClicks] + [csOpaque];
  629. Width := 100;
  630. Height := 16;
  631. ParentColor := False;
  632. Color := clScrollBar;
  633. FTimer := TTimer.Create(Self);
  634. FTimer.OnTimer := TimerHandler;
  635. FShowArrows := True;
  636. FBorderStyle := bsSingle;
  637. FHandleColor := clBtnShadow;
  638. FButtonColor := clBtnFace;
  639. FHighLightColor := clBtnHighlight;
  640. FShadowColor := clBtnShadow;
  641. FBorderColor := clWindowFrame;
  642. FShowHandleGrip := True;
  643. end;
  644. destructor TArrowBar.Destroy;
  645. begin
  646. {$ifdef MSWINDOWS}
  647. if (FScrollBarTheme <> 0) then
  648. CloseThemeData(FScrollBarTheme);
  649. {$endif}
  650. inherited;
  651. end;
  652. procedure TArrowBar.BeginLockUpdate;
  653. begin
  654. Inc(FLockUpdate);
  655. end;
  656. procedure TArrowBar.EndLockUpdate;
  657. begin
  658. Dec(FLockUpdate);
  659. end;
  660. procedure TArrowBar.DoChange;
  661. begin
  662. if (LockUpdate > 0) then
  663. Exit;
  664. BeginLockUpdate;
  665. try
  666. if Assigned(FOnChange) then
  667. FOnChange(Self);
  668. if FGenChange and Assigned(FOnUserChange) then
  669. FOnUserChange(Self);
  670. finally
  671. EndLockUpdate;
  672. end;
  673. end;
  674. procedure TArrowBar.DoDrawButton(R: TRect; Direction: TRBDirection; Pushed, Enabled, Hot: Boolean);
  675. const
  676. EnabledFlags: array [Boolean] of Integer = (DFCS_INACTIVE, 0);
  677. PushedFlags: array [Boolean] of Integer = (0, DFCS_PUSHED or DFCS_FLAT);
  678. DirectionFlags: array [TRBDirection] of Integer = (DFCS_SCROLLLEFT, DFCS_SCROLLUP,
  679. DFCS_SCROLLRIGHT, DFCS_SCROLLDOWN);
  680. {$ifdef MSWINDOWS}
  681. DirectionXPFlags: array [TRBDirection] of Cardinal = (ABS_LEFTNORMAL,
  682. ABS_UPNORMAL, ABS_RIGHTNORMAL, ABS_DOWNNORMAL);
  683. {$ENDIF}
  684. var
  685. Edges: TRBDirections;
  686. {$ifdef MSWINDOWS}
  687. Flags: Integer;
  688. {$ENDIF}
  689. begin
  690. if Style = rbsDefault then
  691. begin
  692. {$IFDEF FPC}
  693. {$IFNDEF Windows}
  694. Canvas.Brush.Color := clBtnface;
  695. Canvas.FillRect(R);
  696. LCLIntf.DrawFrameControl(Canvas.Handle, R, DFC_BUTTON, 0);
  697. InflateRect(R, -2, -2);
  698. If not DrawEnabled then
  699. begin
  700. InflateRect(R, -1, -1);
  701. OffsetRect(R, 1, 1);
  702. DrawArrow(Canvas, R, Direction, clWhite);
  703. OffsetRect(R, -1, -1);
  704. DrawArrow(Canvas, R, Direction, clGrayText);
  705. end
  706. else
  707. begin
  708. If Pushed then OffsetRect(R, 1, 1);
  709. DrawArrow(Canvas, R, Direction, clBtnText);
  710. end;
  711. {$ENDIF}
  712. {$ENDIF}
  713. {$ifdef MSWINDOWS}
  714. if UseThemes then
  715. begin
  716. Flags := DirectionXPFlags[Direction];
  717. if not Enabled then Inc(Flags, 3)
  718. else if Pushed then Inc(Flags, 2)
  719. else if Hot then Inc(Flags);
  720. DrawThemeBackground(ScrollBarTheme, Canvas.Handle, SBP_ARROWBTN, Flags, R, nil);
  721. end
  722. else
  723. DrawFrameControl(Canvas.Handle, R, DFC_SCROLL,
  724. DirectionFlags[Direction] or EnabledFlags[DrawEnabled] or PushedFlags[Pushed])
  725. {$ENDIF}
  726. end
  727. else
  728. begin
  729. Edges := [drLeft, drUp, drRight, drDown];
  730. Exclude(Edges, OppositeDirection[Direction]);
  731. if not DrawEnabled then
  732. begin
  733. DrawRectEx(Canvas, R, Edges, fShadowColor);
  734. Canvas.Brush.Color := fButtonColor;
  735. FillRect(Canvas.Handle, R, Canvas.Brush.Handle);
  736. GR32.InflateRect(R, -1, -1);
  737. GR32.OffsetRect(R, 1, 1);
  738. DrawArrow(Canvas, R, Direction, fHighLightColor);
  739. GR32.OffsetRect(R, -1, -1);
  740. DrawArrow(Canvas, R, Direction, fShadowColor);
  741. end
  742. else
  743. begin
  744. DrawRectEx(Canvas, R, Edges, fBorderColor);
  745. if Pushed then
  746. begin
  747. Canvas.Brush.Color := fButtonColor;
  748. FillRect(Canvas.Handle, R, Canvas.Brush.Handle);
  749. GR32.OffsetRect(R, 1, 1);
  750. GR32.InflateRect(R, -1, -1);
  751. end
  752. else
  753. begin
  754. Frame3D(Canvas, R, fHighLightColor, fShadowColor, True);
  755. Canvas.Brush.Color := fButtonColor;
  756. FillRect(Canvas.Handle, R, Canvas.Brush.Handle);
  757. end;
  758. DrawArrow(Canvas, R, Direction, fBorderColor);
  759. end;
  760. end;
  761. end;
  762. procedure TArrowBar.DoDrawHandle(R: TRect; Horz, Pushed, Hot: Boolean);
  763. {$ifdef MSWINDOWS}
  764. const
  765. PartXPFlags: array [Boolean] of Cardinal = (SBP_THUMBBTNVERT, SBP_THUMBBTNHORZ);
  766. GripperFlags: array [Boolean] of Cardinal = (SBP_GRIPPERVERT, SBP_GRIPPERHORZ);
  767. var
  768. Flags: Cardinal;
  769. {$ENDIF}
  770. begin
  771. if GR32.IsRectEmpty(R) then Exit;
  772. case Style of
  773. rbsDefault:
  774. begin
  775. {$ifdef MSWINDOWS}
  776. if UseThemes then
  777. begin
  778. Flags := SCRBS_NORMAL;
  779. if not Enabled then Inc(Flags, 3)
  780. else if Pushed then Inc(Flags, 2)
  781. else if Hot then Inc(Flags);
  782. DrawThemeBackground(ScrollBarTheme, Canvas.Handle, PartXPFlags[Horz], Flags, R, nil);
  783. if ShowHandleGrip then
  784. DrawThemeBackground(ScrollBarTheme, Canvas.Handle, GripperFlags[Horz], 0, R, nil);
  785. end
  786. else
  787. DrawEdge(Canvas.Handle, R, EDGE_RAISED, BF_RECT or BF_MIDDLE);
  788. {$ENDIF}
  789. end;
  790. rbsMac:
  791. begin
  792. DrawHandle(Canvas, R, HandleColor, Pushed, ShowHandleGrip, Horz, fBorderColor);
  793. end;
  794. end;
  795. end;
  796. procedure TArrowBar.DoDrawTrack(R: TRect; Direction: TRBDirection; Pushed, Enabled, Hot: Boolean);
  797. {$ifdef MSWINDOWS}
  798. const
  799. PartXPFlags: array [TRBDirection] of Cardinal =
  800. (SBP_LOWERTRACKHORZ, SBP_LOWERTRACKVERT, SBP_UPPERTRACKHORZ, SBP_UPPERTRACKVERT);
  801. {$ENDIF}
  802. var
  803. {$ifdef MSWINDOWS}
  804. Flags: Cardinal;
  805. {$ENDIF}
  806. C: TColor;
  807. Edges: set of TRBDirection;
  808. begin
  809. if (R.Right <= R.Left) or (R.Bottom <= R.Top) then Exit;
  810. if Style = rbsDefault then
  811. begin
  812. {$ifdef MSWINDOWS}
  813. if UseThemes then
  814. begin
  815. Flags := SCRBS_NORMAL;
  816. if Pushed then Inc(Flags, 2);
  817. DrawThemeBackground(ScrollBarTheme, Canvas.Handle, PartXPFlags[Direction], Flags, R, nil);
  818. end
  819. else
  820. {$ENDIF}
  821. begin
  822. if Pushed then DitherRect(Canvas, R, clWindowFrame, clWindowFrame)
  823. else DitherRect(Canvas, R, clBtnHighlight, Color);
  824. end;
  825. end
  826. else
  827. with Canvas, R do
  828. begin
  829. if DrawEnabled then C := FBorderColor
  830. else C := FShadowColor;
  831. Edges := [drLeft, drUp, drRight, drDown];
  832. Exclude(Edges, OppositeDirection[Direction]);
  833. DrawRectEx(Canvas, R, Edges, C);
  834. if Pushed then DitherRect(Canvas, R, fBorderColor,fBorderColor)
  835. else if not GR32.IsRectEmpty(R) then with R do
  836. begin
  837. if DrawEnabled then
  838. begin
  839. Pen.Color := MixColors(fBorderColor, MixColors(fHighLightColor, Color, 127), 32);
  840. case Direction of
  841. drLeft, drUp:
  842. begin
  843. MoveTo(Left, Bottom - 1); LineTo(Left, Top); LineTo(Right, Top);
  844. Inc(Top); Inc(Left);
  845. end;
  846. drRight:
  847. begin
  848. MoveTo(Left, Top); LineTo(Right, Top);
  849. Inc(Top);
  850. end;
  851. drDown:
  852. begin
  853. MoveTo(Left, Top); LineTo(Left, Bottom);
  854. Inc(Left);
  855. end;
  856. end;
  857. if Backgnd = bgPattern then DitherRect(Canvas, R, fHighLightColor, Color)
  858. else DitherRect(Canvas, R, Color, Color);
  859. end
  860. else
  861. begin
  862. Brush.Color := fButtonColor;
  863. FillRect(R);
  864. end;
  865. end;
  866. end;
  867. end;
  868. function TArrowBar.DrawEnabled: Boolean;
  869. begin
  870. Result := Enabled;
  871. end;
  872. function TArrowBar.GetBorderSize: Integer;
  873. const
  874. CSize: array [Boolean] of Integer = (0, 1);
  875. begin
  876. Result := CSize[BorderStyle = bsSingle];
  877. end;
  878. function TArrowBar.GetButtonSize: Integer;
  879. var
  880. W, H: Integer;
  881. begin
  882. if not ShowArrows then Result := 0
  883. else
  884. begin
  885. Result := ButtonSize;
  886. if Kind = sbHorizontal then
  887. begin
  888. W := ClientWidth;
  889. H := ClientHeight;
  890. end
  891. else
  892. begin
  893. W := ClientHeight;
  894. H := ClientWidth;
  895. end;
  896. if Result = 0 then Result := Min(H, 32);
  897. if Result * 2 >= W then Result := W div 2;
  898. if Style = rbsMac then Dec(Result);
  899. if Result < 2 then Result := 0;
  900. end;
  901. end;
  902. function TArrowBar.GetHandleRect: TRect;
  903. begin
  904. Result := Rect(0, 0, 0, 0);
  905. end;
  906. {$ifdef MSWINDOWS}
  907. function TArrowBar.GetScrollBarTheme: HTHEME;
  908. begin
  909. if (FScrollBarTheme = 0) then
  910. FScrollBarTheme := OpenThemeData(WindowHandle, 'SCROLLBAR');
  911. Result := FScrollBarTheme;
  912. end;
  913. {$endif}
  914. function TArrowBar.GetTrackBoundary: TRect;
  915. begin
  916. Result := ClientRect;
  917. if Kind = sbHorizontal then GR32.InflateRect(Result, -GetButtonSize, 0)
  918. else GR32.InflateRect(Result, 0, -GetButtonSize);
  919. end;
  920. function TArrowBar.GetZone(X, Y: Integer): TRBZone;
  921. var
  922. P: TPoint;
  923. R, R1: TRect;
  924. Sz: Integer;
  925. begin
  926. Result := zNone;
  927. P := Point(X, Y);
  928. R := ClientRect;
  929. if not GR32.PtInrect(R, P) then Exit;
  930. Sz := GetButtonSize;
  931. R1 := R;
  932. if Kind = sbHorizontal then
  933. begin
  934. R1.Right := R1.Left + Sz;
  935. if GR32.PtInRect(R1, P) then Result := zBtnPrev
  936. else
  937. begin
  938. R1.Right := R.Right;
  939. R1.Left := R.Right - Sz;
  940. if GR32.PtInRect(R1, P) then Result := zBtnNext;
  941. end;
  942. end
  943. else
  944. begin
  945. R1.Bottom := R1.Top + Sz;
  946. if GR32.PtInRect(R1, P) then Result := zBtnPrev
  947. else
  948. begin
  949. R1.Bottom := R.Bottom;
  950. R1.Top := R.Bottom - Sz;
  951. if GR32.PtInRect(R1, P) then Result := zBtnNext;
  952. end;
  953. end;
  954. if Result = zNone then
  955. begin
  956. R := GetHandleRect;
  957. P := Point(X, Y);
  958. if GR32.PtInRect(R, P) then Result := zHandle
  959. else
  960. begin
  961. if Kind = sbHorizontal then
  962. begin
  963. if (X > 0) and (X < R.Left) then Result := zTrackPrev
  964. else if (X >= R.Right) and (X < ClientWidth - 1) then Result := zTrackNext;
  965. end
  966. else
  967. begin
  968. if (Y > 0) and (Y < R.Top) then Result := zTrackPrev
  969. else if (Y >= R.Bottom) and (Y < ClientHeight - 1) then Result := zTrackNext;
  970. end;
  971. end;
  972. end;
  973. end;
  974. function TArrowBar.GetZoneRect(Zone: TRBZone): TRect;
  975. const
  976. CEmptyRect: TRect = (Left: 0; Top: 0; Right: 0; Bottom: 0);
  977. var
  978. BtnSize: Integer;
  979. Horz: Boolean;
  980. R: TRect;
  981. begin
  982. Horz := Kind = sbHorizontal;
  983. BtnSize:= GetButtonSize;
  984. case Zone of
  985. zNone: Result := CEmptyRect;
  986. zBtnPrev:
  987. begin
  988. Result := ClientRect;
  989. if Horz then Result.Right := Result.Left + BtnSize
  990. else Result.Bottom := Result.Top + BtnSize;
  991. end;
  992. zTrackPrev..zTrackNext:
  993. begin
  994. Result := GetTrackBoundary;
  995. R := GetHandleRect;
  996. if not DrawEnabled or GR32.IsRectEmpty(R) then
  997. begin
  998. R.Left := (Result.Left + Result.Right) div 2;
  999. R.Top := (Result.Top + Result.Bottom) div 2;
  1000. R.Right := R.Left;
  1001. R.Bottom := R.Top;
  1002. end;
  1003. case Zone of
  1004. zTrackPrev:
  1005. if Horz then Result.Right := R.Left
  1006. else Result.Bottom := R.Top;
  1007. zHandle:
  1008. Result := R;
  1009. zTrackNext:
  1010. if Horz then Result.Left := R.Right
  1011. else Result.Top := R.Bottom;
  1012. end;
  1013. end;
  1014. zBtnNext:
  1015. begin
  1016. Result := ClientRect;
  1017. if Horz then Result.Left := Result.Right - BtnSize
  1018. else Result.Top := Result.Bottom - BtnSize;
  1019. end;
  1020. end;
  1021. end;
  1022. procedure TArrowBar.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1023. begin
  1024. inherited;
  1025. if Button <> mbLeft then Exit;
  1026. FDragZone := GetZone(X, Y);
  1027. Invalidate;
  1028. FStored.X := X;
  1029. FStored.Y := Y;
  1030. StartDragTracking;
  1031. end;
  1032. procedure TArrowBar.MouseLeft;
  1033. begin
  1034. StopHotTracking;
  1035. end;
  1036. procedure TArrowBar.MouseMove(Shift: TShiftState; X, Y: Integer);
  1037. var
  1038. NewHotZone: TRBZone;
  1039. begin
  1040. inherited;
  1041. if (FDragZone = zNone) and (DrawEnabled) and (MouseCapture) then
  1042. begin
  1043. NewHotZone := GetZone(X, Y);
  1044. if NewHotZone <> FHotZone then
  1045. begin
  1046. FHotZone := NewHotZone;
  1047. if FHotZone <> zNone then StartHotTracking;
  1048. Invalidate;
  1049. end;
  1050. end;
  1051. end;
  1052. procedure TArrowBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1053. begin
  1054. inherited;
  1055. FDragZone := zNone;
  1056. Invalidate;
  1057. StopDragTracking;
  1058. end;
  1059. procedure TArrowBar.Paint;
  1060. const
  1061. CPrevDirs: array [Boolean] of TRBDirection = (drUp, drLeft);
  1062. CNextDirs: array [Boolean] of TRBDirection = (drDown, drRight);
  1063. var
  1064. BSize: Integer;
  1065. ShowEnabled: Boolean;
  1066. R, BtnRect, HandleRect: TRect;
  1067. Horz, ShowHandle: Boolean;
  1068. begin
  1069. R := ClientRect;
  1070. Horz := Kind = sbHorizontal;
  1071. ShowEnabled := DrawEnabled;
  1072. BSize := GetButtonSize;
  1073. if ShowArrows then
  1074. begin
  1075. { left / top button }
  1076. BtnRect := R;
  1077. with BtnRect do if Horz then Right := Left + BSize else Bottom := Top + BSize;
  1078. DoDrawButton(BtnRect, CPrevDirs[Horz], FDragZone = zBtnPrev, ShowEnabled, FHotZone = zBtnPrev);
  1079. { right / bottom button }
  1080. BtnRect := R;
  1081. with BtnRect do if Horz then Left := Right - BSize else Top := Bottom - BSize;
  1082. DoDrawButton(BtnRect, CNextDirs[Horz], FDragZone = zBtnNext, ShowEnabled, FHotZone = zBtnNext);
  1083. end;
  1084. if Horz then GR32.InflateRect(R, -BSize, 0) else GR32.InflateRect(R, 0, -BSize);
  1085. if ShowEnabled then HandleRect := GetHandleRect
  1086. else HandleRect := Rect(0, 0, 0, 0);
  1087. ShowHandle := not GR32.IsRectEmpty(HandleRect);
  1088. DoDrawTrack(GetZoneRect(zTrackPrev), CPrevDirs[Horz], FDragZone = zTrackPrev, ShowEnabled, FHotZone = zTrackPrev);
  1089. DoDrawTrack(GetZoneRect(zTrackNext), CNextDirs[Horz], FDragZone = zTrackNext, ShowEnabled, FHotZone = zTrackNext);
  1090. if ShowHandle then DoDrawHandle(HandleRect, Horz, FDragZone = zHandle, FHotZone = zHandle);
  1091. end;
  1092. procedure TArrowBar.SetBackgnd(Value: TRBBackgnd);
  1093. begin
  1094. if Value <> FBackgnd then
  1095. begin
  1096. FBackgnd := Value;
  1097. Invalidate;
  1098. end;
  1099. end;
  1100. procedure TArrowBar.SetBorderStyle(Value: TBorderStyle);
  1101. begin
  1102. if Value <> FBorderStyle then
  1103. begin
  1104. FBorderStyle := Value;
  1105. {$IFNDEF FPC}
  1106. RecreateWnd;
  1107. {$ELSE}
  1108. Invalidate;
  1109. {$ENDIF}
  1110. end;
  1111. end;
  1112. procedure TArrowBar.SetButtonSize(Value: Integer);
  1113. begin
  1114. if Value <> FButtonSize then
  1115. begin
  1116. FButtonSize := Value;
  1117. Invalidate;
  1118. end;
  1119. end;
  1120. procedure TArrowBar.SetHandleColor(Value: TColor);
  1121. begin
  1122. if Value <> FHandleColor then
  1123. begin
  1124. FHandleColor := Value;
  1125. Invalidate;
  1126. end;
  1127. end;
  1128. procedure TArrowBar.SetHighLightColor(Value: TColor);
  1129. begin
  1130. if Value <> FHighLightColor then
  1131. begin
  1132. FHighLightColor := Value;
  1133. Invalidate;
  1134. end;
  1135. end;
  1136. procedure TArrowBar.SetButtonColor(Value: TColor);
  1137. begin
  1138. if Value <> FButtonColor then
  1139. begin
  1140. FButtonColor := Value;
  1141. Invalidate;
  1142. end;
  1143. end;
  1144. procedure TArrowBar.SetBorderColor(Value: TColor);
  1145. begin
  1146. if Value <> FBorderColor then
  1147. begin
  1148. FBorderColor := Value;
  1149. Invalidate;
  1150. end;
  1151. end;
  1152. procedure TArrowBar.SetShadowColor(Value: TColor);
  1153. begin
  1154. if Value <> FShadowColor then
  1155. begin
  1156. FShadowColor := Value;
  1157. Invalidate;
  1158. end;
  1159. end;
  1160. procedure TArrowBar.SetKind(Value: TScrollBarKind);
  1161. var
  1162. Tmp: Integer;
  1163. begin
  1164. if Value <> FKind then
  1165. begin
  1166. FKind := Value;
  1167. if (csDesigning in ComponentState) and not (csLoading in ComponentState) then
  1168. begin
  1169. Tmp := Width;
  1170. Width := Height;
  1171. Height := Tmp;
  1172. end;
  1173. Invalidate;
  1174. end;
  1175. end;
  1176. procedure TArrowBar.SetShowArrows(Value: Boolean);
  1177. begin
  1178. if Value <> FShowArrows then
  1179. begin
  1180. FShowArrows := Value;
  1181. Invalidate;
  1182. end;
  1183. end;
  1184. procedure TArrowBar.SetShowHandleGrip(Value: Boolean);
  1185. begin
  1186. if Value <> FShowHandleGrip then
  1187. begin
  1188. FShowHandleGrip := Value;
  1189. Invalidate;
  1190. end;
  1191. end;
  1192. procedure TArrowBar.SetStyle(Value: TRBStyle);
  1193. begin
  1194. FStyle := Value;
  1195. {$IFDEF FPC}
  1196. Invalidate;
  1197. {$ELSE}
  1198. RecreateWnd;
  1199. {$ENDIF}
  1200. end;
  1201. procedure TArrowBar.StartDragTracking;
  1202. begin
  1203. FTimer.Interval := FIRST_DELAY;
  1204. FTimerMode := tmScroll;
  1205. TimerHandler(Self);
  1206. FTimerMode := tmScrollFirst;
  1207. FTimer.Enabled := True;
  1208. end;
  1209. procedure TArrowBar.StartHotTracking;
  1210. begin
  1211. FTimer.Interval := HOTTRACK_INTERVAL;
  1212. FTimerMode := tmHotTrack;
  1213. FTimer.Enabled := True;
  1214. end;
  1215. procedure TArrowBar.StopDragTracking;
  1216. begin
  1217. StartHotTracking;
  1218. end;
  1219. procedure TArrowBar.StopHotTracking;
  1220. begin
  1221. FTimer.Enabled := False;
  1222. FHotZone := zNone;
  1223. Invalidate;
  1224. end;
  1225. procedure TArrowBar.TimerHandler(Sender: TObject);
  1226. var
  1227. Pt: TPoint;
  1228. begin
  1229. case FTimerMode of
  1230. tmScrollFirst:
  1231. begin
  1232. FTimer.Interval := SCROLL_INTERVAL;
  1233. FTimerMode := tmScroll;
  1234. end;
  1235. tmHotTrack:
  1236. begin
  1237. Pt := ScreenToClient(Mouse.CursorPos);
  1238. if not GR32.PtInRect(ClientRect, Pt) then
  1239. begin
  1240. StopHotTracking;
  1241. Invalidate;
  1242. end;
  1243. end;
  1244. end;
  1245. end;
  1246. {$IFDEF FPC}
  1247. procedure TArrowBar.WMEraseBkgnd(var Message: TLmEraseBkgnd);
  1248. begin
  1249. Message.Result := -1;
  1250. end;
  1251. procedure TArrowBar.WMNCCalcSize(var Message: TLMNCCalcSize);
  1252. var
  1253. Sz: Integer;
  1254. begin
  1255. Sz := GetBorderSize;
  1256. GR32.InflateRect(Message.CalcSize_Params.rgrc[0], -Sz, -Sz);
  1257. end;
  1258. {$ifdef MSWINDOWS}
  1259. procedure TArrowBar.WMNCPaint(var Message: TWMNCPaint);
  1260. procedure DrawNCArea(ADC: HDC; const Clip: HRGN);
  1261. var
  1262. DC: HDC;
  1263. R: TRect;
  1264. begin
  1265. if BorderStyle = bsNone then Exit;
  1266. if ADC = 0 then DC := GetWindowDC(Handle)
  1267. else DC := ADC;
  1268. try
  1269. GetWindowRect(Handle, R);
  1270. OffsetRect(R, -R.Left, -R.Top);
  1271. DrawEdge(DC, R, BDR_SUNKENOUTER, BF_RECT);
  1272. finally
  1273. if ADC = 0 then ReleaseDC(Handle, DC);
  1274. end;
  1275. end;
  1276. begin
  1277. DrawNCArea(0, Message.RGN);
  1278. end;
  1279. {$ENDIF}
  1280. {$ELSE}
  1281. procedure TArrowBar.WMEraseBkgnd(var Message: TWmEraseBkgnd);
  1282. begin
  1283. Message.Result := -1;
  1284. end;
  1285. procedure TArrowBar.WMNCCalcSize(var Message: TWMNCCalcSize);
  1286. var
  1287. Sz: Integer;
  1288. begin
  1289. Sz := GetBorderSize;
  1290. GR32.InflateRect(Message.CalcSize_Params.rgrc[0], -Sz, -Sz);
  1291. end;
  1292. procedure TArrowBar.WMNCPaint(var Message: TWMNCPaint);
  1293. procedure DrawNCArea(ADC: HDC; const Clip: HRGN);
  1294. var
  1295. DC: HDC;
  1296. R: TRect;
  1297. begin
  1298. if BorderStyle = bsNone then Exit;
  1299. if ADC = 0 then DC := GetWindowDC(Handle)
  1300. else DC := ADC;
  1301. try
  1302. GetWindowRect(Handle, R);
  1303. GR32.OffsetRect(R, -R.Left, -R.Top);
  1304. DrawEdge(DC, R, BDR_SUNKENOUTER, BF_RECT);
  1305. finally
  1306. if ADC = 0 then ReleaseDC(Handle, DC);
  1307. end;
  1308. end;
  1309. begin
  1310. DrawNCArea(0, Message.RGN);
  1311. end;
  1312. {$ENDIF}
  1313. { TCustomRangeBar }
  1314. procedure TCustomRangeBar.AdjustPosition;
  1315. begin
  1316. AdjustPosition(FPosition);
  1317. end;
  1318. procedure TCustomRangeBar.AdjustPosition(var APosition: Single);
  1319. begin
  1320. if (APosition > Range - EffectiveWindow) then
  1321. APosition := Range - EffectiveWindow;
  1322. if (APosition < 0) then
  1323. APosition := 0;
  1324. end;
  1325. constructor TCustomRangeBar.Create(AOwner: TComponent);
  1326. begin
  1327. inherited;
  1328. FIncrement := 8;
  1329. end;
  1330. procedure TCustomRangeBar.DoChanging(ANewPosition: Single; var Handled: boolean);
  1331. begin
  1332. if (LockUpdate > 0) then
  1333. Exit;
  1334. BeginLockUpdate;
  1335. try
  1336. if FGenChange and Assigned(FOnUserChanging) then
  1337. FOnUserChanging(Self, ANewPosition, Handled);
  1338. finally
  1339. EndLockUpdate;
  1340. end;
  1341. end;
  1342. function TCustomRangeBar.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  1343. MousePos: TPoint): Boolean;
  1344. const OneHundredTwenteenth = 1 / 120;
  1345. begin
  1346. Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);
  1347. if not Result then Position := Position + Increment * WheelDelta * OneHundredTwenteenth;
  1348. Result := True;
  1349. end;
  1350. function TCustomRangeBar.DrawEnabled: Boolean;
  1351. begin
  1352. Result := Enabled and (Range > EffectiveWindow);
  1353. end;
  1354. function TCustomRangeBar.GetHandleRect: TRect;
  1355. var
  1356. BtnSz, ClientSz: Integer;
  1357. HandleSz, HandlePos: Integer;
  1358. R: TRect;
  1359. Horz: Boolean;
  1360. begin
  1361. R := Rect(0, 0, ClientWidth, ClientHeight);
  1362. Horz := Kind = sbHorizontal;
  1363. BtnSz := GetButtonSize;
  1364. if Horz then
  1365. begin
  1366. GR32.InflateRect(R, -BtnSz, 0);
  1367. ClientSz := R.Right - R.Left;
  1368. end
  1369. else
  1370. begin
  1371. GR32.InflateRect(R, 0, -BtnSz);
  1372. ClientSz := R.Bottom - R.Top;
  1373. end;
  1374. if ClientSz < 18 then
  1375. begin
  1376. Result := Rect(0, 0, 0, 0);
  1377. Exit;
  1378. end;
  1379. if Range > EffectiveWindow then
  1380. begin
  1381. HandleSz := Round(ClientSz * EffectiveWindow / Range);
  1382. if HandleSz >= MIN_SIZE then HandlePos := Round(ClientSz * Position / Range)
  1383. else
  1384. begin
  1385. HandleSz := MIN_SIZE;
  1386. HandlePos := Round((ClientSz - MIN_SIZE) * Position / (Range - EffectiveWindow));
  1387. end;
  1388. Result := R;
  1389. if Horz then
  1390. begin
  1391. Result.Left := R.Left + HandlePos;
  1392. Result.Right := R.Left + HandlePos + HandleSz;
  1393. end
  1394. else
  1395. begin
  1396. Result.Top := R.Top + HandlePos;
  1397. Result.Bottom := R.Top + HandlePos + HandleSz;
  1398. end;
  1399. end
  1400. else Result := R;
  1401. end;
  1402. function TCustomRangeBar.IsPositionStored: Boolean;
  1403. begin
  1404. Result := FPosition > 0;
  1405. end;
  1406. procedure TCustomRangeBar.MouseDown(Button: TMouseButton;
  1407. Shift: TShiftState; X, Y: Integer);
  1408. begin
  1409. if Range <= EffectiveWindow then FDragZone := zNone
  1410. else
  1411. begin
  1412. inherited;
  1413. if FDragZone = zHandle then
  1414. begin
  1415. StopDragTracking;
  1416. FPosBeforeDrag := Position;
  1417. end;
  1418. end;
  1419. end;
  1420. procedure TCustomRangeBar.MouseMove(Shift: TShiftState; X, Y: Integer);
  1421. var
  1422. Delta: Single;
  1423. WinSz: Single;
  1424. ClientSz, HandleSz: Integer;
  1425. begin
  1426. inherited;
  1427. if (FDragZone = zHandle) and (MouseCapture) then
  1428. begin
  1429. WinSz := EffectiveWindow;
  1430. if Range <= WinSz then Exit;
  1431. if Kind = sbHorizontal then Delta := X - FStored.X else Delta := Y - FStored.Y;
  1432. if Kind = sbHorizontal then ClientSz := ClientWidth else ClientSz := ClientHeight;
  1433. Dec(ClientSz, GetButtonSize * 2);
  1434. if BorderStyle = bsSingle then Dec(ClientSz, 2);
  1435. HandleSz := Round(ClientSz * WinSz / Range);
  1436. if HandleSz < MIN_SIZE then Delta := Round(Delta * (Range - WinSz) / (ClientSz - MIN_SIZE))
  1437. else Delta := Delta * Range / ClientSz;
  1438. try
  1439. FGenChange := True;
  1440. try
  1441. Position := FPosBeforeDrag + Delta;
  1442. finally
  1443. FGenChange := False;
  1444. end;
  1445. except
  1446. // Propagation of exception will cause loss of mouse capture, so we need
  1447. // to emulate mouse release in order to restore internal state.
  1448. if (MouseCapture) then
  1449. begin
  1450. MouseCapture := False;
  1451. MouseUp(mbLeft, Shift, X, Y);
  1452. end;
  1453. raise;
  1454. end;
  1455. end;
  1456. end;
  1457. procedure TCustomRangeBar.Resize;
  1458. var
  1459. OldWindow: Integer;
  1460. Center: Single;
  1461. NewPosition: Single;
  1462. begin
  1463. NewPosition := FPosition;
  1464. if Centered then
  1465. begin
  1466. OldWindow := EffectiveWindow;
  1467. UpdateEffectiveWindow;
  1468. if (Range > EffectiveWindow) then
  1469. begin
  1470. if (Range > OldWindow) and (Range <> 0) then
  1471. Center := (FPosition + OldWindow * 0.5) / Range
  1472. else
  1473. Center := 0.5;
  1474. NewPosition := Center * Range - EffectiveWindow * 0.5;
  1475. end;
  1476. end;
  1477. Position := NewPosition;
  1478. inherited;
  1479. end;
  1480. procedure TCustomRangeBar.SetParams(NewRange, NewWindow: Integer);
  1481. var
  1482. OldWindow, OldRange: Integer;
  1483. Center: Single;
  1484. NewPosition: Single;
  1485. begin
  1486. if (NewRange < 0) then
  1487. NewRange := 0;
  1488. if (NewWindow < 0) then
  1489. NewWindow := 0;
  1490. if (NewRange = FRange) and (NewWindow = EffectiveWindow) then
  1491. exit;
  1492. OldWindow := EffectiveWindow;
  1493. OldRange := Range;
  1494. FRange := NewRange;
  1495. FWindow := NewWindow;
  1496. UpdateEffectiveWindow;
  1497. NewPosition := FPosition;
  1498. if Centered and (Range > EffectiveWindow) then
  1499. begin
  1500. if (OldRange > OldWindow) and (OldRange <> 0) then
  1501. Center := (FPosition + OldWindow * 0.5) / OldRange
  1502. else
  1503. Center := 0.5;
  1504. NewPosition := Center * Range - EffectiveWindow * 0.5;
  1505. end;
  1506. Position := NewPosition;
  1507. Invalidate;
  1508. end;
  1509. procedure TCustomRangeBar.SetPosition(Value: Single);
  1510. var
  1511. NewPosition: Single;
  1512. Handled: boolean;
  1513. begin
  1514. if (Value = FPosition) then
  1515. exit;
  1516. NewPosition := Value;
  1517. AdjustPosition(NewPosition);
  1518. if (NewPosition = FPosition) then
  1519. exit;
  1520. Handled := False;
  1521. DoChanging(NewPosition, Handled);
  1522. if (Handled) then
  1523. exit;
  1524. FPosition := NewPosition;
  1525. Invalidate;
  1526. DoChange;
  1527. end;
  1528. procedure TCustomRangeBar.SetRange(Value: Integer);
  1529. begin
  1530. SetParams(Value, Window);
  1531. end;
  1532. procedure TCustomRangeBar.SetWindow(Value: Integer);
  1533. begin
  1534. SetParams(Range, Value);
  1535. end;
  1536. procedure TCustomRangeBar.TimerHandler(Sender: TObject);
  1537. var
  1538. OldPosition: Single;
  1539. Pt: TPoint;
  1540. function MousePos: TPoint;
  1541. begin
  1542. Result := ScreenToClient(Mouse.CursorPos);
  1543. if Result.X < 0 then Result.X := 0;
  1544. if Result.Y < 0 then Result.Y := 0;
  1545. if Result.X >= ClientWidth then Result.X := ClientWidth - 1;
  1546. if Result.Y >= ClientHeight then Result.Y := ClientHeight - 1
  1547. end;
  1548. begin
  1549. inherited;
  1550. if (not MouseCapture) then
  1551. Exit;
  1552. FGenChange := True;
  1553. try
  1554. OldPosition := Position;
  1555. case FDragZone of
  1556. zBtnPrev:
  1557. begin
  1558. Position := Position - Increment;
  1559. if Position = OldPosition then StopDragTracking;
  1560. end;
  1561. zBtnNext:
  1562. begin
  1563. Position := Position + Increment;
  1564. if Position = OldPosition then StopDragTracking;
  1565. end;
  1566. zTrackNext:
  1567. begin
  1568. Pt := MousePos;
  1569. if GetZone(Pt.X, Pt.Y) in [zTrackNext, zBtnNext] then
  1570. Position := Position + EffectiveWindow;
  1571. end;
  1572. zTrackPrev:
  1573. begin
  1574. Pt := MousePos;
  1575. if GetZone(Pt.X, Pt.Y) in [zTrackPrev, zBtnPrev] then
  1576. Position := Position - EffectiveWindow;
  1577. end;
  1578. end;
  1579. finally
  1580. FGenChange := False;
  1581. end;
  1582. end;
  1583. procedure TCustomRangeBar.UpdateEffectiveWindow;
  1584. begin
  1585. if (FWindow > 0) then
  1586. FEffectiveWindow := FWindow
  1587. else
  1588. begin
  1589. if (Kind = sbHorizontal) then
  1590. FEffectiveWindow := Width
  1591. else
  1592. FEffectiveWindow := Height;
  1593. end;
  1594. end;
  1595. //----------------------------------------------------------------------------//
  1596. { TCustomGaugeBar }
  1597. procedure TCustomGaugeBar.AdjustPosition;
  1598. begin
  1599. AdjustPosition(FPosition);
  1600. end;
  1601. procedure TCustomGaugeBar.AdjustPosition(var APosition: integer);
  1602. begin
  1603. if (APosition < Min) then
  1604. APosition := Min
  1605. else
  1606. if (APosition > Max) then
  1607. APosition := Max;
  1608. end;
  1609. constructor TCustomGaugeBar.Create(AOwner: TComponent);
  1610. begin
  1611. inherited;
  1612. FLargeChange := 1;
  1613. FMax := 100;
  1614. FSmallChange := 1;
  1615. end;
  1616. procedure TCustomGaugeBar.DoChanging(ANewPosition: integer; var Handled: boolean);
  1617. begin
  1618. if (LockUpdate > 0) then
  1619. Exit;
  1620. BeginLockUpdate;
  1621. try
  1622. if FGenChange and Assigned(FOnUserChanging) then
  1623. FOnUserChanging(Self, ANewPosition, Handled);
  1624. finally
  1625. EndLockUpdate;
  1626. end;
  1627. end;
  1628. function TCustomGaugeBar.DoMouseWheel(Shift: TShiftState;
  1629. WheelDelta: Integer; MousePos: TPoint): Boolean;
  1630. begin
  1631. Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);
  1632. if not Result then Position := Position + FSmallChange * WheelDelta div 120;
  1633. Result := True;
  1634. end;
  1635. function TCustomGaugeBar.GetHandleRect: TRect;
  1636. var
  1637. Sz, HandleSz: Integer;
  1638. Horz: Boolean;
  1639. Pos: Integer;
  1640. begin
  1641. Result := GetTrackBoundary;
  1642. Horz := Kind = sbHorizontal;
  1643. HandleSz := GetHandleSize;
  1644. if Horz then Sz := Result.Right - Result.Left
  1645. else Sz := Result.Bottom - Result.Top;
  1646. Pos := Round((Position - Min) / (Max - Min) * (Sz - GetHandleSize));
  1647. if Horz then
  1648. begin
  1649. Inc(Result.Left, Pos);
  1650. Result.Right := Result.Left + HandleSz;
  1651. end
  1652. else
  1653. begin
  1654. Inc(Result.Top, Pos);
  1655. Result.Bottom := Result.Top + HandleSz;
  1656. end;
  1657. end;
  1658. function TCustomGaugeBar.GetHandleSize: Integer;
  1659. var
  1660. R: TRect;
  1661. Sz: Integer;
  1662. begin
  1663. Result := HandleSize;
  1664. if Result = 0 then
  1665. begin
  1666. if Kind = sbHorizontal then Result := ClientHeight else Result := ClientWidth;
  1667. end;
  1668. R := GetTrackBoundary;
  1669. if Kind = sbHorizontal then Sz := R.Right - R.Left
  1670. else Sz := R.Bottom - R.Top;
  1671. if Sz - Result < 1 then Result := Sz - 1;
  1672. if Result < 0 then Result := 0;
  1673. end;
  1674. procedure TCustomGaugeBar.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1675. begin
  1676. inherited;
  1677. if FDragZone = zHandle then
  1678. begin
  1679. StopDragTracking;
  1680. FPosBeforeDrag := Position;
  1681. end;
  1682. end;
  1683. procedure TCustomGaugeBar.MouseMove(Shift: TShiftState; X, Y: Integer);
  1684. var
  1685. Delta: Single;
  1686. R: TRect;
  1687. ClientSz: Integer;
  1688. begin
  1689. inherited;
  1690. if (FDragZone = zHandle) and (MouseCapture) then
  1691. begin
  1692. if Kind = sbHorizontal then Delta := X - FStored.X else Delta := Y - FStored.Y;
  1693. R := GetTrackBoundary;
  1694. if Kind = sbHorizontal then ClientSz := R.Right - R.Left
  1695. else ClientSz := R.Bottom - R.Top;
  1696. Delta := Delta * (Max - Min) / (ClientSz - GetHandleSize);
  1697. try
  1698. FGenChange := True;
  1699. try
  1700. Position := Round(FPosBeforeDrag + Delta);
  1701. finally
  1702. FGenChange := False;
  1703. end;
  1704. except
  1705. // Propagation of exception will cause loss of mouse capture, so we need
  1706. // to emulate mouse release in order to restore internal state.
  1707. if (MouseCapture) then
  1708. begin
  1709. MouseCapture := False;
  1710. MouseUp(mbLeft, Shift, X, Y);
  1711. end;
  1712. raise;
  1713. end;
  1714. end;
  1715. end;
  1716. procedure TCustomGaugeBar.SetHandleSize(Value: Integer);
  1717. begin
  1718. if Value < 0 then Value := 0;
  1719. if Value <> FHandleSize then
  1720. begin
  1721. FHandleSize := Value;
  1722. Invalidate;
  1723. end;
  1724. end;
  1725. procedure TCustomGaugeBar.SetLargeChange(Value: Integer);
  1726. begin
  1727. if Value < 1 then Value := 1;
  1728. FLargeChange := Value;
  1729. end;
  1730. procedure TCustomGaugeBar.SetMax(Value: Integer);
  1731. begin
  1732. if (Value <= FMin) and not (csLoading in ComponentState) then
  1733. Value := FMin + 1;
  1734. if Value <> FMax then
  1735. begin
  1736. FMax := Value;
  1737. Position := FPosition;
  1738. Invalidate;
  1739. end;
  1740. end;
  1741. procedure TCustomGaugeBar.SetMin(Value: Integer);
  1742. begin
  1743. if (Value >= FMax) and not (csLoading in ComponentState) then
  1744. Value := FMax - 1;
  1745. if Value <> FMin then
  1746. begin
  1747. FMin := Value;
  1748. Position := FPosition;
  1749. Invalidate;
  1750. end;
  1751. end;
  1752. procedure TCustomGaugeBar.SetPosition(Value: Integer);
  1753. var
  1754. Handled: boolean;
  1755. begin
  1756. AdjustPosition(Value);
  1757. if (Value = FPosition) then
  1758. exit;
  1759. Handled := False;
  1760. DoChanging(Value, Handled);
  1761. if (Handled) then
  1762. exit;
  1763. FPosition := Value;
  1764. Invalidate;
  1765. DoChange;
  1766. end;
  1767. procedure TCustomGaugeBar.SetSmallChange(Value: Integer);
  1768. begin
  1769. if Value < 1 then Value := 1;
  1770. FSmallChange := Value;
  1771. end;
  1772. procedure TCustomGaugeBar.TimerHandler(Sender: TObject);
  1773. var
  1774. OldPosition: Single;
  1775. Pt: TPoint;
  1776. function MousePos: TPoint;
  1777. begin
  1778. Result := ScreenToClient(Mouse.CursorPos);
  1779. if Result.X < 0 then Result.X := 0;
  1780. if Result.Y < 0 then Result.Y := 0;
  1781. if Result.X >= ClientWidth then Result.X := ClientWidth - 1;
  1782. if Result.Y >= ClientHeight then Result.Y := ClientHeight - 1
  1783. end;
  1784. begin
  1785. inherited;
  1786. if (not MouseCapture) then
  1787. Exit;
  1788. FGenChange := True;
  1789. try
  1790. OldPosition := Position;
  1791. case FDragZone of
  1792. zBtnPrev:
  1793. begin
  1794. Position := Position - SmallChange;
  1795. if Position = OldPosition then StopDragTracking;
  1796. end;
  1797. zBtnNext:
  1798. begin
  1799. Position := Position + SmallChange;
  1800. if Position = OldPosition then StopDragTracking;
  1801. end;
  1802. zTrackNext:
  1803. begin
  1804. Pt := MousePos;
  1805. if GetZone(Pt.X, Pt.Y) in [zTrackNext, zBtnNext] then
  1806. Position := Position + LargeChange;
  1807. end;
  1808. zTrackPrev:
  1809. begin
  1810. Pt := MousePos;
  1811. if GetZone(Pt.X, Pt.Y) in [zTrackPrev, zBtnPrev] then
  1812. Position := Position - LargeChange;
  1813. end;
  1814. end;
  1815. finally
  1816. FGenChange := False;
  1817. end;
  1818. end;
  1819. { TArrowBarAccess }
  1820. function TArrowBarAccess.GetBackgnd: TRBBackgnd;
  1821. begin
  1822. Result := FMaster.Backgnd;
  1823. end;
  1824. function TArrowBarAccess.GetButtonSize: Integer;
  1825. begin
  1826. Result := FMaster.ButtonSize;
  1827. end;
  1828. function TArrowBarAccess.GetColor: TColor;
  1829. begin
  1830. Result := FMaster.Color;
  1831. end;
  1832. function TArrowBarAccess.GetHandleColor: TColor;
  1833. begin
  1834. Result := FMaster.HandleColor;
  1835. end;
  1836. function TArrowBarAccess.GetHighLightColor: TColor;
  1837. begin
  1838. Result := FMaster.HighLightColor;
  1839. end;
  1840. function TArrowBarAccess.GetShadowColor: TColor;
  1841. begin
  1842. Result := FMaster.ShadowColor;
  1843. end;
  1844. function TArrowBarAccess.GetButtonColor: TColor;
  1845. begin
  1846. Result := FMaster.ButtonColor;
  1847. end;
  1848. function TArrowBarAccess.GetBorderColor: TColor;
  1849. begin
  1850. Result := FMaster.BorderColor;
  1851. end;
  1852. function TArrowBarAccess.GetShowArrows: Boolean;
  1853. begin
  1854. Result := FMaster.ShowArrows;
  1855. end;
  1856. function TArrowBarAccess.GetShowHandleGrip: Boolean;
  1857. begin
  1858. Result := FMaster.ShowHandleGrip;
  1859. end;
  1860. function TArrowBarAccess.GetStyle: TRBStyle;
  1861. begin
  1862. Result := FMaster.Style;
  1863. end;
  1864. procedure TArrowBarAccess.SetBackgnd(Value: TRBBackgnd);
  1865. begin
  1866. FMaster.Backgnd := Value;
  1867. if FSlave <> nil then FSlave.Backgnd := Value;
  1868. end;
  1869. procedure TArrowBarAccess.SetButtonSize(Value: Integer);
  1870. begin
  1871. FMaster.ButtonSize := Value;
  1872. if FSlave <> nil then FSlave.ButtonSize := Value;
  1873. end;
  1874. procedure TArrowBarAccess.SetColor(Value: TColor);
  1875. begin
  1876. FMaster.Color := Value;
  1877. if FSlave <> nil then FSlave.Color := Value;
  1878. end;
  1879. procedure TArrowBarAccess.SetHandleColor(Value: TColor);
  1880. begin
  1881. FMaster.HandleColor := Value;
  1882. if FSlave <> nil then FSlave.HandleColor := Value;
  1883. end;
  1884. procedure TArrowBarAccess.SetHighLightColor(Value: TColor);
  1885. begin
  1886. FMaster.HighLightColor := Value;
  1887. if FSlave <> nil then FSlave.HighLightColor := Value;
  1888. end;
  1889. procedure TArrowBarAccess.SetShadowColor(Value: TColor);
  1890. begin
  1891. FMaster.ShadowColor := Value;
  1892. if FSlave <> nil then FSlave.ShadowColor := Value;
  1893. end;
  1894. procedure TArrowBarAccess.SetButtonColor(Value: TColor);
  1895. begin
  1896. FMaster.ButtonColor := Value;
  1897. if FSlave <> nil then FSlave.ButtonColor := Value;
  1898. end;
  1899. procedure TArrowBarAccess.SetBorderColor(Value: TColor);
  1900. begin
  1901. FMaster.BorderColor := Value;
  1902. if FSlave <> nil then FSlave.BorderColor := Value;
  1903. end;
  1904. procedure TArrowBarAccess.SetShowArrows(Value: Boolean);
  1905. begin
  1906. FMaster.ShowArrows := Value;
  1907. if FSlave <> nil then FSlave.ShowArrows := Value;
  1908. end;
  1909. procedure TArrowBarAccess.SetShowHandleGrip(Value: Boolean);
  1910. begin
  1911. FMaster.ShowHandleGrip := Value;
  1912. if FSlave <> nil then FSlave.ShowHandleGrip := Value;
  1913. end;
  1914. procedure TArrowBarAccess.SetStyle(Value: TRBStyle);
  1915. begin
  1916. FMaster.Style := Value;
  1917. if FSlave <> nil then FSlave.Style := Value;
  1918. end;
  1919. end.