UpDownEdit.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. unit UpDownEdit;
  2. interface
  3. uses
  4. Windows, ComCtrls, Controls, ExtCtrls, Classes, Graphics, Messages, Forms,
  5. StdCtrls, Menus, SysUtils;
  6. { TUpDownEdit }
  7. type
  8. TValueType = (vtInt, vtFloat, vtHex);
  9. TUpDownEditGetValue = procedure(Sender: TObject; Text: string;
  10. var Value: Extended; var Handled: Boolean) of object;
  11. TUpDownEditSetValue = procedure(Sender: TObject; Value: Extended;
  12. var Text: string; var Handled: Boolean) of object;
  13. TUpDownEdit = class(TCustomEdit)
  14. private
  15. FAlignment: TAlignment;
  16. FMinValue: Extended;
  17. FMaxValue: Extended;
  18. FIncrement: Extended;
  19. FDecimal: Byte;
  20. FChanging: Boolean;
  21. FEditorEnabled: Boolean;
  22. FValueType: TValueType;
  23. FArrowKeys: Boolean;
  24. FButtonsVisible: Boolean;
  25. FDarkMode: Boolean;
  26. FOnTopClick: TNotifyEvent;
  27. FOnBottomClick: TNotifyEvent;
  28. FUpDown: TCustomUpDown;
  29. FOnGetValue: TUpDownEditGetValue;
  30. FOnSetValue: TUpDownEditSetValue;
  31. procedure UpDownClick(Sender: TObject; Button: TUDBtnType);
  32. function GetMinHeight: Integer;
  33. procedure GetTextHeight(var SysHeight, Height: Integer);
  34. function GetValue: Extended;
  35. function CheckValue(NewValue: Extended): Extended;
  36. function GetAsInteger: Longint;
  37. function IsIncrementStored: Boolean;
  38. function IsMaxStored: Boolean;
  39. function IsMinStored: Boolean;
  40. function IsValueStored: Boolean;
  41. procedure SetArrowKeys(Value: Boolean);
  42. procedure SetAsInteger(NewValue: Longint);
  43. procedure SetValue(NewValue: Extended);
  44. procedure SetValueType(NewType: TValueType);
  45. procedure SetDecimal(NewValue: Byte);
  46. function GetButtonWidth: Integer;
  47. procedure RecreateButton;
  48. procedure ResizeButton;
  49. procedure SetEditRect;
  50. procedure SetAlignment(Value: TAlignment);
  51. procedure SetButtonsVisible(Value: Boolean);
  52. procedure SetDarkMode(Value: Boolean);
  53. procedure WMSize(var Message: TWMSize); message WM_SIZE;
  54. procedure CMEnter(var Message: TMessage); message CM_ENTER;
  55. procedure CMExit(var Message: TCMExit); message CM_EXIT;
  56. procedure WMPaste(var Message: TWMPaste); message WM_PASTE;
  57. procedure WMCut(var Message: TWMCut); message WM_CUT;
  58. procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  59. procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  60. procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  61. procedure CMBiDiModeChanged(var Message: TMessage); message CM_BIDIMODECHANGED;
  62. protected
  63. procedure Change; override;
  64. function IsValidChar(Key: Char): Boolean; virtual;
  65. procedure UpClick(Sender: TObject); virtual;
  66. procedure DownClick(Sender: TObject); virtual;
  67. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  68. procedure KeyPress(var Key: Char); override;
  69. procedure CreateParams(var Params: TCreateParams); override;
  70. procedure CreateWnd; override;
  71. function DefBtnWidth: Integer;
  72. public
  73. constructor Create(AOwner: TComponent); override;
  74. destructor Destroy; override;
  75. property AsInteger: Longint read GetAsInteger write SetAsInteger default 0;
  76. property Text;
  77. published
  78. property Alignment: TAlignment read FAlignment write SetAlignment
  79. default taLeftJustify;
  80. property ArrowKeys: Boolean read FArrowKeys write SetArrowKeys default True;
  81. property Decimal: Byte read FDecimal write SetDecimal default 2;
  82. property EditorEnabled: Boolean read FEditorEnabled write FEditorEnabled default True;
  83. property Increment: Extended read FIncrement write FIncrement stored IsIncrementStored;
  84. property MaxValue: Extended read FMaxValue write FMaxValue stored IsMaxStored;
  85. property MinValue: Extended read FMinValue write FMinValue stored IsMinStored;
  86. property ValueType: TValueType read FValueType write SetValueType default vtInt;
  87. property Value: Extended read GetValue write SetValue stored IsValueStored;
  88. property ButtonsVisible: Boolean read FButtonsVisible write SetButtonsVisible default True;
  89. property DarkMode: Boolean read FDarkMode write SetDarkMode default False;
  90. property AutoSelect;
  91. property AutoSize;
  92. property BorderStyle;
  93. property Color;
  94. property Ctl3D;
  95. property DragCursor;
  96. property DragMode;
  97. property Enabled;
  98. property Font;
  99. property Anchors;
  100. property BiDiMode;
  101. property Constraints;
  102. property DragKind;
  103. property ParentBiDiMode;
  104. property ImeMode;
  105. property ImeName;
  106. property MaxLength;
  107. property ParentColor;
  108. property ParentCtl3D;
  109. property ParentFont;
  110. property ParentShowHint;
  111. property PopupMenu;
  112. property ReadOnly;
  113. property ShowHint;
  114. property TabOrder;
  115. property TabStop;
  116. property Visible;
  117. property OnBottomClick: TNotifyEvent read FOnBottomClick write FOnBottomClick;
  118. property OnTopClick: TNotifyEvent read FOnTopClick write FOnTopClick;
  119. property OnGetValue: TUpDownEditGetValue read FOnGetValue write FOnGetValue;
  120. property OnSetValue: TUpDownEditSetValue read FOnSetValue write FOnSetValue;
  121. property OnChange;
  122. property OnClick;
  123. property OnDblClick;
  124. property OnDragDrop;
  125. property OnDragOver;
  126. property OnEndDrag;
  127. property OnEnter;
  128. property OnExit;
  129. property OnKeyDown;
  130. property OnKeyPress;
  131. property OnKeyUp;
  132. property OnMouseDown;
  133. property OnMouseMove;
  134. property OnMouseUp;
  135. property OnStartDrag;
  136. property OnContextPopup;
  137. property OnMouseWheelDown;
  138. property OnMouseWheelUp;
  139. property OnEndDock;
  140. property OnStartDock;
  141. end;
  142. procedure Register;
  143. implementation
  144. uses
  145. CommCtrl, PasTools, Math;
  146. procedure Register;
  147. begin
  148. RegisterComponents('Martin', [TUpDownEdit]);
  149. end;
  150. type
  151. TEmbededUpDown = class(TCustomUpDown)
  152. private
  153. FChanging: Boolean;
  154. procedure ScrollMessage(var Message: TWMVScroll);
  155. procedure WMHScroll(var Message: TWMHScroll); message CN_HSCROLL;
  156. procedure WMVScroll(var Message: TWMVScroll); message CN_VSCROLL;
  157. procedure WMSize(var Message: TWMSize); message WM_SIZE;
  158. protected
  159. procedure CreateWnd; override;
  160. public
  161. constructor Create(AOwner: TComponent); override;
  162. destructor Destroy; override;
  163. published
  164. property OnClick;
  165. end;
  166. constructor TEmbededUpDown.Create(AOwner: TComponent);
  167. begin
  168. inherited Create(AOwner);
  169. Orientation := udVertical;
  170. Min := -1;
  171. Max := 1;
  172. Position := 0;
  173. end;
  174. destructor TEmbededUpDown.Destroy;
  175. begin
  176. OnClick := nil;
  177. inherited Destroy;
  178. end;
  179. procedure TEmbededUpDown.CreateWnd;
  180. var
  181. UpDownEdit: TUpDownEdit;
  182. begin
  183. inherited;
  184. UpDownEdit := Owner as TUpDownEdit;
  185. if Assigned(UpDownEdit) then
  186. begin
  187. // Theme style for "Spin" found using msstylEditor in aero.msstyles
  188. if UpDownEdit.DarkMode then
  189. SetDarkModeTheme(Self, 'Explorer');
  190. // edit rect is reset while changing the theme, calling always for consistency
  191. UpDownEdit.SetEditRect;
  192. end;
  193. end;
  194. procedure TEmbededUpDown.ScrollMessage(var Message: TWMVScroll);
  195. begin
  196. if Message.ScrollCode = SB_THUMBPOSITION then begin
  197. if not FChanging then begin
  198. FChanging := True;
  199. try
  200. if Message.Pos > 0 then Click(btNext)
  201. else if Message.Pos < 0 then Click(btPrev);
  202. if HandleAllocated then
  203. SendMessage(Handle, UDM_SETPOS, 0, 0);
  204. finally
  205. FChanging := False;
  206. end;
  207. end;
  208. end;
  209. end;
  210. procedure TEmbededUpDown.WMHScroll(var Message: TWMHScroll);
  211. begin
  212. ScrollMessage(TWMVScroll(Message));
  213. end;
  214. procedure TEmbededUpDown.WMVScroll(var Message: TWMVScroll);
  215. begin
  216. ScrollMessage(Message);
  217. end;
  218. procedure TEmbededUpDown.WMSize(var Message: TWMSize);
  219. var
  220. Def: Integer;
  221. begin
  222. inherited;
  223. Def := TUpDownEdit(Parent).DefBtnWidth;
  224. if Width <> Def then Width := Def;
  225. end;
  226. { TUpDownEdit }
  227. constructor TUpDownEdit.Create(AOwner: TComponent);
  228. begin
  229. inherited Create(AOwner);
  230. Text := '0';
  231. ControlStyle := ControlStyle - [csSetCaption];
  232. FIncrement := 1.0;
  233. FDecimal := 2;
  234. FEditorEnabled := True;
  235. FArrowKeys := True;
  236. FButtonsVisible := True;
  237. FDarkMode := False;
  238. RecreateButton;
  239. end;
  240. destructor TUpDownEdit.Destroy;
  241. begin
  242. Destroying;
  243. FChanging := True;
  244. if FUpDown <> nil then
  245. begin
  246. FUpDown.Free;
  247. FUpDown := nil;
  248. end;
  249. inherited Destroy;
  250. end;
  251. procedure TUpDownEdit.RecreateButton;
  252. begin
  253. if (csDestroying in ComponentState) then Exit;
  254. FUpDown.Free;
  255. FUpDown := nil;
  256. FUpDown := TEmbededUpDown.Create(Self);
  257. with TEmbededUpDown(FUpDown) do begin
  258. Visible := True;
  259. SetBounds(0, 0, DefBtnWidth, Self.Height);
  260. if (BiDiMode = bdRightToLeft) then Align := alLeft
  261. else Align := alRight;
  262. Parent := Self;
  263. OnClick := UpDownClick;
  264. end;
  265. end;
  266. procedure TUpDownEdit.SetArrowKeys(Value: Boolean);
  267. begin
  268. FArrowKeys := Value;
  269. ResizeButton;
  270. end;
  271. procedure TUpDownEdit.UpDownClick(Sender: TObject; Button: TUDBtnType);
  272. begin
  273. if TabStop and CanFocus then SetFocus;
  274. case Button of
  275. btNext: UpClick(Sender);
  276. btPrev: DownClick(Sender);
  277. end;
  278. end;
  279. function TUpDownEdit.GetButtonWidth: Integer;
  280. begin
  281. if FUpDown.Visible then Result := FUpDown.Width
  282. else Result := 0;
  283. end;
  284. function TUpDownEdit.DefBtnWidth: Integer;
  285. begin
  286. Result := 15;
  287. if Parent <> nil then
  288. begin
  289. Result := ScaleByPixelsPerInch(Result, Self);
  290. Result := Math.Min(GetSystemMetricsForControl(Self, SM_CXVSCROLL), Result);
  291. end;
  292. end;
  293. procedure TUpDownEdit.ResizeButton;
  294. begin
  295. if FUpDown <> nil then
  296. begin
  297. FUpDown.Width := DefBtnWidth;
  298. if (BiDiMode = bdRightToLeft) then FUpDown.Align := alLeft
  299. else FUpDown.Align := alRight;
  300. FUpDown.Visible := ButtonsVisible;
  301. end
  302. end;
  303. procedure TUpDownEdit.KeyDown(var Key: Word; Shift: TShiftState);
  304. begin
  305. inherited KeyDown(Key, Shift);
  306. if ArrowKeys and (Key in [VK_UP, VK_DOWN]) then
  307. begin
  308. if Key = VK_UP then UpClick(Self)
  309. else
  310. if Key = VK_DOWN then DownClick(Self);
  311. Key := 0;
  312. end;
  313. end;
  314. procedure TUpDownEdit.Change;
  315. begin
  316. if not FChanging then inherited Change;
  317. end;
  318. procedure TUpDownEdit.KeyPress(var Key: Char);
  319. begin
  320. if not IsValidChar(Key) then
  321. begin
  322. Key := #0;
  323. MessageBeep(MB_ICONHAND)
  324. end;
  325. if Key <> #0 then
  326. begin
  327. inherited KeyPress(Key);
  328. if (Key = Char(VK_RETURN)) or (Key = Char(VK_ESCAPE)) then
  329. begin
  330. { must catch and remove this, since is actually multi-line }
  331. GetParentForm(Self).Perform(CM_DIALOGKEY, Byte(Key), 0);
  332. if Key = Char(VK_RETURN) then Key := #0;
  333. end;
  334. end;
  335. end;
  336. function TUpDownEdit.IsValidChar(Key: Char): Boolean;
  337. var
  338. ValidChars: TSysCharSet;
  339. begin
  340. ValidChars := ['+', '-', '0'..'9'];
  341. if ValueType = vtFloat then
  342. begin
  343. if Pos(FormatSettings.DecimalSeparator, Text) = 0 then
  344. ValidChars := ValidChars + [FormatSettings.DecimalSeparator];
  345. if Pos('E', AnsiUpperCase(Text)) = 0 then
  346. ValidChars := ValidChars + ['e', 'E'];
  347. end
  348. else
  349. if ValueType = vtHex then
  350. begin
  351. ValidChars := ValidChars + ['A'..'F', 'a'..'f'];
  352. end;
  353. Result := CharInSet(Key, ValidChars) or (Key < #32);
  354. if not FEditorEnabled and Result and ((Key >= #32) or
  355. (Key = Char(VK_BACK)) or (Key = Char(VK_DELETE))) then Result := False;
  356. end;
  357. procedure TUpDownEdit.CreateParams(var Params: TCreateParams);
  358. const
  359. Alignments: array[Boolean, TAlignment] of DWORD =
  360. ((ES_LEFT, ES_RIGHT, ES_CENTER), (ES_RIGHT, ES_LEFT, ES_CENTER));
  361. begin
  362. inherited CreateParams(Params);
  363. Params.Style := Params.Style or ES_MULTILINE or WS_CLIPCHILDREN or
  364. Alignments[UseRightToLeftAlignment, FAlignment];
  365. end;
  366. procedure TUpDownEdit.CreateWnd;
  367. begin
  368. inherited CreateWnd;
  369. ResizeButton; // now we know the scaling factor
  370. SetEditRect;
  371. SetValue(Value);
  372. if DarkMode then
  373. SetDarkModeTheme(Self, 'CFD');
  374. end;
  375. procedure TUpDownEdit.SetEditRect;
  376. var
  377. Loc: TRect;
  378. begin
  379. if (BiDiMode = bdRightToLeft) then
  380. SetRect(Loc, GetButtonWidth + 1, 0, ClientWidth - 1, ClientHeight + 1)
  381. else
  382. SetRect(Loc, 0, 0, ClientWidth - GetButtonWidth - 2, ClientHeight + 1);
  383. SendMessage(Handle, EM_SETRECTNP, 0, Longint(@Loc));
  384. end;
  385. procedure TUpDownEdit.SetAlignment(Value: TAlignment);
  386. begin
  387. if FAlignment <> Value then
  388. begin
  389. FAlignment := Value;
  390. RecreateWnd;
  391. end;
  392. end;
  393. procedure TUpDownEdit.WMSize(var Message: TWMSize);
  394. var
  395. MinHeight: Integer;
  396. begin
  397. inherited;
  398. MinHeight := GetMinHeight;
  399. { text edit bug: if size to less than minheight, then edit ctrl does
  400. not display the text }
  401. if Height < MinHeight then
  402. Height := MinHeight
  403. else begin
  404. ResizeButton;
  405. SetEditRect;
  406. end;
  407. end;
  408. procedure TUpDownEdit.GetTextHeight(var SysHeight, Height: Integer);
  409. var
  410. DC: HDC;
  411. SaveFont: HFont;
  412. SysMetrics, Metrics: TTextMetric;
  413. begin
  414. DC := GetDC(0);
  415. GetTextMetrics(DC, SysMetrics);
  416. SaveFont := SelectObject(DC, Font.Handle);
  417. GetTextMetrics(DC, Metrics);
  418. SelectObject(DC, SaveFont);
  419. ReleaseDC(0, DC);
  420. SysHeight := SysMetrics.tmHeight;
  421. Height := Metrics.tmHeight;
  422. end;
  423. function TUpDownEdit.GetMinHeight: Integer;
  424. var
  425. I, H: Integer;
  426. begin
  427. GetTextHeight(I, H);
  428. if I > H then I := H;
  429. Result := H + (GetSystemMetricsForControl(Self, SM_CYBORDER) * 4) + 1;
  430. end;
  431. procedure TUpDownEdit.UpClick(Sender: TObject);
  432. var
  433. OldText: string;
  434. begin
  435. if ReadOnly then MessageBeep(MB_ICONHAND)
  436. else begin
  437. FChanging := True;
  438. try
  439. OldText := inherited Text;
  440. Value := Value + FIncrement;
  441. finally
  442. FChanging := False;
  443. end;
  444. if CompareText(inherited Text, OldText) <> 0 then
  445. begin
  446. Modified := True;
  447. Change;
  448. end;
  449. if Assigned(FOnTopClick) then FOnTopClick(Self);
  450. end;
  451. end;
  452. procedure TUpDownEdit.DownClick(Sender: TObject);
  453. var
  454. OldText: string;
  455. begin
  456. if ReadOnly then MessageBeep(MB_ICONHAND)
  457. else begin
  458. FChanging := True;
  459. try
  460. OldText := inherited Text;
  461. Value := Value - FIncrement;
  462. finally
  463. FChanging := False;
  464. end;
  465. if CompareText(inherited Text, OldText) <> 0 then
  466. begin
  467. Modified := True;
  468. Change;
  469. end;
  470. if Assigned(FOnBottomClick) then FOnBottomClick(Self);
  471. end;
  472. end;
  473. procedure TUpDownEdit.CMBiDiModeChanged(var Message: TMessage);
  474. begin
  475. inherited;
  476. ResizeButton;
  477. SetEditRect;
  478. end;
  479. procedure TUpDownEdit.CMFontChanged(var Message: TMessage);
  480. begin
  481. inherited;
  482. ResizeButton;
  483. SetEditRect;
  484. end;
  485. procedure TUpDownEdit.CMCtl3DChanged(var Message: TMessage);
  486. begin
  487. inherited;
  488. ResizeButton;
  489. SetEditRect;
  490. end;
  491. procedure TUpDownEdit.CMEnabledChanged(var Message: TMessage);
  492. begin
  493. inherited;
  494. if FUpDown <> nil then
  495. begin
  496. FUpDown.Enabled := Enabled;
  497. ResizeButton;
  498. end;
  499. end;
  500. procedure TUpDownEdit.WMPaste(var Message: TWMPaste);
  501. begin
  502. if not FEditorEnabled or ReadOnly then Exit;
  503. inherited;
  504. end;
  505. procedure TUpDownEdit.WMCut(var Message: TWMCut);
  506. begin
  507. if not FEditorEnabled or ReadOnly then Exit;
  508. inherited;
  509. end;
  510. procedure TUpDownEdit.CMExit(var Message: TCMExit);
  511. begin
  512. inherited;
  513. SetValue(Value);
  514. end;
  515. procedure TUpDownEdit.CMEnter(var Message: TMessage);
  516. begin
  517. if AutoSelect and not (csLButtonDown in ControlState) then SelectAll;
  518. inherited;
  519. end;
  520. function TUpDownEdit.GetValue: Extended;
  521. var
  522. Handled: Boolean;
  523. begin
  524. Handled := False;
  525. if Assigned(FOnGetValue) then FOnGetValue(Self, Text, Result, Handled);
  526. if not Handled then
  527. begin
  528. try
  529. if ValueType = vtFloat then Result := StrToFloat(Text)
  530. else if ValueType = vtHex then Result := StrToInt('$' + Text)
  531. else Result := StrToInt(Text);
  532. except
  533. if ValueType = vtFloat then Result := FMinValue
  534. else Result := Trunc(FMinValue);
  535. end;
  536. end;
  537. end;
  538. procedure TUpDownEdit.SetValue(NewValue: Extended);
  539. var
  540. Handled: Boolean;
  541. AText: string;
  542. begin
  543. NewValue := CheckValue(NewValue);
  544. Handled := False;
  545. if Assigned(FOnSetValue) then
  546. begin
  547. AText := Text;
  548. FOnSetValue(Self, NewValue, AText, Handled);
  549. if Handled then Text := AText;
  550. end;
  551. if not Handled then
  552. begin
  553. if ValueType = vtFloat then
  554. Text := FloatToStrF(NewValue, ffFixed, 15, FDecimal)
  555. else if ValueType = vtHex then
  556. Text := IntToHex(Round(NewValue), 1)
  557. else
  558. Text := IntToStr(Round(NewValue));
  559. end;
  560. end;
  561. function TUpDownEdit.GetAsInteger: Longint;
  562. begin
  563. Result := Trunc(GetValue);
  564. end;
  565. procedure TUpDownEdit.SetAsInteger(NewValue: Longint);
  566. begin
  567. SetValue(NewValue);
  568. end;
  569. procedure TUpDownEdit.SetValueType(NewType: TValueType);
  570. begin
  571. if FValueType <> NewType then
  572. begin
  573. FValueType := NewType;
  574. Value := GetValue;
  575. if FValueType in [vtInt, vtHex] then
  576. begin
  577. FIncrement := Round(FIncrement);
  578. if FIncrement = 0 then FIncrement := 1;
  579. end;
  580. end;
  581. end;
  582. function TUpDownEdit.IsIncrementStored: Boolean;
  583. begin
  584. Result := FIncrement <> 1.0;
  585. end;
  586. function TUpDownEdit.IsMaxStored: Boolean;
  587. begin
  588. Result := (MaxValue <> 0.0);
  589. end;
  590. function TUpDownEdit.IsMinStored: Boolean;
  591. begin
  592. Result := (MinValue <> 0.0);
  593. end;
  594. function TUpDownEdit.IsValueStored: Boolean;
  595. begin
  596. Result := (GetValue <> MinValue);
  597. end;
  598. procedure TUpDownEdit.SetDecimal(NewValue: Byte);
  599. begin
  600. if FDecimal <> NewValue then
  601. begin
  602. FDecimal := NewValue;
  603. Value := GetValue;
  604. end;
  605. end;
  606. function TUpDownEdit.CheckValue(NewValue: Extended): Extended;
  607. begin
  608. Result := NewValue;
  609. if (FMaxValue <> FMinValue) then
  610. begin
  611. if NewValue < FMinValue then
  612. Result := FMinValue
  613. else if NewValue > FMaxValue then
  614. Result := FMaxValue;
  615. end;
  616. end;
  617. procedure TUpDownEdit.SetButtonsVisible(Value: Boolean);
  618. begin
  619. if ButtonsVisible <> Value then
  620. begin
  621. FButtonsVisible := Value;
  622. ResizeButton;
  623. SetEditRect;
  624. end;
  625. end;
  626. procedure TUpDownEdit.SetDarkMode(Value: Boolean);
  627. begin
  628. if DarkMode <> Value then
  629. begin
  630. FDarkMode := Value;
  631. RecreateWnd;
  632. end;
  633. end;
  634. initialization
  635. end.