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

Delphi控件源码

开发平台:

Delphi

  1. unit fcCalcEdit;
  2. {
  3. //
  4. // Components : TfcCalcEdit
  5. //
  6. // Copyright (c) 2001 by Woll2Woll Software
  7. //
  8. // Changes:
  9. // 10/01/2001-Added check to see if current value is 0 then start text with 0 followed by decimal
  10. //            Added OnMouseEnter/OnMouseLeave events.  Added OnSetCalcButtonAttributes event.
  11. //            published AutoSize,Anchors,Constraints properties.
  12. //            Also added AllowNull property. Handled WMPaste and WMCut.
  13. // 10/04/2001-Added Alignment and DisplayFormat property and fixed some text display issues.
  14. // 12/12/2001-Handle additional Decimal cases when cboShowDecimal in Options.
  15. // 1/21/2002 - Color not set when control loses focus.
  16. // 2/28/2002 - Handle Decimal cases when selecting text or when backspacing so as to allow decimals.
  17. // 3/1/2002 - Fixed some display problems when setting value at runtime.
  18. // 3/1/2002 - Enabled Inplace Edit so that end-user can modify an existing number.  Modified behavior to
  19. //            paint focused text without special formatting characters for ease of calculation and natural
  20. //            use by end-user.  ClearOnNextKey flag use eliminated.
  21. // 3/1/2002-PYW-Use new function to handle num pad keys in windows 98.
  22. // 3/11/2002 - PYW - Handle Null Case in new DataChange procedure.
  23. }
  24. interface
  25. uses
  26.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Buttons, Forms, Dialogs,
  27.   StdCtrls, math, extctrls, fccombo, fccommon, fcCalculator, db;
  28. type
  29.   TfcCustomCalcEdit = class;
  30.   TfcPopupCalcOptions = class(TPersistent)
  31.   private
  32.     FBackground:TPicture;
  33.     FBackGroundStyle: TfcCalcBitmapDrawStyle;
  34.     FMargin:integer;
  35.     FOptions: TfcCalcOptions;
  36.     FPanelColor:TColor;
  37.     procedure SetBackgroundStyle(Value: TfcCalcBitmapDrawStyle);
  38.     procedure SetOptions(Value: TfcCalcOptions);
  39.     procedure SetMargin(Value: Integer);
  40.     procedure SetPanelColor(Value: TColor);
  41.   public
  42.     constructor Create(AOwner: TComponent);
  43.     destructor Destroy; override;
  44.   protected
  45.     procedure SetBackgroundBitmap(Value: TPicture); virtual;
  46.   published
  47.     property Background:TPicture read FBackground write SetBackGroundBitmap;
  48.     property BackgroundStyle: TfcCalcBitmapDrawStyle read FBackgroundStyle write SetBackgroundStyle;
  49.     property ButtonMargin: integer read FMargin write SetMargin default 3;
  50.     property Options: TfcCalcOptions read FOptions write SetOptions default [cboHideEditor];
  51.     property PanelColor: TColor read FPanelColor write SetPanelColor default clBtnFace;
  52.   end;
  53.   TfcCalcPanel = class(TfcCalculator)
  54.   private
  55.     FAssociatedEdit:TfcCustomCalcEdit;
  56.   protected
  57.     procedure CreateParams(var Params: TCreateParams); override;
  58.     procedure CreateWnd; override;
  59.     procedure Keypress(var Key: Char); override;
  60. //    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  61.   public
  62.     procedure DoCalc(ButtonType:TfcCalcButtonType); override;
  63.     constructor Create(AOwner: TComponent); override;
  64.     property AssociatedEdit:TfcCustomCalcEdit read FAssociatedEdit write FAssociatedEdit;
  65.   end;
  66.   TfcCalcAttributesEvent = procedure (Sender: TfcCustomCalcEdit;
  67.     var AType:TfcCalcButtonType;
  68.     var ACaption:String;
  69.     var AFontColor:TColor;
  70.     var AButtonColor:TColor;
  71.     var AHint:String) of object;
  72.   TfcCustomCalcEdit = class(TfcCustomCombo)
  73.   private
  74.     FAlignment: TAlignment;
  75.     FDisplayFormat:String;
  76.     FDecimalPlacesStored:integer;
  77.     FDropDownCalc:TfcCalcPanel;
  78.     FClearOnNextKey: boolean;
  79.     FAllowNull: boolean;
  80.     FCalcOptions : TfcPopupCalcOptions;
  81.     FOnCalcButtonAttributes: TfcCalcAttributesEvent;
  82.     FOnBeforeDropDown: TNotifyEvent;
  83.     FSkipTextChangedFlag:boolean;
  84.     FDecimalEntered:boolean;
  85.     procedure CMCancelMode(var Message: TCMCancelMode); message CM_CANCELMODE;
  86.     procedure WMCut(var Message: TMessage); message WM_CUT;
  87.     procedure WMPaste(var Message: TMessage); message WM_PASTE;
  88.     procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  89.     procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
  90.   protected
  91.     function GetValue: Double; virtual;
  92.     procedure SetValue(Value:Double); virtual;
  93.     procedure Paint; override;
  94.     function GetEditRect: TRect; override;
  95.     function IsValidOperator(Key: Char): boolean; virtual;
  96.     function IsUnaryOperator(Key:Char):boolean; virtual;
  97.     function IsBinaryOperator(Key:Char):boolean; virtual;
  98.     procedure CreateParams(var Params: TCreateParams); override;
  99.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  100.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  101.     procedure KeyPress(var Key: Char); override;
  102.     procedure DoEnter; override;
  103.     procedure DoExit; override;
  104.     procedure DoBeforeDropDown; virtual;
  105.     procedure UpdateData(Sender: TObject); override;
  106.     procedure DataChange(Sender: TObject); override;
  107.     // abstract methods
  108.     function SkipInheritedPaint : boolean; override;
  109.     function GetAlignment: TAlignment; virtual;
  110.     function GetDropDownControl: TWinControl; override;
  111.     function GetDropDownContainer: TWinControl; override;
  112.     function GetItemCount: Integer; override;
  113.     function GetItemSize: TSize; override;
  114.     procedure PaintToCanvas(Canvas: TCanvas; Rect: TRect; Highlight, GridPaint: Boolean;
  115.       aText: string); override;
  116. //    function GetPanel: TfcCalcPanel;
  117.     property DecimalEntered : boolean read FDecimalEntered write FDecimalEntered;
  118.     property SkipTextChangedFlag: boolean read FSkipTextChangedFlag write FSkipTextChangedFlag;
  119.   public
  120.     property Panel:TfcCalcPanel read fDropDownCalc write fDropDownCalc;
  121.     constructor Create( AOwner: TComponent ); override;
  122.     destructor Destroy; override;
  123.     procedure Loaded; override;
  124.     procedure CreateWnd; override;
  125.     //MAKE DoCloseUp and DoDropDown events.
  126.     procedure CloseUp(Accept: Boolean); override;
  127.     procedure DropDown; override;
  128.     function IsDroppedDown: Boolean; override;
  129.     procedure DoCalcButtonAttributes(Calc: TfcCalculator;var AType:TfcCalcButtonType;
  130.       var ACaption:String; var AFontColor:TColor; var AButtonColor:TColor; var AHint:String); virtual;
  131.     function GetDisplayText(AText:String):string; virtual;
  132.     procedure ResetCalculator; virtual;
  133.     property Alignment : TAlignment read GetAlignment write FAlignment default taRightJustify;
  134.     property DisplayFormat : string read FDisplayFormat write FDisplayFormat;
  135.     property DecimalPlacesStored : integer read FDecimalPlacesStored write FDecimalPlacesStored;
  136.     property Value: Double read GetValue write SetValue;
  137.     property CalcOptions: TfcPopupCalcOptions read FCalcOptions write FCalcOptions;
  138.     property AllowNull: boolean read FAllowNull write FAllowNull default False;
  139.     property OnSetCalcButtonAttributes:TfcCalcAttributesEvent read FOnCalcButtonAttributes write FOnCalcButtonAttributes;
  140.     property OnBeforeDropDown: TNotifyEvent read FOnBeforeDropDown write FOnBeforeDropDown;
  141.   end;
  142.   TfcCalcEdit = class(TfcCustomCalcEdit)
  143.   published
  144.     property DisableThemes;
  145.     property CalcOptions;
  146.     {$ifdef fcDelphi4Up}
  147.     property Anchors;
  148.     property Constraints;
  149.     {$endif}
  150.     property AutoSelect;
  151.     property AutoSize;
  152.     property BorderStyle;
  153.     property ButtonEffects;
  154.     property ButtonGlyph;
  155.     property ButtonStyle;
  156.     property ButtonWidth;
  157.     property Color;
  158.     property Ctl3D;
  159.     property DataField;
  160.     property DataSource;
  161.     property DisplayFormat;
  162.     property DragCursor;
  163.     property DragMode;
  164.     property Enabled;
  165.     property Font;
  166.     property Frame;
  167.     property ImeMode;
  168.     property ImeName;
  169.     property InfoPower;
  170.     property MaxLength;
  171.     property ParentColor;
  172.     property ParentCtl3D;
  173.     property ParentFont;
  174.     property ParentShowHint;
  175.     property PopupMenu;
  176.     property ReadOnly;
  177.     property OnSetCalcButtonAttributes;
  178.     property ShowButton;
  179.     property ShowHint;
  180.     property TabOrder;
  181.     property TabStop;
  182.     property Text;
  183.     property Visible;
  184.     property OnBeforeDropDown;
  185.     property OnChange;
  186.     property OnClick;
  187.     {$ifdef fcDelphi5Up}
  188.     property OnContextPopup;
  189.     {$endif}
  190.     property OnDblClick;
  191.     property OnDragDrop;
  192.     property OnDragOver;
  193.     property OnDropDown;
  194.     property OnEndDrag;
  195.     property OnEnter;
  196.     property OnExit;
  197.     property OnKeyDown;
  198.     property OnKeyPress;
  199.     property OnKeyUp;
  200.     property OnMouseEnter;
  201.     property OnMouseLeave;
  202.     property OnMouseDown;
  203.     property OnMouseMove;
  204.     property OnMouseUp;
  205.     property OnStartDrag;
  206.   end;
  207. //procedure Register;
  208. implementation
  209. {procedure TfcCalcPanel.Compute(Sender: TObject);
  210. var
  211.  ch: char;
  212.  ButtonType: TfcCalcButtonType;
  213. begin
  214.   ButtonType := TfcCalcButtonType(TSpeedButton(Sender).Tag);
  215.   case ButtonType of
  216.     bt0..bt9:   ch := TSpeedButton(Sender).Caption[1];
  217.     btDecimal:  ch := '.';
  218.     btPlusMinus: ;
  219.     btClearAll:
  220.       ch := 'C'; //char(vk_escape);
  221.     btClear:    ch := char(vk_back);
  222.     btAdd:      ch:='+';
  223.     btSubtract: ch:='-';
  224.     btDivide:   ch:='/';
  225.     btMultiply: ch:='*';
  226.     btBackSpace:ch:=char(vk_back);
  227.     btInverse:  ch:='r';
  228.     btPercent:  ch:='%';
  229.     btSqrt:     ch:='@';
  230.     btMStore:   ch:='m';
  231.     btMAdd:     ch:='p';
  232.     btMRecall:  ch:='r';
  233.     btMClear:   ch:='l';
  234.     btEquals:   ch:='=';
  235.     else
  236.       ch:=' ';
  237.     end;
  238.     SendMessage(FAssociatedEdit.Handle, WM_CHAR, word(ch), 0);
  239. end;
  240.  }
  241. procedure TfcCalcPanel.Keypress(var Key: Char);
  242. begin
  243.   inherited Keypress(Key);
  244. end;
  245.     constructor TfcPopupCalcOptions.Create(AOwner: TComponent);
  246.     begin
  247.       FBackground := TPicture.Create;
  248.       FMargin := 3;
  249.       FOptions := [];
  250.       FPanelColor := clBtnFace;
  251.     end;
  252.     destructor TfcPopupCalcOptions.Destroy;
  253.     begin
  254.       if FBackGround <> nil then begin
  255.          FBackground.Free;
  256.          FBackground := nil;
  257.       end;
  258.       inherited;
  259.     end;
  260.     procedure TfcPopupCalcOptions.SetBackgroundBitmap(Value: TPicture);
  261.     begin
  262.       FBackground.assign(Value);
  263.     end;
  264.     procedure TfcPopupCalcOptions.SetBackgroundStyle(Value: TfcCalcBitmapDrawStyle);
  265.     begin
  266.       if Value<>FBackgroundStyle then begin
  267.          FBackgroundStyle:= Value;
  268.       end;
  269.     end;
  270.     procedure TfcPopupCalcOptions.SetOptions(Value: TfcCalcOptions);
  271.     begin
  272.       if Value<>FOptions then begin
  273.          FOptions:= Value;
  274.       end;
  275.     end;
  276.     procedure TfcPopupCalcOptions.SetPanelColor(Value: TColor);
  277.     begin
  278.       if Value<>FPanelColor then begin
  279.          FPanelColor:= Value;
  280.       end;
  281.     end;
  282.     procedure TfcPopupCalcOptions.SetMargin(Value: Integer);
  283.     begin
  284.       if Value<>FMargin then begin
  285.          FMargin := Value;
  286.       end;
  287.     end;
  288. procedure TfcCalcPanel.DoCalc(ButtonType:TfcCalcButtonType);
  289. begin
  290.   if FAssociatedEdit.EditCanModify then
  291.   begin
  292.      inherited DoCalc(buttonType);
  293.      FAssociatedEdit.SetModified(True);
  294.      if (cboCloseOnEquals in Options) and (ButtonType=btEquals) then begin
  295.        self.update;
  296.        FAssociatedEdit.Closeup(False);
  297.        abort; //!!!!
  298.      end;
  299.   end;
  300. end;
  301. procedure TfcCalcPanel.CreateParams(var Params: TCreateParams);
  302. begin
  303.   inherited CreateParams(Params);
  304.   with Params do
  305.   begin
  306.     Style := Style or WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN; // ak
  307.     Style := Style or WS_BORDER;
  308.     {$ifdef win32}
  309.     ExStyle := WS_EX_TOOLWINDOW;
  310.     ExStyle := ExStyle or WS_EX_CONTROLPARENT; //ak
  311.     {$endif}
  312.     WindowClass.Style := CS_SAVEBITS;
  313.   end;
  314. end;
  315. constructor TfcCalcPanel.Create(AOwner: TComponent);
  316. begin
  317.    inherited Create(AOwner);
  318.    FAssociatedEdit := TfcCustomCalcEdit(AOwner);
  319.    ControlStyle := ControlStyle + [csReplicatable];
  320.    ControlStyle := ControlStyle + [csNoDesignVisible];
  321.    ControlStyle := ControlStyle + [csReflector];
  322.    Color := clBtnFace;
  323. //   Height := 175;
  324. //   Width := 250;
  325. end;
  326. procedure TfcCalcPanel.CreateWnd;
  327. begin
  328.   inherited CreateWnd;
  329.   Windows.SetParent(Handle, 0);
  330. end;
  331. { TfcCustomCalcEdit }
  332. constructor TfcCustomCalcEdit.Create( aOwner: TComponent );
  333. begin
  334.   inherited Create( aOwner );
  335.   MaxLength := 20;
  336. //  WantReturns := True;
  337.   FCalcOptions := TfcPopupCalcOptions.Create(Self);
  338.   FAllowNull := False;
  339.   FAlignment := taRightJustify;
  340.   FDecimalEntered := False;
  341.   Text:='';
  342. end;
  343. procedure TfcCustomCalcEdit.CreateWnd;
  344. begin
  345.   inherited;
  346. end;
  347. procedure TfcCustomCalcEdit.Loaded;
  348. var f:extended;
  349. begin
  350.   inherited;
  351.   try
  352.     if Text='' then abort;
  353.     f:= fcStrToRealDef(Text,0.0)
  354.   except
  355.     f:=0.0;
  356.   end;
  357.   if (AllowNull = False) and ((Text = '') or (f=0.0)) then begin
  358.      if cboShowDecimal in CalcOptions.Options then
  359.         Text := '0'+decimalseparator
  360.      else Text := '0';
  361.   end;
  362. end;
  363. destructor TfcCustomCalcEdit.Destroy;
  364. begin
  365.   inherited Destroy;
  366.   FCalcOptions.Free;
  367. end;
  368. function TfcCustomCalcEdit.IsBinaryOperator(Key:Char): boolean;
  369. begin
  370.   Result := Key in ['+','-','*','/','%','^','='];
  371. end;
  372. function TfcCustomCalcEdit.IsUnaryOperator(Key:Char): boolean;
  373. begin
  374.   Result := Key in ['@','#','r','n','l',';','!','_'];
  375. end;
  376. function TfcCustomCalcEdit.IsValidOperator(Key:Char): boolean;
  377. begin
  378.   Result := IsBinaryOperator(Key) or IsUnaryOperator(Key) or
  379.             (Key in ['m','p']);
  380. end;
  381. procedure TfcCustomCalcEdit.DoEnter;
  382. begin
  383.   inherited;
  384. //  FClearOnNextKey := True;
  385.   if (Alignment <> taRightJustify) or ((DataLink=nil) or (DataLink.Field = nil))
  386.   then begin
  387.     invalidate;
  388.   end;
  389.   if AutoSelect then selectall
  390.   else selStart := Length(Text);
  391. end;
  392. procedure TfcCustomCalcEdit.DoBeforeDropDown;
  393. begin
  394.   if Assigned(FOnBeforeDropDown) then FOnBeforeDropDown(Self);
  395. end;
  396. procedure TfcCustomCalcEdit.DoExit;
  397. begin
  398.     inherited;
  399.     if (Alignment <> taRightJustify) or ((DataLink=nil) or (DataLink.Field = nil)) then invalidate;
  400. //  FClearOnNextKey := True;
  401.     FDecimalEntered := False;
  402. end;
  403. procedure TfcCustomCalcEdit.ResetCalculator;
  404. begin
  405.   if (AllowNull = False) then begin
  406.      if cboShowDecimal in CalcOptions.Options then
  407.         Text := '0'+decimalseparator
  408.      else Text := '0';
  409.   end
  410.   else Text:='';
  411. //  FClearOnNextKey := True;
  412.   FDecimalEntered := False;
  413.   FSkipTextChangedFlag := False;
  414. end;
  415. procedure TfcCustomCalcEdit.CMTextChanged(var Message: TMessage);
  416. begin
  417.    if FSkipTextChangedFlag then exit;
  418.    inherited;
  419. end;
  420. procedure TfcCustomCalcEdit.KeyUp(var Key: Word; Shift: TShiftState);
  421. begin
  422.   inherited KeyUp(Key, Shift);
  423.   if FDropDownCalc <> nil then begin
  424.      FDropDownCalc.ResultKeyUp(FDropDownCalc,Key,Shift);
  425.   end
  426.   else begin
  427.     //10/1/2001-Added code to determine whether text can be cleared or not.
  428.     if (AllowNull = False) and (Text = '') then begin
  429.       FSkipTextChangedFlag := True;
  430.       if cboShowDecimal in CalcOptions.Options then Text := '0'+decimalseparator
  431.       else Text := '0';
  432.       FSkipTextChangedFlag := False;
  433.       SelectAll;
  434.     end;
  435.   end;
  436. end;
  437. procedure TfcCustomCalcEdit.KeyDown(var Key: Word; Shift: TShiftState);
  438. var c:Char;
  439.   function IsValidDigit(Key:Char): boolean;
  440.   begin
  441.       Result := (key in ['0'..'9',',','.'])
  442.                 or (((ord(key) >= VK_NUMPAD0) and (ord(key) <= VK_NUMPAD9)) or (ord(key)=VK_DECIMAL));
  443.   end;
  444.   function IsValidSpecialChar(Key:Word): boolean;
  445.   begin
  446.       Result := (key=vk_back) or (key=vk_delete) or (key=vk_escape);
  447.   end;
  448. begin
  449.   if FClearOnNextKey and (key in [vk_next,vk_prior,vk_left,vk_right,vk_up,vk_down,vk_f2]) then begin
  450.      if (not (fcIsInwwGrid(Self)) and (not isDroppedDown)) then key:=0;
  451.   end;
  452.   inherited KeyDown(Key, Shift);
  453.   c:=char(Key);
  454.   if Key=vk_Return then
  455.     c := '='
  456.   else if isDroppedDown and (IsValidSpecialChar(Key)) then begin
  457.     if FDropDownCalc <> nil then
  458.        FDropDownCalc.ResultKeyDown(FDropDownCalc,key,shift);
  459.   end
  460.   else begin
  461.     //Code := MapVirtualKey(Key, 2);
  462.     //c:=char(code);
  463.     // 3/1/2002-PYW-Use new function to handle num pad keys in windows 98.
  464.     c := fcMessageCodeToChar( key );
  465.     if c='R' then c:='r'
  466.     else if c='M' then c:='m'
  467.     else if c='P' then c:='p'
  468.     else if (ssShift in Shift) then begin
  469.       case c of
  470.         '=':c:='+';
  471.         '2':c:='@';
  472.         '5':c:='%';
  473.         '8':c:='*';
  474.         '-':c:='_';
  475.       end;
  476.     end;
  477.   end;
  478.   if IsValidOperator(c) or (isValidDigit(c) and isDroppedDown) then begin
  479.      if not isDroppedDown and not ((c='=') and (cboCloseOnEquals in CalcOptions.Options) ) then begin
  480.         if (Text <> '') then begin
  481.           DropDown;
  482.           if (FDropDownCalc <> nil) then begin
  483.              FDropDownCalc.ResultKeyDown(FDropDownCalc,Key,Shift);
  484.              sleep(100);
  485.              FDropDownCalc.ResultKeyUp(FDropDownCalc,Key,Shift);
  486.           end;
  487.         end;
  488. //        FClearOnNextKey := True;
  489.      end
  490.      else begin
  491.        // 2/28/2002-PYW-Make sure calculator gets the equals.  Otherwise in some cases
  492.        //              the clearonnextkey flag in the calculator can get mismatched.
  493.        if (c='=') and (cboCloseOnEquals in CalcOptions.Options) then
  494.        begin
  495.           if not isDroppedDown then SelectAll
  496.           else CloseUp(True)
  497.        end
  498.        else if {((c<>'='))and }(FDropDownCalc <> nil) then
  499.            FDropDownCalc.ResultKeyDown(FDropDownCalc,Key,Shift);
  500. {       if (c='=') then begin
  501.           SelectAll;//SelStart := Length(Text);
  502.           if (cboCloseOnEquals in CalcOptions.Options) then CloseUp(True)
  503.           else begin
  504.              if (FDropDownCalc <> nil) and (Text <> '') then begin
  505.                if ((not FDropDownCalc.LastOperatorEquals)
  506.                  and (FDropDownCalc.LastOp <> btNone)) then begin
  507.                  key := vk_return;
  508.                  FDropDownCalc.ResultKeyDown(FDropDownCalc,key,[]);
  509.                end;
  510.              end;
  511.           end;
  512.        end;}
  513.      end;
  514.      Key := 0;
  515.   end;
  516. (*  if {(key=vk_Delete) or} (key=vk_escape) then begin
  517.        //Clear the displayed number.
  518.       Text := '0';
  519.       //Treat vk_Escape as C key like the windows calculator.
  520.       //The C key clears the current calculation.
  521.       if (FLastOperator = char(#0)) or (key=vk_Escape) then begin
  522.          ResetCalculator;
  523.       end;
  524.       SelectAll;
  525.       Key := 0;
  526.    end;
  527.    //Handle Memory Keys....
  528.    if not (ssCtrl in Shift) or (Text = '') then exit;
  529.    try
  530.      curValue := StrToFloat(Text);
  531.    except
  532.      curValue := 0;
  533.    end;
  534.    if (ssCtrl in Shift) and ((key = ord('M')) or (key=ord('m'))) then
  535.       FMemoryValue := curValue;
  536.    if (ssCtrl in Shift) and ((key = ord('L')) or (key=ord('l'))) then
  537.      FMemoryValue := 0.0;
  538.    if (ssCtrl in Shift) and ((key = ord('P')) or (key=ord('p'))) then
  539.      FMemoryValue := FMemoryValue + CurValue;
  540.    if (ssCtrl in Shift) and ((key = ord('R')) or (key=ord('r'))) then
  541.    begin
  542.      Text := FloatToStr(FMemoryValue);
  543.    end;
  544.    *)
  545. end;
  546. procedure TfcCustomCalcEdit.KeyPress(var Key: Char);
  547. var temp:string;
  548.     prevselstart,startlength:integer;
  549.     testfloat:Extended;
  550.   function IsValidDigit(Key:Char): boolean;
  551.   begin
  552.       Result := (key in ['0'..'9',',','.'])
  553.                 or ((ord(key) >= VK_NUMPAD0) and (ord(key) <= VK_NUMPAD9));
  554.   end;
  555.   function IsValidCalcChar(Key:Char): boolean;
  556.   begin
  557.      result:= isValidDigit(Key) or (key=#13) or
  558.               (key = #8) or (key=#46) or (Key=#27) or
  559.               isValidOperator(Key)
  560.   end;
  561.   function DecimalInStr: boolean;
  562.   begin
  563.     result := false;
  564.     if Pos(DecimalSeparator,Text)>0 then
  565.        result := true;
  566.   end;
  567.     function getfstr(val:extended):string;
  568.     var s,fmtstr:string;
  569.           i,places:integer;
  570.     begin
  571.         if Frac(val)=0 then //(Val - Trunc(Val)) = 0.0 then
  572.            result := FormatFloat('#,##0',Val)
  573.         else begin
  574.            // Limit to 15 significant digits
  575.            s:= FloatToStrF(Val, ffFixed, 15, 15);
  576.            // Now val is accurate to 15 digits precision, so now lets get it in our format
  577.            Val:= StrtoFloat(s);
  578.            s:= FormatFloat('#.##############', Val);
  579.            places := length(s)-pos(DecimalSeparator,S);
  580.            fmtstr := '#,##0.';
  581.            for i:=1 to places do
  582.               fmtstr := fmtstr+'0';
  583.            result := FormatFloat(fmtstr,Val);
  584.         end;
  585.     end;
  586. begin
  587.   inherited KeyPress(Key);
  588.   //2/28/2002 - Clear DecimalEntered if Text Selected.
  589.   if SelLength > 0 then
  590.   begin
  591.      FDecimalEntered := False;
  592.      if (key<>#13) and ((cboCloseOnEquals in CalcOptions.Options) and (key<>'=')) then SelText:='';  //8/15/2002
  593.   end;
  594.   //8/15/2002 - Make sure FDecimalEntered is False if there is no Decimal in the String.
  595.   if not DecimalInStr then
  596.      FDecimalEntered := False;
  597.   if isDroppedDown then begin
  598.     if (Key<>#0) then SetModified(True) { RSW };
  599.     key:=#0;
  600.     exit;
  601.   end;
  602.   case Key of
  603.     '.',',':
  604.         if (Key='.') or (Key=',') then begin
  605.            if FClearOnNextKey then begin
  606.               FSkipTextChangedFlag := True;
  607.               Text:='';
  608.               FSkipTextChangedFlag := False;
  609.               FClearOnNextKey := False;
  610.               FDecimalEntered := False;
  611.            end;
  612.             //10/01/2001-Added check to see if current value is 0 then start text with 0 followed by decimal
  613.            if (not FDecimalEntered) {or (not DecimalInStr)} or (fcstrtofloat(text) = 0.0) then begin
  614.               FDecimalEntered := True;
  615.               if (Text = '') or (fcstrtofloat(text) = 0.0) then begin
  616.                  Text := '0'+decimalseparator;
  617.                  SelStart := Length(Text);
  618.                  Key := #0;
  619.               end
  620.               else begin
  621.                  if not Decimalinstr then Key := DecimalSeparator
  622.                  else begin
  623.                     selstart := Length(Text);
  624.                     Key:=#0;
  625.                  end;
  626.                  if False and  (cboDigitGrouping in CalcOptions.Options) then begin
  627.                      prevselstart:=selstart;
  628.                      temp := Copy(Text,1,selstart)+Key+Copy(Text,selstart+sellength+1,length(text)-(selstart+SelLength));
  629.                      FSkipTextChangedFlag := True;
  630.                      if not ((DecimalInStr) and ((Key = '0') or (Key=#96))) then begin
  631.                         startlength := length(Temp);
  632.                         Text := getfstr(fcStrToFloat(Temp))
  633.                      end
  634.                      else Text := Text+'0';
  635.                      SetModified(True);
  636.                      SelStart := prevselstart+1;//length(Text);
  637.                      if startlength <> length(Text) then selstart := selstart+1;
  638.                      FSkipTextChangedFlag := False;
  639.                      Key:=#0;
  640.                  end
  641.               end;
  642.            end
  643.            else begin
  644.               Key := #0;
  645.               Beep;
  646.            end;
  647.         end;
  648.     #8: begin
  649.             if (cboDigitGrouping in CalcOptions.Options) then begin
  650.                prevselstart:=selstart;
  651.                temp := Copy(Text,1,selstart-1)+Copy(Text,selstart+sellength+1,length(text)-(selstart+SelLength));
  652.                FSkipTextChangedFlag := True;
  653.                if (AnsiPos(DecimalSeparator,Temp)> 0) and
  654.                   (AnsiPos(DecimalSeparator,Temp)< selstart) then Text := Temp
  655.                else begin
  656.                   Text := getfstr(fcStrToFloat(temp));
  657.                   DecimalEntered := False;
  658.                end;
  659.                FSkipTextChangedFlag := True;
  660.                SelStart := prevSelStart-1;
  661.                if SelStart=0 then selstart := 1;
  662.                SetModified(True);
  663.                Key:=#0;
  664.             end;
  665.             //2/28/2002 - PYW - Add checks to make sure FDecimalEntered is cleared.
  666.             if (sellength=0) and (Copy(Text,Length(Text),1) = DecimalSeparator) then
  667.                FDecimalEntered := False;
  668.             if (not (DecimalinStr)) then begin
  669.               if (cboShowDecimal in CalcOptions.Options) then begin
  670.                 Text := Text+DecimalSeparator;
  671.                 selstart:=Length(Text)-1;
  672.               end;
  673.               FDecimalEntered := False;
  674.             end;
  675.         end;
  676. {    #46:begin
  677.             if True or (cboGrouping in CalcOptions.Options) then begin
  678.                prevselstart:=selstart;
  679.                temp := Copy(Text,1,selstart)+Copy(Text,selstart+sellength+1,length(text)-(selstart+SelLength));
  680.                FSkipTextChangedFlag := True;
  681.                Text := getfstr(fcStrToFloat(temp));
  682.                FSkipTextChangedFlag := True;
  683.                SelStart := prevSelStart;
  684.                SetModified(True);
  685.                Key:=#0;
  686.             end
  687.         end;}
  688.     '0'..'9':
  689.         begin
  690.             if FClearOnNextKey then begin
  691.                FSkipTextChangedFlag := True;
  692.                Text := '';
  693.                FDecimalEntered := False;
  694.                FSkipTextChangedFlag := False;
  695.             end;
  696.             FClearOnNextKey := false;
  697.             if (cboDigitGrouping in CalcOptions.Options) then begin
  698.                prevselstart:=selstart;
  699.                temp := Copy(Text,1,selstart)+Key+Copy(Text,selstart+sellength+1,length(text)-(selstart+SelLength));
  700.                if not fcStrToFloat2(temp, testFloat,'') then begin
  701.                  Key:=#0;
  702.                  exit;
  703.                end;
  704.                FSkipTextChangedFlag := True;
  705.                //12/12/2001-Handle additional Decimal cases when cboShowDecimal in Options.
  706.                if ((cboShowDecimal in CalcOptions.options)and not DecimalEntered) then begin
  707.                   if (selstart = length(Text)) and (DecimalSeparator = Copy(Text,selstart,1)) then begin
  708.                     Text := Text+Key;
  709.                     startlength:=length(Temp);
  710.                   end
  711.                   else begin
  712.                     startlength := length(Temp);
  713.                     Text := getfstr(fcStrToFloat(Temp))
  714.                   end;
  715.                end
  716.                else if (not ((DecimalInStr) and ((Key = '0') or (Key=#96)))) then begin
  717.                   startlength := length(Temp);
  718.                   Text := getfstr(fcStrToFloat(Temp))
  719.                end
  720.                else begin
  721.                   Text := Text+'0';
  722.                   startlength:=length(Temp);
  723.                end;
  724.                SetModified(True);
  725.                SelStart := prevselstart+1;//length(Text);
  726.                if startlength <> length(Text) then selstart := selstart+1;
  727.                FSkipTextChangedFlag := False;
  728.                Key:=#0;
  729.             end;
  730.             if (not (DecimalinStr)) then begin
  731.               FDecimalEntered := False;
  732.               if (cboShowDecimal in CalcOptions.Options) then begin
  733.                 Text := Text+DecimalSeparator;
  734.                 selstart:=Length(Text)-1;
  735.               end;
  736.             end;
  737.          end;
  738. {    'C': // Clear on 'C' character
  739. //    #27,#47:
  740.         begin
  741.            //If a vk_Escape (C) or a vk_delete (CE) was pressed the text needs to be reset to zero.
  742.            //Clear the displayed number.
  743.            ResetCalculator;
  744.            Text := '0';
  745.            //Treat vk_Escape as C key like the windows calculator.
  746.            //The C key clears the current calculation.
  747.            //if ord(key)=vk_Escape then
  748.            SelectAll;
  749.            Key := #0;
  750.         end}
  751.       else
  752.       begin
  753.          Key:=#0;
  754.       end;
  755.    end;
  756.    if (Key<>#0) then SetModified(True) { RSW };
  757. end;
  758. procedure TfcCustomCalcEdit.SetValue(Value:Double);
  759.     function getfstr(val:extended):string;
  760.     var s,fmtstr:string;
  761.           i,places:integer;
  762.     begin
  763.         if Frac(val)=0 then //(Val - Trunc(Val)) = 0.0 then
  764.            result := FormatFloat('#,##0',Val)
  765.         else begin
  766.            // Limit to 15 significant digits
  767.            s:= FloatToStrF(Val, ffFixed, 15, 15);
  768.            // Now val is accurate to 15 digits precision, so now lets get it in our format
  769.            Val:= StrtoFloat(s);
  770.            s:= FormatFloat('#.##############', Val);
  771.            places := length(s)-pos(DecimalSeparator,S);
  772.            fmtstr := '#,##0.';
  773.            for i:=1 to places do
  774.               fmtstr := fmtstr+'0';
  775.            result := FormatFloat(fmtstr,Val);
  776.         end;
  777.     end;
  778. begin
  779.   if GetValue <> Value then begin
  780.      if Focused then begin
  781.         if (cboDigitGrouping in CalcOptions.Options) then
  782.            Text := getfstr(Value)
  783.         else Text := FloatToStr(Value);             // Maybe use ---> s:= FormatFloat('#.################', Val);
  784.      end
  785.      else begin
  786. //        Text := FormatFloat(displayFormat,value);
  787.         Text := FormatFloat('',value);
  788.      end;
  789.   end;
  790. end;
  791. function TfcCustomCalcEdit.GetValue: Double;
  792. begin
  793.   Result := fcStrToFloat( Text );
  794. end;
  795. procedure TfcCustomCalcEdit.CreateParams(var Params: TCreateParams);
  796. begin
  797.   inherited CreateParams(Params);
  798.   Params.Style :=(Params.Style and not (ES_AUTOVSCROLL or ES_WANTRETURN) or
  799.                    WS_CLIPCHILDREN);
  800. //  if UseRightToLeftAlignment or LimitEditRect then
  801. //  Params.Style:= Params.Style or ES_MULTILINE;
  802.   Params.Style:= Params.Style or ES_WANTRETURN;
  803.   Params.ExStyle := Params.ExStyle or WS_EX_RIGHT;
  804. end;
  805. function TfcCustomCalcEdit.IsDroppedDown: Boolean;
  806. begin
  807.   result := (fDropDownCalc<>nil) and fDropDownCalc.Visible;
  808. end;
  809. procedure TfcCustomCalcEdit.CMCancelMode(var Message: TCMCancelMode);
  810. begin
  811.   if (Message.Sender <> Self) and (Message.Sender <> fDropDownCalc) and
  812.      (Message.Sender <> Button) and (Message.Sender.Parent <> fDropDownCalc) then
  813.     CloseUp(True);
  814. end;
  815. procedure TfcCustomCalcEdit.DropDown;
  816. var
  817.   P: TPoint;
  818.   X, Y: Integer;
  819.   WinAttribute: HWnd;
  820.   f:extended;
  821.   function GetDeskTopHeight:Integer;
  822.      var Rect1:TRect;
  823.   begin
  824.       if SystemParametersInfo(SPI_GETWORKAREA,0,@Rect1,0) Then
  825.          GetDeskTopHeight:=Rect1.Bottom-Rect1.Top
  826.       else
  827.          GetDeskTopHeight:=Screen.Height;
  828.   end;
  829. begin
  830.   DoBeforeDropdown;
  831.   if (fDropDownCalc <> nil) then exit;
  832. {  if wwCalcHook=0 then
  833.       wwCalcHook := SetWindowsHookEx(WH_MOUSE, @wwCalcHookProc, HINSTANCE, GetCurrentThreadID);
  834.  }
  835.   CalcOptions.Options:= CalcOptions.Options + [cboHideEditor{,cboShowDecimal,cboDigitGrouping}];
  836.   fDropDownCalc := TfcCalcPanel.Create(self);
  837.   fDropDownCalc.Visible := False;
  838.   fDropDownCalc.Height := 175;
  839.   fDropDownCalc.OnSetButtonAttributes := DoCalcButtonAttributes;
  840.   if cboSimpleCalc in CalcOptions.Options then
  841.      fDropDownCalc.Width := 148
  842.   else fDropDownCalc.Width := 250;
  843.   fDropDownCalc.Parent := Self;
  844.   FDropDownCalc.CalcEdit := self;
  845.   try
  846.     if Text='' then abort;
  847.     f:= fcStrToFloat(Text);
  848.   except
  849.     f:=0.0;
  850.   end;
  851.   if (f=0.0) or (fdropdowncalc.Text = '') then begin
  852.     if cboShowDecimal in CalcOptions.Options then fDropDownCalc.Text := '0'+decimalseparator
  853.     else fDropDownCalc.Text := '0';
  854.   end;
  855.   if CalcOptions.background <> nil then begin
  856.      fDropDownCalc.BackgroundBitmapDrawStyle := CalcOptions.BackgroundStyle;
  857.      fDropDownCalc.BackgroundBitmap.Assign(CalcOptions.Background);
  858.   end;
  859.   fDropDownCalc.PanelColor := CalcOptions.PanelColor;
  860.   fDropDownCalc.Options := CalcOptions.Options;
  861.   fDropDownCalc.ButtonMargin := CalcOptions.ButtonMargin;
  862.   P := Parent.ClientToScreen(Point(Left, Top));
  863.   Y := P.Y + Height - 1;
  864.   if BorderStyle = bsNone then y:= y + 1;
  865.   { 11/28/2000 - PYW - Check based on actual work area. }
  866.    if Y + fDropDownCalc.Height > GetDeskTopHeight then Y := P.Y - fDropDownCalc.Height;
  867.    { 4/1/97 - Expand list to left since it goes past edge of screen }
  868.    P.X := P.X+Width-1-FDropDownCalc.width;
  869.    X := P.X;
  870.    if P.X < 0 then X := 0;
  871.    if P.X + fDropDownCalc.Width >= Screen.Width then X := Screen.Width-FDropDownCalc.Width;
  872.    try  //10/15/01 - Uncommented to allow dropdown event to be called.
  873.       Update;
  874.       FDecimalEntered := False;
  875.       DoDropDown;
  876.    except
  877.       exit;
  878.    end;
  879.    { 3/13/97 - Always Top so that drop-down is not hidden under taskbar}
  880.    WinAttribute:= HWND_TOPMOST;
  881.    SetWindowPos(fDropDownCalc.Handle, WinAttribute, X, Y, 0, 0,
  882.      SWP_NOSIZE or SWP_NOACTIVATE or SWP_SHOWWINDOW);
  883.    fDropDownCalc.visible:= true;
  884.    if FDropdownCalc.StatusLabel <> nil then
  885.       FDropDownCalc.StatusLabel.Caption := Text;
  886.    Windows.SetFocus(Handle);
  887.    Windows.HideCaret(Handle); // Don't show care thwne calculator dropped down
  888. {   if not inAutoDropDown then DoSelectAll;
  889.    if Editable then ShowCaret(Handle);
  890.    LastShowHint:= ShowHint;
  891.    ShowHint:= False;
  892.    Invalidate;      }
  893. end;
  894. {procedure TfcCustomCalcEdit.SetCalcOptions(Value: TfcPopupCalcOptions);
  895. begin
  896.   if FCalcOptions <> Value then
  897.     FCalcOptions := Value;
  898. end;}
  899. procedure TfcCustomCalcEdit.CloseUp(Accept: Boolean);
  900. var IsDroppedDown: Boolean;
  901.     key:word;
  902. begin
  903.   if Accept then begin
  904.      if (FDropDownCalc <> nil) and (Text <> '') then begin
  905.         if ((not FDropDownCalc.LastOperatorEquals) {and (FDropDownCalc.LastOp <> btPercent)})
  906.            and (FDropDownCalc.LastOp <> btNone) then begin
  907.           key := vk_return;
  908.           FDropDownCalc.ResultKeyDown(FDropDownCalc,key,[]);
  909.         end;
  910.      end;
  911.   end;
  912.   IsDroppedDown := self.IsDroppedDown;
  913.   inherited;
  914.   if IsDroppedDown then
  915.     try
  916.       if fDropDownCalc = nil then exit
  917.       else begin
  918.         fDropDownCalc.Free;
  919.         fDropDownCalc := nil;
  920.       end;
  921.       DoCloseUp(Accept);
  922.     finally
  923.        SetFocus;
  924.        if Editable then begin
  925.          SelectAll;
  926.          Windows.ShowCaret(Handle);
  927.        end;
  928.     end;
  929. end;
  930. //10/1/2001-PYW-Added handling for WMCut and WMPaste.
  931. procedure TfcCustomCalcEdit.WMCut(var Message: TMessage);
  932. begin
  933.   if not EditCanModify then exit;
  934.   inherited;
  935.   SetModified(True);
  936.   if (AllowNull = False) and (Text = '') then begin
  937.      if cboShowDecimal in CalcOptions.Options then Text := '0'+decimalseparator
  938.      else Text := '0';
  939.      SelectAll;
  940.   end;
  941. end;
  942. procedure TfcCustomCalcEdit.WMPaste(var Message: TMessage);
  943. var prevText: string;
  944.     prevSelStart: integer;
  945.     f:extended;
  946. begin
  947.   PrevText:= Text;
  948.   PrevSelStart:= selStart;
  949.   if not EditCanModify then exit;
  950.   inherited;
  951.   SetModified(True);
  952.   if (selStart=0) then selStart:= prevSelStart + length(Text) - length(PrevText);
  953.   try
  954.     if Text='' then abort;
  955.     f:= fcStrToRealDef(Text,0.0)
  956.   except
  957.     f:=0.0;
  958.   end;
  959.   if (AllowNull = False) and ((Text = '') or (f=0.0)) then begin
  960.      if cboShowDecimal in CalcOptions.Options then Text := '0'+decimalseparator
  961.      else Text := '0';
  962.      SelectAll;
  963.   end;
  964. end;
  965. procedure TfcCustomCalcEdit.DoCalcButtonAttributes(Calc: TfcCalculator;var AType:TfcCalcButtonType;
  966.   var ACaption:String; var AFontColor:TColor; var AButtonColor:TColor; var AHint:String);
  967. begin
  968.   if DropDownControl <> nil then
  969.      if Assigned(FOnCalcButtonAttributes) then
  970.         FOnCalcButtonAttributes(self,AType,ACaption,AFontColor,AButtonColor,AHint);
  971. end;
  972. function TfcCustomCalcEdit.GetAlignment:TAlignment;
  973. begin
  974.   result := FAlignment;
  975.   if (DataLink<> nil) and (DataLink.Field <> nil) then
  976.      result := DataLink.Field.Alignment;
  977. end;
  978. procedure TfcCustomCalcEdit.UpdateData(Sender: TObject);
  979. begin
  980.   if DataLink.Field.Value <> Value then
  981.      DataLink.Field.Value := Value;
  982. end;
  983. function TfcCustomCalcEdit.GetDropDownControl: TWinControl;
  984. begin
  985.    result:= fDropDownCalc
  986. end;
  987. function TfcCustomCalcEdit.GetDropDownContainer: TWinControl;
  988. begin
  989.    result:= fDropDownCalc
  990. end;
  991. function TfcCustomCalcEdit.GetItemCount: Integer;
  992. begin
  993.   result := 0;
  994. end;
  995. function TfcCustomCalcEdit.GetItemSize: TSize;
  996. begin
  997.   result := fcSize(0, 0);
  998. end;
  999. // Added function to compute what text should be displayed based on DisplayFormat.
  1000. function TfcCustomCalcEdit.GetDisplayText(AText:String):string;
  1001. begin
  1002.   if (DataLink<>nil) and (Datalink.Field<>nil) then begin
  1003.      if DisplayFormat <> '' then
  1004.         result := FormatFloat(DisplayFormat,Datalink.Field.AsFloat)
  1005.      else result := Datalink.Field.DisplayText;
  1006.   end
  1007.   else if (DisplayFormat <> '') then
  1008. //     result := FormatFloat(DisplayFormat,fcStrToRealDef(AText,0.0))
  1009.      result := FormatFloat(DisplayFormat,fcStrToFloat(AText,DisplayFormat))
  1010.   else result := AText;
  1011. end;
  1012. function TfcCustomCalcEdit.SkipInheritedPaint : boolean;
  1013. begin
  1014.    result := (not FFocused) or (csPaintCopy in ControlState) or
  1015.              (FFocused and (DataLink <>nil) and (Datalink.Field<>nil));
  1016. end;
  1017. procedure TfcCustomCalcEdit.Paint;
  1018. begin
  1019.   PaintToCanvas(Canvas, GetClientEditRect, True, False, Text);
  1020. end;
  1021. //procedure PaintToCanvas(ACanvas: TCanvas; Rect: TRect; Highlight, GridPaint: Boolean;
  1022. //      Text: string); override;
  1023. procedure TfcCustomCalcEdit.PaintToCanvas(Canvas: TCanvas; Rect: TRect;
  1024.   Highlight, GridPaint: Boolean; aText: string);
  1025. var OldBkMode: Integer;
  1026.     Flags: UINT;
  1027.     TempRect:TRect;
  1028.     OldBkColor:TColor;
  1029.     function GetTextRect:TRect;
  1030.     begin
  1031.        result := Classes.Rect(Rect.Left + GetLeftIndent + 2,
  1032.                               Rect.Top + 2,
  1033.                               Rect.Right,Rect.Bottom);
  1034.        {$ifdef fcDelphi4Up}
  1035.        if fcIsInwwObjectView(self) then begin
  1036.           result.Top:= result.Top -1;
  1037.           result.Left:= result.Left -1; // 1/29/01
  1038.        end;
  1039.        {$endif}
  1040.       if (not fcIsInwwObjectView(self)) and
  1041.          Frame.IsFrameEffective then
  1042.       begin
  1043.          Frame.GetFrameTextPosition(result.Left, result.top, FFocused);
  1044.          result.left:= result.Left + GetLeftIndent + 1;
  1045.          if AlignmentVertical = fcavCENTER then result.top:= result.Top -1;
  1046.       end
  1047.     end;
  1048.   function DrawHighlight:boolean;
  1049.   begin
  1050.      result := ((not Editable and Focused) or fcParentGridFocused(Self));
  1051.      if csPaintCopy in ControlState then result:= False;
  1052.   end;
  1053.   procedure PaintText;
  1054.   begin
  1055.     flags := DT_TOP or DT_SINGLELINE;
  1056.     case Alignment of
  1057.       taLeftJustify: Flags := Flags or DT_LEFT;
  1058.       taRightJustify:  Flags := Flags or DT_RIGHT;
  1059.       taCenter:  Flags := Flags or DT_CENTER;
  1060.     end;
  1061.     TempRect := GetTextRect;
  1062.     temprect.right := Temprect.right-3;  //10/04/2001-????
  1063.     if not fcIsInwwGrid(self) then begin
  1064.        TempRect.left:= TempRect.left - 1;
  1065.        TempRect.Top:= TempRect.Top - 1;
  1066.     end
  1067.     else if fcIsClass(parent.classtype, 'TwwDBGrid') then
  1068.     begin
  1069.        if not (dgRowLines in fcGetGridOptions(self)) then TempRect.Top:= TempRect.Top -1;
  1070.     end;
  1071.     if Frame.IsFrameEffective then begin  //10/04/2001-????
  1072. //       temprect.right := Temprect.right+1;
  1073.        temprect.top := Temprect.top+1;
  1074.     end;
  1075.     if fcIsInwwObjectViewPaint(self) or
  1076.        (IsTransparentEffective and not FFocused) or fcIsInwwGridPaint(self) then
  1077.        SetBkMode(Canvas.Handle, TRANSPARENT)
  1078.     else
  1079.        SetBkMode(Canvas.Handle, OPAQUE);
  1080.     if (not FFocused) and IsTransparentEffective and (Frame.NonFocusTransparentFontColor<>clNone) then
  1081.         Canvas.Font.Color:= Frame.NonFocusTransparentFontColor;
  1082.     // 8/1/02
  1083.     if (not IsTransparentEffective) and (not fcIsInwwGridPaint(self)) then
  1084.       if (not FFocused) and (Frame.Enabled) and (Frame.NonFocusColor<>clNone) then
  1085.          Canvas.Brush.Color:= Frame.NonFocusColor;
  1086.     // 3/1/2002 - Enabled Inplace Edit so that end-user can modify an existing number.  Modified behavior to
  1087.     //            paint focused text without special formatting characters for ease of calculation and natural
  1088.     //            use by end-user.
  1089.     if FFocused and (DataLink<>nil) and (Datalink.Field<>nil) then
  1090.         aText := FloatToStr(Value)
  1091.     else aText := GetDisplayText(aText);  //10/5/2001-DisplayText based on displayformat
  1092.     DrawText(Canvas.Handle,PChar(aText),Length(aText),TempRect,Flags);
  1093.   end;
  1094.   function PaintCopyOutsideGrid: boolean;
  1095.   begin
  1096.      result:= not
  1097.        ((not fcIsInwwGrid(self)) and (not (csPaintcopy in ControlState)))
  1098.   end;
  1099. begin
  1100.   OldBkColor := GetBkColor(Canvas.Handle);
  1101.   OldBkMode := GetBkMode(Canvas.Handle);
  1102.   Canvas.Font := Font; { 7/8/99 - Fixes problem where font not set for csPaintCopy }
  1103.   if (not enabled) and (color<>clGrayText) then { 3/7/00 - Use disablec color }
  1104.      Canvas.font.color:= clGrayText;
  1105.   try
  1106.      // Draw Highlight rect with focus rect
  1107.      if (csPaintCopy in ControlState) or // 1/31/01
  1108.         (fcIsInwwGrid(self) and (not Focused or not Highlight)) then
  1109.      begin
  1110.         if not fcIsInwwGrid(self) then Rect.Right := BtnParent.Left-1;
  1111.         // Draw Background in the Highlight color and surround it with a focus rect
  1112.         if (not fcIsInwwGrid(self)) or (not GridPaint) then
  1113.            Canvas.Brush.Color := fcThisThat(Highlight and (DrawHighlight or Not PaintCopyOutsideGrid), clHighlight, self.Color);
  1114.         if (not IsTransparentEffective) and not fcIsInwwObjectViewPaint(self) and
  1115.            not (fcIsInwwGridPaint(self)) then Canvas.FillRect(Rect);
  1116.         if (not GridPaint) and Highlight and (DrawHighlight or Not PaintCopyOutsideGrid) then
  1117.         begin
  1118.            SetBkColor(Canvas.Handle, ColorToRGB(clHighlightText));
  1119.            SetTextColor(Canvas.Handle, ColorToRGB(clHighlight));
  1120.            Canvas.DrawFocusRect(Rect);
  1121.         end;
  1122.         // Draw the text
  1123.         if not fcIsInwwGrid(self) or (not GridPaint) then begin
  1124.            SetBkMode(Canvas.Handle, TRANSPARENT);
  1125.            SetBkColor(Canvas.Handle, ColorToRGB(fcThisThat(Highlight and (DrawHighlight or Not PaintCopyOutsideGrid), clHighlight, clWindow)));
  1126.            SetTextColor(Canvas.Handle, ColorToRGB(fcThisThat(Highlight and (DrawHighlight or Not PaintCopyOutsideGrid), clWindow, Font.Color)));
  1127.         end;
  1128.         PaintText;
  1129.      end
  1130.      else if not fcisinwwGrid(Self) and (not FFocused) and
  1131.        ((csPaintCopy in ControlState) or True{Frame.IsFrameEffective}) then begin
  1132.         Canvas.Brush.Color := Color;  //1/21/2002 - Color not set when control loses focus.
  1133.         PaintText;
  1134.      end;
  1135.      if Frame.IsFrameEffective then
  1136.      begin
  1137.        DrawFrame(Canvas);
  1138.      end;
  1139.   finally
  1140.      SetBkMode(Canvas.Handle,OldBkMode);
  1141.      SetBkColor(Canvas.Handle, OldBkColor);
  1142.   end;
  1143. end;
  1144. function TfcCustomCalcEdit.GetEditRect: TRect;
  1145. begin
  1146.   result:= inherited GetEditRect;
  1147.   if Frame.IsFrameEffective then
  1148.      inc(result.right, +1);
  1149. end;
  1150. // Select all when gettin focus
  1151. procedure TfcCustomCalcEdit.CMEnter(var Message: TCMEnter);
  1152. begin
  1153.   inherited;
  1154. {  FSkipTextChangedFlag := True;
  1155.   Text := FloatToStr(Value);
  1156.   FSkipTextChangedFlag := False;}
  1157.   if autoselect then SelectAll;
  1158. end;
  1159. procedure TfcCustomCalcEdit.DataChange(Sender: TObject);
  1160. begin
  1161.   if DataLink.Field <> nil then
  1162.   begin
  1163.     if not (csDesigning in ComponentState) then
  1164.     begin
  1165.       if (DataLink.Field.DataType = ftString) and (MaxLength = 0) then
  1166.         MaxLength := DataLink.Field.Size;
  1167.     end;
  1168. // 3/1/2002 - Enabled Inplace Edit so that end-user can modify an existing number.  Modified behavior to
  1169. //            paint focused text without special formatting characters for ease of calculation and natural
  1170. //            use by end-user.
  1171.     if Focused and DataLink.CanModify then begin
  1172.       if DataLink.Field.Text <> '' then //3/11/2002 - PYW - Handle Null Case in new DataChange procedure.
  1173.          Text:=  floatToStr(fcStrToFloat(DataLink.Field.Text ))
  1174.       else Text := '';
  1175.     end
  1176.     else begin
  1177.       Text := DataLink.Field.DisplayText;
  1178.     end;
  1179.   end else
  1180.   begin
  1181.     if csDesigning in ComponentState then
  1182.       Text := Name else
  1183.       Text := '';
  1184.   end;
  1185. end;
  1186. {
  1187. procedure Register;
  1188. begin
  1189.   RegisterComponents('Samples', [TfcCustomCalcEdit]);
  1190. end;
  1191. }
  1192. end.