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

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1995, 1996 AO ROSNO             }
  6. {         Copyright (c) 1997, 1998 Master-Bank          }
  7. {                                                       }
  8. {*******************************************************}
  9. unit CurrEdit;
  10. {$I RX.INC}
  11. {$W-}
  12. interface
  13. uses SysUtils, {$IFDEF WIN32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  14.   Messages, Classes, Graphics, Controls, Menus, Forms, StdCtrls, Mask,
  15.   Buttons, ToolEdit;
  16. type
  17. { TCustomNumEdit }
  18.   TCustomNumEdit = class(TCustomComboEdit)
  19.   private
  20.     FCanvas: TControlCanvas;
  21.     FAlignment: TAlignment;
  22.     FFocused: Boolean;
  23.     FValue: Extended;
  24.     FMinValue, FMaxValue: Extended;
  25.     FDecimalPlaces: Cardinal;
  26.     FBeepOnError: Boolean;
  27.     FCheckOnExit: Boolean;
  28.     FZeroEmpty: Boolean;
  29.     FFormatOnEditing: Boolean;
  30.     FFormatting: Boolean;
  31.     FDisplayFormat: PString;
  32.     procedure SetFocused(Value: Boolean);
  33.     procedure SetAlignment(Value: TAlignment);
  34.     procedure SetBeepOnError(Value: Boolean);
  35.     procedure SetDisplayFormat(const Value: string);
  36.     function GetDisplayFormat: string;
  37.     procedure SetDecimalPlaces(Value: Cardinal);
  38.     function GetValue: Extended;
  39.     procedure SetValue(AValue: Extended);
  40.     function GetAsInteger: Longint;
  41.     procedure SetAsInteger(AValue: Longint);
  42.     procedure SetMaxValue(AValue: Extended);
  43.     procedure SetMinValue(AValue: Extended);
  44.     procedure SetZeroEmpty(Value: Boolean);
  45.     procedure SetFormatOnEditing(Value: Boolean);
  46.     function GetText: string;
  47.     procedure SetText(const AValue: string);
  48.     function TextToValText(const AValue: string): string;
  49.     function CheckValue(NewValue: Extended; RaiseOnError: Boolean): Extended;
  50.     function IsFormatStored: Boolean;
  51.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  52.     procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
  53.     procedure CMExit(var Message: TCMExit); message CM_EXIT;
  54.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  55.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  56.     procedure WMPaste(var Message: TMessage); message WM_PASTE;
  57.   protected
  58. {$IFDEF WIN32}
  59.     procedure AcceptValue(const Value: Variant); override;
  60. {$ELSE}
  61.     procedure AcceptValue(const Value: string); override;
  62. {$ENDIF}
  63.     procedure Change; override;
  64.     procedure ReformatEditText; dynamic;
  65.     function GetDefaultBitmap(var DestroyNeeded: Boolean): TBitmap; override;
  66.     procedure DataChanged; virtual;
  67.     function DefaultDisplayFormat: string; virtual;
  68.     procedure KeyPress(var Key: Char); override;
  69.     function IsValidChar(Key: Char): Boolean; virtual;
  70.     function FormatDisplayText(Value: Extended): string;
  71.     function GetDisplayText: string; virtual;
  72.     procedure Reset; override;
  73.     procedure CheckRange;
  74.     procedure UpdateData;
  75.     procedure UpdatePopup; virtual;
  76.     property Formatting: Boolean read FFormatting;
  77.     property Alignment: TAlignment read FAlignment write SetAlignment
  78.       default taRightJustify;
  79.     property BeepOnError: Boolean read FBeepOnError write SetBeepOnError
  80.       default True;
  81.     property CheckOnExit: Boolean read FCheckOnExit write FCheckOnExit default False;
  82.     property GlyphKind default gkDefault;
  83.     property ButtonWidth default 20;
  84.     property DecimalPlaces: Cardinal read FDecimalPlaces write SetDecimalPlaces
  85.       default 2;
  86.     property DisplayFormat: string read GetDisplayFormat write SetDisplayFormat
  87.       stored IsFormatStored;
  88.     property MaxValue: Extended read FMaxValue write SetMaxValue;
  89.     property MinValue: Extended read FMinValue write SetMinValue;
  90.     property FormatOnEditing: Boolean read FFormatOnEditing
  91.       write SetFormatOnEditing default False;
  92.     property Text: string read GetText write SetText stored False;
  93.     property MaxLength default 0;
  94.     property ZeroEmpty: Boolean read FZeroEmpty write SetZeroEmpty default True;
  95.   public
  96.     constructor Create(AOwner: TComponent); override;
  97.     destructor Destroy; override;
  98.     procedure Clear; {$IFDEF RX_D5} override; {$ENDIF}
  99.     property AsInteger: Longint read GetAsInteger write SetAsInteger;
  100.     property DisplayText: string read GetDisplayText;
  101.     property PopupVisible;
  102.     property Value: Extended read GetValue write SetValue;
  103.   end;
  104. { TCurrencyEdit }
  105.   TCurrencyEdit = class(TCustomNumEdit)
  106.   protected
  107.     function DefaultDisplayFormat: string; override;
  108.   public
  109.     constructor Create(AOwner: TComponent); override;
  110.   published
  111.     property Alignment;
  112.     property AutoSelect;
  113.     property AutoSize;
  114.     property BeepOnError;
  115.     property BorderStyle;
  116.     property CheckOnExit;
  117.     property Color;
  118.     property Ctl3D;
  119.     property DecimalPlaces;
  120.     property DisplayFormat;
  121.     property DragCursor;
  122.     property DragMode;
  123.     property Enabled;
  124.     property Font;
  125.     property FormatOnEditing;
  126.     property HideSelection;
  127. {$IFDEF RX_D4}
  128.     property Anchors;
  129.     property BiDiMode;
  130.     property Constraints;
  131.     property DragKind;
  132.     property ParentBiDiMode;
  133. {$ENDIF}
  134. {$IFDEF WIN32}
  135.   {$IFNDEF VER90}
  136.     property ImeMode;
  137.     property ImeName;
  138.   {$ENDIF}
  139. {$ENDIF}
  140.     property MaxLength;
  141.     property MaxValue;
  142.     property MinValue;
  143.     property ParentColor;
  144.     property ParentCtl3D;
  145.     property ParentFont;
  146.     property ParentShowHint;
  147.     property PopupMenu;
  148.     property ReadOnly;
  149.     property ShowHint;
  150.     property TabOrder;
  151.     property TabStop;
  152.     property Text;
  153.     property Value;
  154.     property Visible;
  155.     property ZeroEmpty;
  156.     property OnChange;
  157.     property OnClick;
  158.     property OnDblClick;
  159.     property OnDragDrop;
  160.     property OnDragOver;
  161.     property OnEndDrag;
  162.     property OnEnter;
  163.     property OnExit;
  164.     property OnKeyDown;
  165.     property OnKeyPress;
  166.     property OnKeyUp;
  167.     property OnMouseDown;
  168.     property OnMouseMove;
  169.     property OnMouseUp;
  170. {$IFDEF RX_D5}
  171.     property OnContextPopup;
  172. {$ENDIF}
  173. {$IFDEF WIN32}
  174.     property OnStartDrag;
  175. {$ENDIF}
  176. {$IFDEF RX_D4}
  177.     property OnEndDock;
  178.     property OnStartDock;
  179. {$ENDIF}
  180.   end;
  181. { TRxCustomCalcEdit }
  182.   TRxCustomCalcEdit = class(TCustomNumEdit)
  183.   public
  184.     constructor Create(AOwner: TComponent); override;
  185.   end;
  186. { TRxCalcEdit }
  187.   TRxCalcEdit = class(TRxCustomCalcEdit)
  188.   published
  189.     property Alignment;
  190.     property AutoSelect;
  191.     property AutoSize;
  192.     property BeepOnError;
  193.     property BorderStyle;
  194.     property ButtonHint;
  195.     property CheckOnExit;
  196.     property ClickKey;
  197.     property Color;
  198.     property Ctl3D;
  199.     property DecimalPlaces;
  200.     property DirectInput;
  201.     property DisplayFormat;
  202.     property DragCursor;
  203.     property DragMode;
  204.     property Enabled;
  205.     property Font;
  206.     property FormatOnEditing;
  207.     property GlyphKind;
  208.     { Ensure GlyphKind is published before Glyph and ButtonWidth }
  209.     property Glyph;
  210.     property ButtonWidth;
  211.     property HideSelection;
  212. {$IFDEF RX_D4}
  213.     property Anchors;
  214.     property BiDiMode;
  215.     property Constraints;
  216.     property DragKind;
  217.     property ParentBiDiMode;
  218. {$ENDIF}
  219. {$IFDEF WIN32}
  220.   {$IFNDEF VER90}
  221.     property ImeMode;
  222.     property ImeName;
  223.   {$ENDIF}
  224. {$ENDIF}
  225.     property MaxLength;
  226.     property MaxValue;
  227.     property MinValue;
  228.     property NumGlyphs;
  229.     property ParentColor;
  230.     property ParentCtl3D;
  231.     property ParentFont;
  232.     property ParentShowHint;
  233.     property PopupAlign;
  234.     property PopupMenu;
  235.     property ReadOnly;
  236.     property ShowHint;
  237.     property TabOrder;
  238.     property TabStop;
  239.     property Text;
  240.     property Value;
  241.     property Visible;
  242.     property ZeroEmpty;
  243.     property OnButtonClick;
  244.     property OnChange;
  245.     property OnClick;
  246.     property OnDblClick;
  247.     property OnDragDrop;
  248.     property OnDragOver;
  249.     property OnEndDrag;
  250.     property OnEnter;
  251.     property OnExit;
  252.     property OnKeyDown;
  253.     property OnKeyPress;
  254.     property OnKeyUp;
  255.     property OnMouseDown;
  256.     property OnMouseMove;
  257.     property OnMouseUp;
  258. {$IFDEF RX_D5}
  259.     property OnContextPopup;
  260. {$ENDIF}
  261. {$IFDEF WIN32}
  262.     property OnStartDrag;
  263. {$ENDIF}
  264. {$IFDEF RX_D4}
  265.     property OnEndDock;
  266.     property OnStartDock;
  267. {$ENDIF}
  268.   end;
  269. implementation
  270. uses Consts, rxStrUtils, VclUtils, MaxMin, RxCalc;
  271. {$IFDEF WIN32}
  272.  {$R *.R32}
  273. {$ELSE}
  274.  {$R *.R16}
  275. {$ENDIF}
  276. const
  277.   sCalcBmp = 'CEDITBMP'; { Numeric editor button glyph }
  278.   CalcBitmap: TBitmap = nil;
  279. type
  280.   THack = class(TPopupWindow);
  281. function IsValidFloat(const Value: string; var RetValue: Extended): Boolean;
  282. var
  283.   I: Integer;
  284.   Buffer: array[0..63] of Char;
  285. begin
  286.   Result := False;
  287.   for I := 1 to Length(Value) do
  288.     if not (Value[I] in [DecimalSeparator, '-', '+', '0'..'9', 'e', 'E']) then
  289.       Exit;
  290.   Result := TextToFloat(StrPLCopy(Buffer, Value,
  291.     SizeOf(Buffer) - 1), RetValue {$IFDEF WIN32}, fvExtended {$ENDIF});
  292. end;
  293. function FormatFloatStr(const S: string; Thousands: Boolean): string;
  294. var
  295.   I, MaxSym, MinSym, Group: Integer;
  296.   IsSign: Boolean;
  297. begin
  298.   Result := '';
  299.   MaxSym := Length(S);
  300.   IsSign := (MaxSym > 0) and (S[1] in ['-', '+']);
  301.   if IsSign then MinSym := 2
  302.   else MinSym := 1;
  303.   I := Pos(DecimalSeparator, S);
  304.   if I > 0 then MaxSym := I - 1;
  305.   I := Pos('E', AnsiUpperCase(S));
  306.   if I > 0 then MaxSym := Min(I - 1, MaxSym);
  307.   Result := Copy(S, MaxSym + 1, MaxInt);
  308.   Group := 0;
  309.   for I := MaxSym downto MinSym do begin
  310.     Result := S[I] + Result;
  311.     Inc(Group);
  312.     if (Group = 3) and Thousands and (I > MinSym) then begin
  313.       Group := 0;
  314.       Result := ThousandSeparator + Result;
  315.     end;
  316.   end;
  317.   if IsSign then Result := S[1] + Result;
  318. end;
  319. { TCustomNumEdit }
  320. constructor TCustomNumEdit.Create(AOwner: TComponent);
  321. begin
  322.   inherited Create(AOwner);
  323.   ControlStyle := ControlStyle - [csSetCaption];
  324.   MaxLength := 0;
  325.   FBeepOnError := True;
  326.   FAlignment := taRightJustify;
  327.   FDisplayFormat := NewStr(DefaultDisplayFormat);
  328.   FDecimalPlaces := 2;
  329.   FZeroEmpty := True;
  330.   inherited Text := '';
  331.   inherited Alignment := taLeftJustify;
  332.   FDefNumGlyphs := 2;
  333.   { forces update }
  334.   DataChanged;
  335.   ControlState := ControlState + [csCreating];
  336.   try
  337.     GlyphKind := gkDefault;
  338.     ButtonWidth := 20;
  339.   finally
  340.     ControlState := ControlState - [csCreating];
  341.   end;
  342. end;
  343. destructor TCustomNumEdit.Destroy;
  344. begin
  345.   FCanvas.Free;
  346.   DisposeStr(FDisplayFormat);
  347.   if FPopup <> nil then begin
  348.     TPopupWindow(FPopup).OnCloseUp := nil;
  349.     FPopup.Free;
  350.     FPopup := nil;
  351.   end;
  352.   inherited Destroy;
  353. end;
  354. function TCustomNumEdit.GetDefaultBitmap(var DestroyNeeded: Boolean): TBitmap;
  355. begin
  356.   DestroyNeeded := False;
  357.   if CalcBitmap = nil then begin
  358.     CalcBitmap := TBitmap.Create;
  359.     CalcBitmap.Handle := LoadBitmap(hInstance, sCalcBmp);
  360.   end;
  361.   Result := CalcBitmap;
  362. end;
  363. function TCustomNumEdit.DefaultDisplayFormat: string;
  364. begin
  365.   Result := ',0.##';
  366. end;
  367. function TCustomNumEdit.IsFormatStored: Boolean;
  368. begin
  369.   Result := (DisplayFormat <> DefaultDisplayFormat);
  370. end;
  371. function TCustomNumEdit.IsValidChar(Key: Char): Boolean;
  372. var
  373.   S: string;
  374.   SelStart, SelStop, DecPos: Integer;
  375.   RetValue: Extended;
  376. begin
  377.   Result := False;
  378.   S := EditText;
  379.   GetSel(SelStart, SelStop);
  380.   System.Delete(S, SelStart + 1, SelStop - SelStart);
  381.   System.Insert(Key, S, SelStart + 1);
  382.   S := TextToValText(S);
  383.   DecPos := Pos(DecimalSeparator, S);
  384.   if (DecPos > 0) then begin
  385.     SelStart := Pos('E', UpperCase(S));
  386.     if (SelStart > DecPos) then DecPos := SelStart - DecPos
  387.     else DecPos := Length(S) - DecPos;
  388.     if DecPos > Integer(FDecimalPlaces) then Exit;
  389.   end;
  390.   Result := IsValidFloat(S, RetValue);
  391.   if Result and (FMinValue >= 0) and (FMaxValue > 0) and (RetValue < 0) then
  392.     Result := False;
  393. end;
  394. procedure TCustomNumEdit.KeyPress(var Key: Char);
  395. begin
  396.   if PopupVisible and (UpCase(Key) in ['0'..'9', DecimalSeparator, '.', ',',
  397.     '+', '-', '*', '/', '_', '=', 'C', 'R', 'Q', '%', #8, #13]) then
  398.   begin
  399.     THack(FPopup).KeyPress(Key);
  400.     Key := #0;
  401.   end;
  402.   if Key in ['.', ','] then Key := DecimalSeparator;
  403.   inherited KeyPress(Key);
  404.   if (Key in [#32..#255]) and not IsValidChar(Key) then begin
  405.     if BeepOnError then MessageBeep(0);
  406.     Key := #0;
  407.   end
  408.   else if Key = #27 then begin
  409.     Reset;
  410.     Key := #0;
  411.   end;
  412. end;
  413. procedure TCustomNumEdit.Reset;
  414. begin
  415.   DataChanged;
  416.   SelectAll;
  417. end;
  418. procedure TCustomNumEdit.SetZeroEmpty(Value: Boolean);
  419. begin
  420.   if FZeroEmpty <> Value then begin
  421.     FZeroEmpty := Value;
  422.     DataChanged;
  423.   end;
  424. end;
  425. procedure TCustomNumEdit.SetBeepOnError(Value: Boolean);
  426. begin
  427.   if FBeepOnError <> Value then begin
  428.     FBeepOnError := Value;
  429.     UpdatePopup;
  430.   end;
  431. end;
  432. procedure TCustomNumEdit.SetAlignment(Value: TAlignment);
  433. begin
  434.   if FAlignment <> Value then begin
  435.     FAlignment := Value;
  436.     Invalidate;
  437.   end;
  438. end;
  439. procedure TCustomNumEdit.SetDisplayFormat(const Value: string);
  440. begin
  441.   if DisplayFormat <> Value then begin
  442.     AssignStr(FDisplayFormat, Value);
  443.     Invalidate;
  444.     DataChanged;
  445.   end;
  446. end;
  447. function TCustomNumEdit.GetDisplayFormat: string;
  448. begin
  449.   Result := FDisplayFormat^;
  450. end;
  451. procedure TCustomNumEdit.SetFocused(Value: Boolean);
  452. begin
  453.   if FFocused <> Value then begin
  454.     FFocused := Value;
  455.     Invalidate;
  456.     FFormatting := True;
  457.     try
  458.       DataChanged;
  459.     finally
  460.       FFormatting := False;
  461.     end;
  462.   end;
  463. end;
  464. procedure TCustomNumEdit.SetFormatOnEditing(Value: Boolean);
  465. begin
  466.   if FFormatOnEditing <> Value then begin
  467.     FFormatOnEditing := Value;
  468.     if FFormatOnEditing then inherited Alignment := Alignment
  469.     else inherited Alignment := taLeftJustify;
  470.     if FFormatOnEditing and FFocused then ReformatEditText
  471.     else if FFocused then begin
  472.       UpdateData;
  473.       DataChanged;
  474.     end;
  475.   end;
  476. end;
  477. procedure TCustomNumEdit.SetDecimalPlaces(Value: Cardinal);
  478. begin
  479.   if FDecimalPlaces <> Value then begin
  480.     FDecimalPlaces := Value;
  481.     DataChanged;
  482.     Invalidate;
  483.   end;
  484. end;
  485. function TCustomNumEdit.FormatDisplayText(Value: Extended): string;
  486. begin
  487.   if DisplayFormat <> '' then
  488.     Result := FormatFloat(DisplayFormat, Value)
  489.   else
  490.     Result := FloatToStr(Value);
  491. end;
  492. function TCustomNumEdit.GetDisplayText: string;
  493. begin
  494.   Result := FormatDisplayText(FValue);
  495. end;
  496. procedure TCustomNumEdit.Clear;
  497. begin
  498.   Text := '';
  499. end;
  500. procedure TCustomNumEdit.DataChanged;
  501. var
  502.   EditFormat: string;
  503. begin
  504.   EditFormat := '0';
  505.   if FDecimalPlaces > 0 then
  506.     EditFormat := EditFormat + '.' + MakeStr('#', FDecimalPlaces);
  507.   if (FValue = 0.0) and FZeroEmpty then
  508.     EditText := ''
  509.   else
  510.     EditText := FormatFloat(EditFormat, FValue);
  511. end;
  512. function TCustomNumEdit.CheckValue(NewValue: Extended;
  513.   RaiseOnError: Boolean): Extended;
  514. begin
  515.   Result := NewValue;
  516.   if (FMaxValue <> FMinValue) then begin
  517.     if (FMaxValue > FMinValue) then begin
  518.       if NewValue < FMinValue then Result := FMinValue
  519.       else if NewValue > FMaxValue then Result := FMaxValue;
  520.     end
  521.     else begin
  522.       if FMaxValue = 0 then begin
  523.         if NewValue < FMinValue then Result := FMinValue;
  524.       end
  525.       else if FMinValue = 0 then begin
  526.         if NewValue > FMaxValue then Result := FMaxValue;
  527.       end;
  528.     end;
  529.     if RaiseOnError and (Result <> NewValue) then
  530.       raise ERangeError.CreateFmt(ReplaceStr(ResStr(SOutOfRange), '%d', '%.*f'),
  531.         [DecimalPlaces, FMinValue, DecimalPlaces, FMaxValue]);
  532.   end;
  533. end;
  534. procedure TCustomNumEdit.CheckRange;
  535. begin
  536.   if not (csDesigning in ComponentState) and CheckOnExit then
  537.     CheckValue(StrToFloat(TextToValText(EditText)), True);
  538. end;
  539. procedure TCustomNumEdit.UpdateData;
  540. begin
  541.   ValidateEdit;
  542.   FValue := CheckValue(StrToFloat(TextToValText(EditText)), False);
  543. end;
  544. procedure TCustomNumEdit.UpdatePopup;
  545. begin
  546.   if FPopup <> nil then
  547.     SetupPopupCalculator(FPopup, DefCalcPrecision, BeepOnError);
  548. end;
  549. function TCustomNumEdit.GetValue: Extended;
  550. begin
  551.   if not (csDesigning in ComponentState) then
  552.     try
  553.       UpdateData;
  554.     except
  555.       FValue := FMinValue;
  556.     end;
  557.   Result := FValue;
  558. end;
  559. procedure TCustomNumEdit.SetValue(AValue: Extended);
  560. begin
  561.   FValue := CheckValue(AValue, False);
  562.   DataChanged;
  563.   Invalidate;
  564. end;
  565. function TCustomNumEdit.GetAsInteger: Longint;
  566. begin
  567.   Result := Trunc(Value);
  568. end;
  569. procedure TCustomNumEdit.SetAsInteger(AValue: Longint);
  570. begin
  571.   SetValue(AValue);
  572. end;
  573. procedure TCustomNumEdit.SetMinValue(AValue: Extended);
  574. begin
  575.   if FMinValue <> AValue then begin
  576.     FMinValue := AValue;
  577.     Value := FValue;
  578.   end;
  579. end;
  580. procedure TCustomNumEdit.SetMaxValue(AValue: Extended);
  581. begin
  582.   if FMaxValue <> AValue then begin
  583.     FMaxValue := AValue;
  584.     Value := FValue;
  585.   end;
  586. end;
  587. function TCustomNumEdit.GetText: string;
  588. begin
  589.   Result := inherited Text;
  590. end;
  591. function TCustomNumEdit.TextToValText(const AValue: string): string;
  592. begin
  593.   Result := DelRSpace(AValue);
  594.   if DecimalSeparator <> ThousandSeparator then begin
  595.     Result := DelChars(Result, ThousandSeparator);
  596.   end;
  597.   if (DecimalSeparator <> '.') and (ThousandSeparator <> '.') then
  598.     Result := ReplaceStr(Result, '.', DecimalSeparator);
  599.   if (DecimalSeparator <> ',') and (ThousandSeparator <> ',') then
  600.     Result := ReplaceStr(Result, ',', DecimalSeparator);
  601.   if Result = '' then Result := '0'
  602.   else if Result = '-' then Result := '-0';
  603. end;
  604. procedure TCustomNumEdit.SetText(const AValue: string);
  605. begin
  606.   if not (csReading in ComponentState) then begin
  607.     FValue := CheckValue(StrToFloat(TextToValText(AValue)), False);
  608.     DataChanged;
  609.     Invalidate;
  610.   end;
  611. end;
  612. procedure TCustomNumEdit.ReformatEditText;
  613. var
  614.   S: string;
  615.   IsEmpty: Boolean;
  616.   OldLen, SelStart, SelStop: Integer;
  617. begin
  618.   FFormatting := True;
  619.   try
  620.     S := inherited Text;
  621.     OldLen := Length(S);
  622.     IsEmpty := (OldLen = 0) or (S = '-');
  623.     if HandleAllocated then GetSel(SelStart, SelStop);
  624.     if not IsEmpty then S := TextToValText(S);
  625.     S := FormatFloatStr(S, Pos(',', DisplayFormat) > 0);
  626.     inherited Text := S;
  627.     if HandleAllocated and (GetFocus = Handle) and not
  628.       (csDesigning in ComponentState) then
  629.     begin
  630.       Inc(SelStart, Length(S) - OldLen);
  631.       SetCursor(SelStart);
  632.     end;
  633.   finally
  634.     FFormatting := False;
  635.   end;
  636. end;
  637. procedure TCustomNumEdit.Change;
  638. begin
  639.   if not FFormatting then begin
  640.     if FFormatOnEditing and FFocused then ReformatEditText;
  641.     inherited Change;
  642.   end;
  643. end;
  644. {$IFDEF WIN32}
  645. procedure TCustomNumEdit.AcceptValue(const Value: Variant);
  646. {$ELSE}
  647. procedure TCustomNumEdit.AcceptValue(const Value: string);
  648. {$ENDIF}
  649. begin
  650.   inherited AcceptValue(Value);
  651. end;
  652. procedure TCustomNumEdit.WMPaste(var Message: TMessage);
  653. var
  654.   S: string;
  655. begin
  656.   S := EditText;
  657.   try
  658.     inherited;
  659.     UpdateData;
  660.   except
  661.     EditText := S;
  662.     SelectAll;
  663.     if CanFocus then SetFocus;
  664.     if BeepOnError then MessageBeep(0);
  665.   end;
  666. end;
  667. procedure TCustomNumEdit.CMEnter(var Message: TCMEnter);
  668. begin
  669.   SetFocused(True);
  670.   if FFormatOnEditing then ReformatEditText;
  671.   inherited;
  672. end;
  673. procedure TCustomNumEdit.CMExit(var Message: TCMExit);
  674. begin
  675.   try
  676.     CheckRange;
  677.     UpdateData;
  678.   except
  679.     SelectAll;
  680.     if CanFocus then SetFocus;
  681.     raise;
  682.   end;
  683.   SetFocused(False);
  684.   SetCursor(0);
  685.   DoExit;
  686. end;
  687. procedure TCustomNumEdit.CMEnabledChanged(var Message: TMessage);
  688. begin
  689.   inherited;
  690.   if NewStyleControls and not FFocused then Invalidate;
  691. end;
  692. procedure TCustomNumEdit.WMPaint(var Message: TWMPaint);
  693. var
  694.   S: string;
  695. begin
  696.   if PopupVisible then S := TPopupWindow(FPopup).GetPopupText
  697.   else S := GetDisplayText;
  698.   if not PaintComboEdit(Self, S, FAlignment, FFocused and not PopupVisible,
  699.     FCanvas, Message) then inherited;
  700. end;
  701. procedure TCustomNumEdit.CMFontChanged(var Message: TMessage);
  702. begin
  703.   inherited;
  704.   Invalidate;
  705. end;
  706. { TCurrencyEdit }
  707. constructor TCurrencyEdit.Create(AOwner: TComponent);
  708. begin
  709.   inherited Create(AOwner);
  710.   ControlState := ControlState + [csCreating];
  711.   try
  712.     ButtonWidth := 0;
  713.   finally
  714.     ControlState := ControlState - [csCreating];
  715.   end;
  716. end;
  717. function TCurrencyEdit.DefaultDisplayFormat: string;
  718. var
  719.   CurrStr: string;
  720.   I: Integer;
  721.   C: Char;
  722. begin
  723.   Result := ',0.' + MakeStr('0', CurrencyDecimals);
  724.   CurrStr := '';
  725.   for I := 1 to Length(CurrencyString) do begin
  726.     C := CurrencyString[I];
  727.     if C in [',', '.'] then CurrStr := CurrStr + '''' + C + ''''
  728.     else CurrStr := CurrStr + C;
  729.   end;
  730.   if Length(CurrStr) > 0 then
  731.     case CurrencyFormat of
  732.       0: Result := CurrStr + Result; { '$1' }
  733.       1: Result := Result + CurrStr; { '1$' }
  734.       2: Result := CurrStr + ' ' + Result; { '$ 1' }
  735.       3: Result := Result + ' ' + CurrStr; { '1 $' }
  736.     end;
  737.   Result := Format('%s;-%s', [Result, Result]);
  738. end;
  739. { TRxCustomCalcEdit }
  740. constructor TRxCustomCalcEdit.Create(AOwner: TComponent);
  741. begin
  742.   inherited Create(AOwner);
  743.   ControlState := ControlState + [csCreating];
  744.   try
  745.     FPopup := TPopupWindow(CreatePopupCalculator(Self
  746.       {$IFDEF RX_D4}, BiDiMode {$ENDIF}));
  747.     TPopupWindow(FPopup).OnCloseUp := PopupCloseUp;
  748.     UpdatePopup;
  749.   finally
  750.     ControlState := ControlState - [csCreating];
  751.   end;
  752. end;
  753. procedure DestroyLocals; far;
  754. begin
  755.   CalcBitmap.Free;
  756.   CalcBitmap := nil;
  757. end;
  758. {$IFDEF WIN32}
  759. initialization
  760. finalization
  761.   DestroyLocals;
  762. {$ELSE}
  763. initialization
  764.   AddExitProc(DestroyLocals);
  765. {$ENDIF}
  766. end.