bctrackbarupdown.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. // SPDX-License-Identifier: LGPL-3.0-linking-exception
  2. {
  3. Created by BGRA Controls Team
  4. Dibo, Circular, lainz (007) and contributors.
  5. For detailed information see readme.txt
  6. Site: https://sourceforge.net/p/bgra-controls/
  7. Wiki: http://wiki.lazarus.freepascal.org/BGRAControls
  8. Forum: http://forum.lazarus.freepascal.org/index.php/board,46.0.html
  9. }
  10. {******************************* CONTRIBUTOR(S) ******************************
  11. - Edivando S. Santos Brasil | [email protected]
  12. (Compatibility with delphi VCL 11/2018)
  13. ***************************** END CONTRIBUTOR(S) *****************************}
  14. unit BCTrackbarUpdown;
  15. {$I bgracontrols.inc}
  16. interface
  17. uses
  18. {$IFDEF FPC}LCLType, LResources,{$ENDIF}
  19. Classes, SysUtils, Types, Forms, Controls, Graphics, Dialogs,
  20. {$IFNDEF FPC}BGRAGraphics, GraphType, FPImage, {$ENDIF}
  21. ExtCtrls, BGRABitmap, BCBaseCtrls, BCTypes;
  22. type
  23. TTrackBarUpDownChangeEvent = procedure(Sender: TObject; AByUser: boolean) of object;
  24. { TCustomBCTrackbarUpdown }
  25. TCustomBCTrackbarUpdown = class(TBCCustomControl)
  26. protected
  27. FHandlingUserInput: boolean;
  28. FLongTimeInterval,FShortTimeInterval: integer;
  29. FMinValue,FMaxValue,FIncrement,FValue: integer;
  30. FAllowNegativeValues: boolean;
  31. FStartNegativeValue: boolean;
  32. FBarExponent: single;
  33. FSelStart,FSelLength: integer;
  34. FEmptyText: boolean;
  35. FBarClick,FUpClick,FDownClick: boolean;
  36. FTimer: TTimer;
  37. FOnChange: TTrackBarUpDownChangeEvent;
  38. FBCBorder: TBCBorder;
  39. FBCRounding: TBCRounding;
  40. FBCBackground: TBCBackground;
  41. FBCButtonBackground,FBCButtonDownBackground: TBCBackground;
  42. FArrowColor: TColor;
  43. FHasTrackBar: boolean;
  44. FCanvasScaling: double;
  45. FTextLeft: Integer;
  46. FBarLeft,FBarTop,FBarWidth,FBarHeight: Integer;
  47. FUpDownWidth: Integer;
  48. FUpDownLeft: Integer;
  49. FDownButtonTop: integer;
  50. function GetValue: integer;
  51. procedure SetAllowNegativeValues(AValue: boolean);
  52. procedure SetArrowColor(AValue: TColor);
  53. procedure SetHasTrackBar(AValue: boolean);
  54. procedure SetBarExponent(AValue: single);
  55. procedure SetBCBackground(AValue: TBCBackground);
  56. procedure SetBCBorder(AValue: TBCBorder);
  57. procedure SetBCButtonBackground(AValue: TBCBackground);
  58. procedure SetBCButtonDownBackground(AValue: TBCBackground);
  59. procedure SetBCRounding(AValue: TBCRounding);
  60. procedure OnChangeProperty({%H-}Sender: TObject; {%H-}AData: PtrInt);
  61. procedure Timer({%H-}Sender: TObject);
  62. procedure RenderOnBitmap(ABitmap: TBGRABitmap);
  63. procedure DrawControl; override;
  64. procedure DoSelectAll;
  65. function GetText: string; virtual;
  66. procedure SetText(AValue: string); virtual;
  67. procedure EnabledChanged; override;
  68. procedure NotifyChange; virtual;
  69. procedure SetIncrement(AValue: integer);
  70. procedure SetMaxValue(AValue: integer);
  71. procedure SetMinValue(AValue: integer);
  72. procedure SetValue(AValue: integer);
  73. function ValueToBarPos(AValue: integer): integer;
  74. function BarPosToValue(ABarPos: integer): integer;
  75. procedure MouseDown(Button: TMouseButton; {%H-}Shift: TShiftState; X, Y: Integer); override;
  76. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  77. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  78. function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override;
  79. procedure UTF8KeyPress(var UTF8Key: {$IFDEF FPC}TUTF8Char{$ELSE}String{$ENDIF}); override;
  80. procedure DoEnter; override;
  81. procedure DoExit; override;
  82. public
  83. constructor Create(AOwner: TComponent); override;
  84. procedure SelectAll;
  85. function RemoveSelection: boolean; //returns True if there was a selection to be removed
  86. procedure DelayTimer; //use after the program has been busy updating something according to the value of this component
  87. procedure SetFocus; override;
  88. destructor Destroy; override;
  89. property Border: TBCBorder read FBCBorder write SetBCBorder;
  90. property Background: TBCBackground read FBCBackground write SetBCBackground;
  91. property ButtonBackground: TBCBackground read FBCButtonBackground write SetBCButtonBackground;
  92. property ButtonDownBackground: TBCBackground read FBCButtonDownBackground write SetBCButtonDownBackground;
  93. property Rounding: TBCRounding read FBCRounding write SetBCRounding;
  94. property ArrowColor: TColor read FArrowColor write SetArrowColor;
  95. property HasTrackBar: boolean read FHasTrackBar write SetHasTrackBar;
  96. property AllowNegativeValues: boolean read FAllowNegativeValues write SetAllowNegativeValues;
  97. property BarExponent: single read FBarExponent write SetBarExponent;
  98. property Increment: integer read FIncrement write SetIncrement;
  99. property LongTimeInterval: integer read FLongTimeInterval write FLongTimeInterval;
  100. property MinValue: integer read FMinValue write SetMinValue;
  101. property MaxValue: integer read FMaxValue write SetMaxValue;
  102. property OnChange: TTrackBarUpDownChangeEvent read FOnChange write FOnChange;
  103. property Text: string read GetText write SetText;
  104. property Value: integer read GetValue write SetValue;
  105. property SelStart: integer read FSelStart;
  106. property SelLength: integer read FSelLength;
  107. property ShortTimeInterval: integer read FShortTimeInterval write FShortTimeInterval;
  108. end;
  109. TBCTrackbarUpdown = class(TCustomBCTrackbarUpdown)
  110. published
  111. property AllowNegativeValues;
  112. property BarExponent;
  113. property Increment;
  114. property LongTimeInterval;
  115. property MinValue;
  116. property MaxValue;
  117. property OnChange;
  118. property Value;
  119. property SelStart;
  120. property SelLength;
  121. property ShortTimeInterval;
  122. property Background;
  123. property ButtonBackground;
  124. property ButtonDownBackground;
  125. property Border;
  126. property Rounding;
  127. property Font;
  128. property HasTrackBar;
  129. property ArrowColor;
  130. //inherited
  131. property Align;
  132. property Anchors;
  133. property BorderSpacing;
  134. property ChildSizing;
  135. {$IFDEF FPC} //#
  136. property OnGetDockCaption;
  137. {$ENDIF}
  138. property ClientHeight;
  139. property ClientWidth;
  140. property Constraints;
  141. property DockSite;
  142. property DragCursor;
  143. property DragKind;
  144. property DragMode;
  145. property Enabled;
  146. property ParentShowHint;
  147. property PopupMenu;
  148. property ShowHint;
  149. property TabOrder;
  150. property TabStop;
  151. property UseDockManager default True;
  152. property Visible;
  153. property OnClick;
  154. property OnContextPopup;
  155. property OnDockDrop;
  156. property OnDockOver;
  157. property OnDblClick;
  158. property OnDragDrop;
  159. property OnDragOver;
  160. property OnEndDock;
  161. property OnEndDrag;
  162. property OnEnter;
  163. property OnExit;
  164. property OnGetSiteInfo;
  165. property OnMouseDown;
  166. property OnMouseEnter;
  167. property OnMouseLeave;
  168. property OnMouseMove;
  169. property OnMouseUp;
  170. property OnResize;
  171. property OnStartDock;
  172. property OnStartDrag;
  173. property OnUnDock;
  174. end;
  175. {$IFDEF FPC}procedure Register;{$ENDIF}
  176. implementation
  177. uses BGRABitmapTypes, Math, BCTools;
  178. {$IFDEF FPC}
  179. procedure Register;
  180. begin
  181. RegisterComponents('BGRA Controls', [TBCTrackbarUpdown]);
  182. end;
  183. {$ENDIF}
  184. { TCustomBCTrackbarUpdown }
  185. function TCustomBCTrackbarUpdown.GetText: string;
  186. begin
  187. if FEmptyText then
  188. begin
  189. if FStartNegativeValue then
  190. result := '-'
  191. else
  192. result := '';
  193. end else
  194. result := IntToStr(FValue);
  195. end;
  196. procedure TCustomBCTrackbarUpdown.SetText(AValue: string);
  197. var errPos,tempValue: integer;
  198. txt: string;
  199. prevActualValue: integer;
  200. begin
  201. if trim(AValue) = '' then
  202. begin
  203. if not FEmptyText or FStartNegativeValue then
  204. begin
  205. FEmptyText:= true;
  206. FStartNegativeValue:= false;
  207. Invalidate;
  208. end;
  209. exit;
  210. end;
  211. prevActualValue:= Value;
  212. val(AValue,tempValue,errPos);
  213. if errPos = 0 then
  214. begin
  215. if tempValue > FMaxValue then tempValue := FMaxValue;
  216. if (tempValue < 0) and (tempValue < FMinValue) then tempValue:= FMinValue;
  217. if (FValue = tempValue) and not FEmptyText then exit;
  218. FValue := tempValue;
  219. FEmptyText:= false;
  220. end else
  221. if (AValue = '-') and AllowNegativeValues then
  222. begin
  223. FEmptyText:= true;
  224. FStartNegativeValue:= true;
  225. end;
  226. txt := Text;
  227. if FSelStart > length(txt) then FSelStart := length(txt);
  228. if FSelStart+FSelLength > length(txt) then FSelLength:= length(txt)-FSelStart;
  229. Repaint;
  230. if Value <> prevActualValue then NotifyChange;
  231. end;
  232. procedure TCustomBCTrackbarUpdown.EnabledChanged;
  233. begin
  234. inherited EnabledChanged;
  235. Invalidate;
  236. end;
  237. procedure TCustomBCTrackbarUpdown.NotifyChange;
  238. begin
  239. if Assigned(FOnChange) then FOnChange(self, FHandlingUserInput);
  240. end;
  241. procedure TCustomBCTrackbarUpdown.SetIncrement(AValue: integer);
  242. begin
  243. if FIncrement=AValue then Exit;
  244. FIncrement:=AValue;
  245. end;
  246. procedure TCustomBCTrackbarUpdown.SetMaxValue(AValue: integer);
  247. begin
  248. if not AllowNegativeValues and (AValue < 0) then AValue := 0;
  249. if FMaxValue=AValue then Exit;
  250. FMaxValue:=AValue;
  251. if FMaxValue < FMinValue then FMinValue := FMaxValue;
  252. if AValue > FMaxValue then FMaxValue:= AValue;
  253. Invalidate;
  254. end;
  255. procedure TCustomBCTrackbarUpdown.SetMinValue(AValue: integer);
  256. begin
  257. if not AllowNegativeValues and (AValue < 0) then AValue := 0;
  258. if FMinValue=AValue then Exit;
  259. FMinValue:=AValue;
  260. if FMinValue > FMaxValue then FMaxValue := FMinValue;
  261. if AValue < FMinValue then FMinValue:= AValue;
  262. Invalidate;
  263. end;
  264. procedure TCustomBCTrackbarUpdown.SetValue(AValue: integer);
  265. begin
  266. if AValue < FMinValue then AValue := FMinValue;
  267. if AValue > FMaxValue then AValue := FMaxValue;
  268. if FValue=AValue then Exit;
  269. FValue:=AValue;
  270. FEmptyText:= false;
  271. DoSelectAll;
  272. Invalidate;
  273. if not (csLoading in ComponentState) then NotifyChange;
  274. end;
  275. procedure TCustomBCTrackbarUpdown.SetArrowColor(AValue: TColor);
  276. begin
  277. if FArrowColor=AValue then Exit;
  278. FArrowColor:=AValue;
  279. Invalidate;
  280. end;
  281. procedure TCustomBCTrackbarUpdown.SetHasTrackBar(AValue: boolean);
  282. begin
  283. if FHasTrackBar=AValue then Exit;
  284. FHasTrackBar:=AValue;
  285. Invalidate;
  286. end;
  287. procedure TCustomBCTrackbarUpdown.SetAllowNegativeValues(AValue: boolean);
  288. var
  289. changeVal: Boolean;
  290. begin
  291. if FAllowNegativeValues=AValue then Exit;
  292. FAllowNegativeValues:=AValue;
  293. if not FAllowNegativeValues then
  294. begin
  295. if (FMinValue < 0) or (FValue < 0) or (FMaxValue < 0) then
  296. begin
  297. if FMinValue < 0 then FMinValue := 0;
  298. if FValue < 0 then
  299. begin
  300. FValue := 0;
  301. changeVal := true;
  302. end else changeVal := false;
  303. if FMaxValue < 0 then FMaxValue:= 0;
  304. Invalidate;
  305. if changeVal then NotifyChange;
  306. end;
  307. end;
  308. end;
  309. function TCustomBCTrackbarUpdown.GetValue: integer;
  310. begin
  311. if FValue < FMinValue then result := FMinValue else
  312. result := FValue;
  313. end;
  314. procedure TCustomBCTrackbarUpdown.SetBarExponent(AValue: single);
  315. begin
  316. if AValue <= 0 then exit;
  317. if FBarExponent=AValue then Exit;
  318. FBarExponent:=AValue;
  319. Invalidate;
  320. end;
  321. procedure TCustomBCTrackbarUpdown.SetBCBackground(AValue: TBCBackground);
  322. begin
  323. if FBCBackground=AValue then Exit;
  324. FBCBackground.Assign(AValue);
  325. end;
  326. procedure TCustomBCTrackbarUpdown.SetBCBorder(AValue: TBCBorder);
  327. begin
  328. if FBCBorder=AValue then Exit;
  329. FBCBorder.Assign(AValue);
  330. end;
  331. procedure TCustomBCTrackbarUpdown.SetBCButtonBackground(AValue: TBCBackground);
  332. begin
  333. if FBCButtonBackground=AValue then Exit;
  334. FBCButtonBackground.Assign(AValue);
  335. end;
  336. procedure TCustomBCTrackbarUpdown.SetBCButtonDownBackground(
  337. AValue: TBCBackground);
  338. begin
  339. if FBCButtonDownBackground=AValue then Exit;
  340. FBCButtonDownBackground.Assign(AValue);
  341. end;
  342. procedure TCustomBCTrackbarUpdown.SetBCRounding(AValue: TBCRounding);
  343. begin
  344. if FBCRounding=AValue then Exit;
  345. FBCRounding.Assign(AValue);
  346. end;
  347. procedure TCustomBCTrackbarUpdown.OnChangeProperty(Sender: TObject;
  348. AData: PtrInt);
  349. begin
  350. RenderControl;
  351. Invalidate;
  352. end;
  353. procedure TCustomBCTrackbarUpdown.Timer(Sender: TObject);
  354. begin
  355. FHandlingUserInput:= true;
  356. if FUpClick then
  357. begin
  358. Value := Value + Increment;
  359. end else
  360. if FDownClick then
  361. Value := Value - Increment;
  362. FHandlingUserInput:= false;
  363. FTimer.Interval := ShortTimeInterval;
  364. end;
  365. procedure TCustomBCTrackbarUpdown.RenderOnBitmap(ABitmap: TBGRABitmap);
  366. var bordercolor,fgcolor,btntext: TBGRAPixel;
  367. x,y,ty,barx: integer;
  368. s: TSize;
  369. midy: integer;
  370. midx: single;
  371. beforeSel,inSel,afterSel: string;
  372. bounds,fullBounds: TRect;
  373. begin
  374. fullbounds := rect(0,0,ABitmap.Width,ABitmap.Height);
  375. bounds := fullBounds;
  376. CalculateInnerRect(Border, bounds);
  377. ty := bounds.bottom-bounds.top-2;
  378. FTextLeft := bounds.left+1+((ty+5) div 10);
  379. FUpDownWidth := (ty*3+3) div 5;
  380. FUpDownLeft := bounds.right-FUpDownWidth;
  381. FBarLeft := bounds.left+1;
  382. if FHasTrackBar then
  383. begin
  384. FBarHeight := (bounds.bottom-bounds.top+3) div 5+1;
  385. FBarWidth := bounds.right-FUpDownWidth-FBarHeight+1-FBarLeft;
  386. if (Rounding.RoundX > 1) and (Rounding.RoundY > 1) then
  387. FBarLeft := FBarLeft +FBarHeight+1;
  388. end else
  389. begin
  390. FBarWidth := 0;
  391. FBarHeight := 2;
  392. end;
  393. FBarTop := bounds.bottom-FBarHeight;
  394. midy := ABitmap.Height div 2;
  395. FDownButtonTop := midy;
  396. ABitmap.ClipRect := rect(fullbounds.left,fullbounds.top,FUpDownLeft+1,fullbounds.bottom);
  397. RenderBackgroundAndBorder(fullbounds, Background, ABitmap, Rounding, Border);
  398. bordercolor := ColorToBGRA(ColorToRGB(Border.Color),Border.ColorOpacity);
  399. ABitmap.VertLine(FUpDownLeft,bounds.top,bounds.bottom-1,bordercolor,dmDrawWithTransparency);
  400. if FUpClick then
  401. begin
  402. ABitmap.ClipRect := rect(FUpDownLeft+1,fullbounds.top,fullbounds.Right,midy);
  403. RenderBackgroundAndBorder(fullbounds, ButtonDownBackground, ABitmap, Rounding, Border);
  404. ABitmap.ClipRect := rect(FUpDownLeft+1,midy,fullbounds.Right,fullbounds.bottom);
  405. RenderBackgroundAndBorder(fullbounds, ButtonBackground, ABitmap, Rounding, Border);
  406. end else
  407. if FDownClick then
  408. begin
  409. ABitmap.ClipRect := rect(FUpDownLeft+1,fullbounds.top,fullbounds.Right,midy+1);
  410. RenderBackgroundAndBorder(fullbounds, ButtonBackground, ABitmap, Rounding, Border);
  411. ABitmap.ClipRect := rect(FUpDownLeft+1,midy+1,fullbounds.Right,fullbounds.bottom);
  412. RenderBackgroundAndBorder(fullbounds, ButtonDownBackground, ABitmap, Rounding, Border);
  413. end else
  414. begin
  415. ABitmap.ClipRect := rect(FUpDownLeft+1,fullbounds.top,fullbounds.Right,fullbounds.bottom);
  416. RenderBackgroundAndBorder(fullbounds, ButtonBackground, ABitmap, Rounding, Border);
  417. end;
  418. ABitmap.NoClip;
  419. ABitmap.HorizLine(FUpDownLeft+1,midy,bounds.right-1,bordercolor,dmDrawWithTransparency);
  420. ABitmap.FontQuality := fqFineAntialiasing;
  421. ABitmap.FontName := Font.Name;
  422. ABitmap.FontStyle := Font.Style;
  423. ABitmap.FontHeight := ((ty-FBarHeight+1)*8+4) div 9;
  424. fgcolor := Font.Color;
  425. x := FTextLeft;
  426. y := bounds.top+1;
  427. if Focused then
  428. begin
  429. if SelStart = 0 then
  430. begin
  431. beforeSel := '';
  432. inSel := Text;
  433. end else
  434. begin
  435. beforeSel := copy(Text,1,SelStart);
  436. inSel := copy(Text,SelStart+1,length(Text)-SelStart);
  437. end;
  438. if length(inSel)>SelLength then
  439. begin
  440. afterSel:= copy(inSel,SelLength+1,length(inSel)-SelLength);
  441. inSel := copy(inSel,1,SelLength);
  442. end else
  443. afterSel := '';
  444. ABitmap.TextOut(x,y,beforeSel,fgcolor);
  445. inc(x, ABitmap.TextSize(beforeSel).cx);
  446. if inSel = '' then ABitmap.SetVertLine(x,y,y+ABitmap.FontFullHeight-1,fgcolor)
  447. else
  448. begin
  449. s := ABitmap.TextSize(inSel);
  450. ABitmap.FillRect(x,y+1,x+s.cx,y+s.cy,ColorToRGB(clHighlight),dmSet);
  451. ABitmap.TextOut(x,y,inSel,ColorToRGB(clHighlightText));
  452. inc(x,s.cx);
  453. end;
  454. ABitmap.TextOut(x,y,afterSel,fgcolor);
  455. end else
  456. begin
  457. if Enabled then
  458. ABitmap.TextOut(x,y,Text,fgcolor)
  459. else
  460. ABitmap.TextOut(x,y,Text,BGRA(fgcolor.red,fgcolor.green,fgcolor.blue,fgcolor.alpha div 2));
  461. end;
  462. barx := ValueToBarPos(Value);
  463. if FHasTrackBar then
  464. ABitmap.FillPolyAntialias([PointF(barx,FBarTop),PointF(barx+FBarHeight,FBarTop+FBarHeight),
  465. PointF(barx-FBarHeight,FBarTop+FBarHeight)],fgcolor);
  466. midx := FUpDownLeft+(FUpDownWidth-1)/2;
  467. btntext := FArrowColor;
  468. ABitmap.FillPolyAntialias([PointF(FUpDownLeft+2,midy*4/5),PointF(midx,midy/5),PointF(FUpDownLeft+FUpDownWidth-3,midy*4/5)],btntext);
  469. ABitmap.FillPolyAntialias([PointF(FUpDownLeft+2,midy*6/5),PointF(midx,ABitmap.Height-midy/5),PointF(FUpDownLeft+FUpDownWidth-3,midy*6/5)],btntext);
  470. end;
  471. function TCustomBCTrackbarUpdown.ValueToBarPos(AValue: integer): integer;
  472. var t: single;
  473. begin
  474. if FMaxValue>FMinValue then
  475. begin
  476. t := (AValue-FMinValue)/(FMaxValue-FMinValue);
  477. if t < 0 then t := 0;
  478. if t > 1 then t := 1;
  479. result := FBarLeft+round(power(t,1/FBarExponent)*(FBarWidth-1))
  480. end
  481. else
  482. result := FBarLeft;
  483. end;
  484. function TCustomBCTrackbarUpdown.BarPosToValue(ABarPos: integer): integer;
  485. var t: single;
  486. begin
  487. if FBarWidth > FBarLeft then
  488. begin
  489. t := (ABarPos-FBarLeft)/(FBarWidth-1);
  490. if t < 0 then t := 0;
  491. if t > 1 then t := 1;
  492. result := round(power(t,FBarExponent)*(FMaxValue-FMinValue))+FMinValue
  493. end
  494. else
  495. result := FMinValue;
  496. end;
  497. procedure TCustomBCTrackbarUpdown.MouseDown(Button: TMouseButton;
  498. Shift: TShiftState; X, Y: Integer);
  499. begin
  500. X := round(X*FCanvasScaling);
  501. Y := round(Y*FCanvasScaling);
  502. if Button = mbLeft then
  503. begin
  504. FHandlingUserInput:= true;
  505. if X >= FUpDownLeft then
  506. begin
  507. if Y > FDownButtonTop then
  508. begin
  509. FDownClick:= true;
  510. Value := Value-Increment;
  511. Invalidate;
  512. FTimer.Interval := LongTimeInterval;
  513. FTimer.Enabled:= true;
  514. end else
  515. if Y < FDownButtonTop then
  516. begin
  517. FUpClick:= true;
  518. Value := Value+Increment;
  519. Invalidate;
  520. FTimer.Interval := LongTimeInterval;
  521. FTimer.Enabled:= true;
  522. end;
  523. end else
  524. if (Y >= Height-FBarHeight-1) and (FBarWidth>1) then
  525. begin
  526. FBarClick:= true;
  527. Value := BarPosToValue(X);
  528. Repaint;
  529. end;
  530. FHandlingUserInput:= false;
  531. end;
  532. if not Focused then
  533. begin
  534. SetFocus;
  535. SelectAll;
  536. end;
  537. inherited MouseDown(Button, Shift, X, Y);
  538. end;
  539. procedure TCustomBCTrackbarUpdown.MouseMove(Shift: TShiftState; X, Y: Integer);
  540. begin
  541. inherited MouseMove(Shift, X, Y);
  542. X := round(X*FCanvasScaling);
  543. Y := round(Y*FCanvasScaling);
  544. if FBarClick and (FBarWidth>1) then
  545. begin
  546. FHandlingUserInput:= true;
  547. Value := BarPosToValue(X);
  548. FHandlingUserInput:= false;
  549. end;
  550. end;
  551. procedure TCustomBCTrackbarUpdown.MouseUp(Button: TMouseButton;
  552. Shift: TShiftState; X, Y: Integer);
  553. begin
  554. inherited MouseUp(Button, Shift, X, Y);
  555. X := round(X*FCanvasScaling);
  556. Y := round(Y*FCanvasScaling);
  557. if Button = mbLeft then
  558. begin
  559. if FBarClick then FBarClick:= false else
  560. if FUpClick then
  561. begin
  562. FUpClick:= false;
  563. Invalidate;
  564. FTimer.Enabled:= false;
  565. end else
  566. if FDownClick then
  567. begin
  568. FDownClick:= false;
  569. Invalidate;
  570. FTimer.Enabled:= false;
  571. end;
  572. end;
  573. end;
  574. function TCustomBCTrackbarUpdown.DoMouseWheel(Shift: TShiftState;
  575. WheelDelta: Integer; MousePos: TPoint): Boolean;
  576. begin
  577. if Assigned(OnMouseWheel) or Assigned(OnMouseWheelDown) or Assigned(OnMouseWheelUp) then
  578. begin
  579. result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);
  580. exit;
  581. end;
  582. FHandlingUserInput:= true;
  583. Value := Value + Increment*WheelDelta div 120;
  584. FHandlingUserInput := false;
  585. Invalidate;
  586. result := true;
  587. end;
  588. procedure TCustomBCTrackbarUpdown.UTF8KeyPress(var UTF8Key: {$IFDEF FPC}TUTF8Char{$ELSE}String{$ENDIF});
  589. var tempText: string;
  590. begin
  591. FHandlingUserInput:= true;
  592. if UTF8Key = #8 then
  593. begin
  594. if not RemoveSelection and (SelStart > 0) then
  595. begin
  596. tempText := Text;
  597. Dec(FSelStart);
  598. Delete(tempText,SelStart+1,1);
  599. Text := tempText;
  600. Invalidate;
  601. end;
  602. UTF8Key:= #0;
  603. end else
  604. if (length(UTF8Key)=1) and ((UTF8Key[1] in['0'..'9']) or ((UTF8Key[1]='-') and (SelStart = 0))) then
  605. begin
  606. RemoveSelection;
  607. tempText := Text;
  608. Insert(UTF8Key,tempText,SelStart+1);
  609. Text := tempText;
  610. if FSelStart < length(Text) then inc(FSelStart);
  611. Invalidate;
  612. UTF8Key:= #0;
  613. end;
  614. FHandlingUserInput:= false;
  615. end;
  616. procedure TCustomBCTrackbarUpdown.DoEnter;
  617. begin
  618. inherited DoEnter;
  619. Invalidate;
  620. end;
  621. procedure TCustomBCTrackbarUpdown.DoExit;
  622. begin
  623. inherited DoExit;
  624. if FValue > FMaxValue then FValue := FMaxValue;
  625. if FValue < FMinValue then FValue := FMinValue;
  626. if FEmptyText then
  627. begin
  628. FEmptyText:= false;
  629. SelectAll;
  630. end;
  631. Invalidate;
  632. end;
  633. procedure TCustomBCTrackbarUpdown.DrawControl;
  634. var bmp: TBGRABitmap;
  635. begin
  636. FCanvasScaling:= GetCanvasScaleFactor;
  637. bmp := TBGRABitmap.Create(round(Width*FCanvasScaling),round(Height*FCanvasScaling));
  638. RenderOnBitmap(bmp);
  639. bmp.Draw(Canvas,rect(0,0,Width,Height),False);
  640. bmp.Free;
  641. end;
  642. constructor TCustomBCTrackbarUpdown.Create(AOwner: TComponent);
  643. begin
  644. inherited Create(AOwner);
  645. with GetControlClassDefaultSize do
  646. SetInitialBounds(0, 0, CX, CY);
  647. FMinValue:= 0;
  648. FMaxValue := 100;
  649. FValue := 50;
  650. FIncrement := 1;
  651. FBarExponent:= 1;
  652. FCanvasScaling:= 1;
  653. FTimer := TTimer.Create(self);
  654. FTimer.Enabled := false;
  655. FTimer.OnTimer:=Timer;
  656. FLongTimeInterval:= 400;
  657. FShortTimeInterval:= 100;
  658. FHasTrackBar:= true;
  659. FBCBorder := TBCBorder.Create(self);
  660. FBCBorder.Color := clWindowText;
  661. FBCBorder.Width := 1;
  662. FBCBorder.Style := bboSolid;
  663. FBCBorder.OnChange := OnChangeProperty;
  664. FBCRounding := TBCRounding.Create(self);
  665. FBCRounding.RoundX := 1;
  666. FBCRounding.RoundY := 1;
  667. FBCRounding.OnChange := OnChangeProperty;
  668. FBCBackground := TBCBackground.Create(self);
  669. FBCBackground.Style := bbsColor;
  670. FBCBackground.Color := clWindow;
  671. FBCBackground.OnChange := OnChangeProperty;
  672. FBCButtonBackground := TBCBackground.Create(self);
  673. FBCButtonBackground.Style := bbsGradient;
  674. FBCButtonBackground.Gradient1EndPercent := 50;
  675. FBCButtonBackground.Gradient1.Point1YPercent := -50;
  676. FBCButtonBackground.Gradient1.Point2YPercent := 50;
  677. FBCButtonBackground.Gradient1.StartColor := clBtnShadow;
  678. FBCButtonBackground.Gradient1.EndColor := clBtnFace;
  679. FBCButtonBackground.Gradient2.Point1YPercent := 50;
  680. FBCButtonBackground.Gradient2.Point2YPercent := 150;
  681. FBCButtonBackground.Gradient2.StartColor := clBtnFace;
  682. FBCButtonBackground.Gradient2.EndColor := clBtnShadow;
  683. FBCButtonBackground.OnChange := OnChangeProperty;
  684. FBCButtonDownBackground := TBCBackground.Create(self);
  685. FBCButtonDownBackground.Style := bbsColor;
  686. FBCButtonDownBackground.Color := clBtnShadow;
  687. FBCButtonDownBackground.OnChange := OnChangeProperty;
  688. FArrowColor:= clBtnText;
  689. Font.Color := clWindowText;
  690. Font.Name := 'Arial';
  691. DoSelectAll;
  692. TabStop := true;
  693. end;
  694. procedure TCustomBCTrackbarUpdown.DoSelectAll;
  695. begin
  696. FSelStart := 0;
  697. FSelLength := length(Text);
  698. end;
  699. procedure TCustomBCTrackbarUpdown.SelectAll;
  700. begin
  701. DoSelectAll;
  702. Invalidate;
  703. end;
  704. function TCustomBCTrackbarUpdown.RemoveSelection: boolean;
  705. var
  706. tempText: string;
  707. len:integer;
  708. begin
  709. if SelLength > 0 then
  710. begin
  711. tempText := Text;
  712. len := FSelLength;
  713. FSelLength := 0;
  714. Delete(tempText,SelStart+1,len);
  715. Text := tempText;
  716. Invalidate;
  717. result := true
  718. end else
  719. result := false;
  720. end;
  721. procedure TCustomBCTrackbarUpdown.DelayTimer;
  722. begin
  723. if FTimer.Enabled then
  724. begin
  725. FTimer.Enabled:= false;
  726. FTimer.Enabled:= true;
  727. end;
  728. end;
  729. procedure TCustomBCTrackbarUpdown.SetFocus;
  730. begin
  731. try
  732. inherited SetFocus;
  733. except
  734. //in some cases, it is impossible to set the focus
  735. //but that's not a reason to crash the program
  736. end;
  737. end;
  738. destructor TCustomBCTrackbarUpdown.Destroy;
  739. begin
  740. FreeAndNil(FTimer);
  741. FreeAndNil(FBCBackground);
  742. FreeAndNil(FBCButtonBackground);
  743. FreeAndNil(FBCButtonDownBackground);
  744. FreeAndNil(FBCBorder);
  745. FreeAndNil(FBCRounding);
  746. inherited Destroy;
  747. end;
  748. end.