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

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************************}
  2. {                                                                   }
  3. {       Almediadev Visual Component Library                         }
  4. {       BusinessSkinForm                                            }
  5. {       Version 2.90                                                }
  6. {                                                                   }
  7. {       Copyright (c) 2000-2004 Almediadev                          }
  8. {       ALL RIGHTS RESERVED                                         }
  9. {                                                                   }
  10. {       Home:  http://www.almdev.com                                }
  11. {       Support: support@almdev.com                                 }
  12. {                                                                   }
  13. {*******************************************************************}
  14. unit bscalc;
  15. interface
  16. uses Windows, SysUtils, {$IFDEF VER 140}Variants,{$ENDIF}
  17.      {$IFDEF VER 150}Variants,{$ENDIF}
  18.   Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Menus,
  19.   ExtCtrls, Buttons, bsSkinCtrls, Clipbrd, BusinessSkinForm, bsSkinData,
  20.   bsSkinBoxCtrls;
  21. const
  22.   DefCalcPrecision = 15;
  23. type
  24.   TbsCalcState = (csFirst, csValid, csError);
  25.   TbsCalculatorForm = class;
  26. { TbsSkinCalculator }
  27.   TbsSkinCalculator = class(TComponent)
  28.   private
  29.     FAlphaBlend: Boolean;
  30.     FAlphaBlendAnimation: Boolean;
  31.     FAlphaBlendValue: Byte;
  32.     FSD: TbsSkinData;
  33.     FCtrlFSD: TbsSkinData;
  34.     FButtonSkinDataName: String;
  35.     FDisplayLabelSkinDataName: String;
  36.     FDefaultFont: TFont;
  37.     FValue: Double;
  38.     FTitle: String;
  39.     FMemory: Double;
  40.     FPrecision: Byte;
  41.     FBeepOnError: Boolean;
  42.     FHelpContext: THelpContext;
  43.     FCalc: TbsCalculatorForm;
  44.     FOnChange: TNotifyEvent;
  45.     FOnCalcKey: TKeyPressEvent;
  46.     FOnDisplayChange: TNotifyEvent;
  47.     function GetDisplay: Double;
  48.     function GetTitle: string;
  49.     procedure SetTitle(const Value: string);
  50.     procedure SetDefaultFont(Value: TFont);
  51.     function TitleStored: Boolean;
  52.   protected
  53.     procedure Change; dynamic;
  54.     procedure CalcKey(var Key: Char); dynamic;
  55.     procedure DisplayChange; dynamic;
  56.     procedure Notification(AComponent: TComponent;  Operation: TOperation); override;
  57.   public
  58.     constructor Create(AOwner: TComponent); override;
  59.     destructor Destroy; override;
  60.     function Execute: Boolean;
  61.     property CalcDisplay: Double read GetDisplay;
  62.     property Memory: Double read FMemory;
  63.   published
  64.     property AlphaBlend: Boolean read FAlphaBlend write FAlphaBlend;
  65.     property AlphaBlendAnimation: Boolean
  66.       read FAlphaBlendAnimation write FAlphaBlendAnimation;
  67.     property AlphaBlendValue: Byte read FAlphaBlendValue write FAlphaBlendValue;
  68.     property SkinData: TbsSkinData read FSD write FSD;
  69.     property CtrlSkinData: TbsSkinData read FCtrlFSD write FCtrlFSD;
  70.     property ButtonSkinDataName: String
  71.       read FButtonSkinDataName write FButtonSkinDataName;
  72.     property DisplayLabelSkinDataName: String
  73.       read FDisplayLabelSkinDataName write FDisplayLabelSkinDataName;
  74.     property DefaultFont: TFont read FDefaultFont write SetDefaultFont;  
  75.     property BeepOnError: Boolean read FBeepOnError write FBeepOnError default True;
  76.     property HelpContext: THelpContext read FHelpContext write FHelpContext default 0;
  77.     property Precision: Byte read FPrecision write FPrecision default DefCalcPrecision;
  78.     property Title: string read GetTitle write SetTitle stored TitleStored;
  79.     property Value: Double read FValue write FValue;
  80.     property OnCalcKey: TKeyPressEvent read FOnCalcKey write FOnCalcKey;
  81.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  82.     property OnDisplayChange: TNotifyEvent read FOnDisplayChange write FOnDisplayChange;
  83.   end;
  84. { TbsCalculatorForm }
  85.   TbsCalculatorForm = class(TForm)
  86.   private
  87.     procedure FormKeyPress(Sender: TObject; var Key: Char);
  88.   protected
  89.     procedure OkClick(Sender: TObject);
  90.     procedure CancelClick(Sender: TObject);
  91.     procedure CalcKey(Sender: TObject; var Key: Char);
  92.     procedure DisplayChange(Sender: TObject);
  93.   public
  94.     BSF: TbsBusinessSkinForm;
  95.     FCalcPanel: TbsSkinPanel;
  96.     FDisplayLabel: TbsSkinLabel;
  97.     constructor Create(AOwner: TComponent); override;
  98.   end;
  99.   TbsSkinCalcEdit = class;
  100.   TbsPopupCalculatorForm = class(TbsSkinPanel)
  101.   protected
  102.     procedure WMMouseActivate(var Message: TMessage); message WM_MOUSEACTIVATE;
  103.     procedure CreateParams(var Params: TCreateParams); override;
  104.     procedure OkClick(Sender: TObject);
  105.     procedure CancelClick(Sender: TObject);
  106.   public
  107.     CalcEdit: TbsSkinCalcEdit;
  108.     FCalcPanel: TbsSkinPanel;
  109.     FDisplayLabel: TbsSkinLabel;
  110.     constructor Create(AOwner: TComponent); override;
  111.     destructor Destroy; override;
  112.     procedure Show(X, Y: Integer);
  113.     procedure Hide;
  114.   end;
  115.   TbsSkinCalcEdit = class(TbsSkinCustomEdit)
  116.   private
  117.     FMemory: Double;
  118.     FPrecision: Byte;
  119.     FCalc: TbsPopupCalculatorForm;
  120.     StopCheck, FromEdit: Boolean;
  121.     FDecimal: Byte;
  122.     FMinValue, FMaxValue, FIncrement: Double;
  123.     FValueType: TbsValueType;
  124.     FValue: Double;
  125.     FCalcButtonSkinDataName: String;
  126.     FCalcDisplayLabelSkinDataName: String;
  127.     FAlphaBlend: Boolean;
  128.     FAlphaBlendAnimation: Boolean;
  129.     FAlphaBlendValue: Byte;
  130.     procedure SetValue(AValue: Double);
  131.     procedure SetMinValue(AValue: Double);
  132.     procedure SetMaxValue(AValue: Double);
  133.     procedure SetValueType(NewType: TbsValueType);
  134.     procedure SetDecimal(NewValue: Byte);
  135.     procedure ButtonClick(Sender: TObject);
  136.     procedure DropDown;
  137.     procedure CloseUp;
  138.   protected
  139.     function CheckValue(NewValue: Double): Double;
  140.     procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  141.     procedure CMCancelMode(var Message: TCMCancelMode); message CM_CANCELMODE;
  142.     procedure KeyPress(var Key: Char); override;
  143.     function IsValidChar(Key: Char): Boolean;
  144.     procedure Change; override;
  145.     procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  146.     property Text;
  147.   public
  148.     constructor Create(AOwner: TComponent); override;
  149.     destructor Destroy; override;
  150.     function IsNumText(AText: String): Boolean;
  151.     property Memory: Double read FMemory;
  152.   published
  153.     property AlphaBlend: Boolean read FAlphaBlend write FAlphaBlend;
  154.     property AlphaBlendAnimation: Boolean
  155.       read FAlphaBlendAnimation write FAlphaBlendAnimation;
  156.     property AlphaBlendValue: Byte read FAlphaBlendValue write FAlphaBlendValue;
  157.     property CalcButtonSkinDataName: String
  158.       read FCalcButtonSkinDataName
  159.       write FCalcButtonSkinDataName;
  160.     property CalcDisplayLabelSkinDataName: String
  161.       read FCalcDisplayLabelSkinDataName
  162.       write FCalcDisplayLabelSkinDataName;
  163.     property Precision: Byte read FPrecision write FPrecision default DefCalcPrecision;
  164.     property ValueType: TbsValueType read FValueType write SetValueType;
  165.     property Decimal: Byte read FDecimal write SetDecimal default 2;
  166.      property Align;
  167.     property MinValue: Double read FMinValue write SetMinValue;
  168.     property MaxValue: Double read FMaxValue write SetMaxValue;
  169.     property Value: Double read FValue write SetValue;
  170.     property Increment: Double read FIncrement write FIncrement;
  171.         property DefaultFont;
  172.     property DefaultWidth;
  173.     property DefaultHeight;
  174.     property ButtonMode;
  175.     property SkinData;
  176.     property SkinDataName;
  177.     property OnMouseEnter;
  178.     property OnMouseLeave;
  179.     property ReadOnly;
  180.     property Font;
  181.     property Anchors;
  182.     property AutoSelect;
  183.     property BiDiMode;
  184.     property CharCase;
  185.     property Constraints;
  186.     property DragCursor;
  187.     property DragKind;
  188.     property DragMode;
  189.     property Enabled;
  190.     property HideSelection;
  191.     property ImeMode;
  192.     property ImeName;
  193.     property MaxLength;
  194.     property OEMConvert;
  195.     property ParentBiDiMode;
  196.     property ParentColor;
  197.     property ParentCtl3D;
  198.     property ParentFont;
  199.     property ParentShowHint;
  200.     property PopupMenu;
  201.     property ShowHint;
  202.     property TabOrder;
  203.     property TabStop;
  204.     property Visible;
  205.     property OnButtonClick;
  206.     property OnChange;
  207.     property OnClick;
  208.     property OnDblClick;
  209.     property OnDragDrop;
  210.     property OnDragOver;
  211.     property OnEndDock;
  212.     property OnEndDrag;
  213.     property OnEnter;
  214.     property OnExit;
  215.     property OnKeyDown;
  216.     property OnKeyPress;
  217.     property OnKeyUp;
  218.     property OnMouseDown;
  219.     property OnMouseMove;
  220.     property OnMouseUp;
  221.     property OnStartDock;
  222.     property OnStartDrag;
  223.   end;
  224. function CreateCalculatorForm(AOwner: TComponent; AHelpContext: THelpContext): TbsCalculatorForm;
  225. implementation
  226.  {$R bscalc}
  227. uses bsUtils, bsConst;
  228. const
  229.   WS_EX_LAYERED = $80000;
  230.   CS_DROPSHADOW_ = $20000;
  231.   
  232. type
  233.   TCalcBtnKind =
  234.    (cbNone, cbNum0, cbNum1, cbNum2, cbNum3, cbNum4, cbNum5, cbNum6,
  235.     cbNum7, cbNum8, cbNum9, cbSgn, cbDcm, cbDiv, cbMul, cbSub,
  236.     cbAdd, cbSqr, cbPcnt, cbRev, cbEql, cbBck, cbClr, cbMP,
  237.     cbMS, cbMR, cbMC, cbOk, cbCancel);
  238. function CreateCalculatorForm(AOwner: TComponent; AHelpContext: THelpContext): TbsCalculatorForm;
  239. begin
  240.   Result := TbsCalculatorForm.Create(AOwner);
  241.   with Result do
  242.   try
  243.     HelpContext := AHelpContext;
  244.     if HelpContext <> 0 then BorderIcons := BorderIcons + [biHelp];
  245.     if Screen.PixelsPerInch <> 96 then begin { scale to screen res }
  246.       ScaleBy(Screen.PixelsPerInch, 96);
  247.       Left := (Screen.Width div 2) - (Width div 2);
  248.       Top := (Screen.Height div 2) - (Height div 2);
  249.     end;
  250.   except
  251.     Free;
  252.     raise;
  253.   end;
  254. end;
  255. { TCalcButton }
  256. type
  257.   TCalcButton = class(TbsSkinSpeedButton)
  258.   private
  259.     FKind: TCalcBtnKind;
  260.   protected
  261.   public
  262.     constructor CreateKind(AOwner: TComponent; AKind: TCalcBtnKind);
  263.     property Kind: TCalcBtnKind read FKind;
  264.   end;
  265. constructor TCalcButton.CreateKind(AOwner: TComponent; AKind: TCalcBtnKind);
  266. begin
  267.   inherited Create(AOwner);
  268.   ControlStyle := ControlStyle + [csReplicatable];
  269.   FKind := AKind;
  270.   if FKind in [cbNum0..cbClr] then Tag := Ord(Kind) - 1
  271.   else Tag := -1;
  272. end;
  273. const
  274.   BtnPos: array[TCalcBtnKind] of TPoint =
  275.   ((X: -1; Y: -1), (X: 38; Y: 120), (X: 38; Y: 92), (X: 71; Y: 92),
  276.     (X: 104; Y: 92), (X: 38; Y: 64), (X: 71; Y: 64), (X: 104; Y: 64),
  277.     (X: 38; Y: 36), (X: 71; Y: 36), (X: 104; Y: 36), (X: 71; Y: 120),
  278.     (X: 104; Y: 120), (X: 137; Y: 36), (X: 137; Y: 64), (X: 137; Y: 92),
  279.     (X: 137; Y: 120), (X: 170; Y: 36), (X: 170; Y: 64), (X: 170; Y: 92),
  280.     (X: 170; Y: 120), (X: 104; Y: 6), (X: 154; Y: 6), (X: 5; Y: 120),
  281.     (X: 5; Y: 92), (X: 5; Y: 64), (X: 5; Y: 36),
  282.     (X: 38; Y: 6), (X: 71; Y: 6));
  283.    ResultKeys = [#13, '=', '%'];
  284. function CreateCalcBtn(AParent: TWinControl; AKind: TCalcBtnKind;
  285.   AOnClick: TNotifyEvent): TCalcButton;
  286. const
  287.   BtnCaptions: array[cbSgn..cbMC] of PChar =
  288.    ('+/-', ',', '/', '*', '-', '+', 'sqrt', '%', '1/x', '=', '<', 'C',
  289.     'MP', 'MS', 'MR', 'MC');
  290. begin
  291.   Result := TCalcButton.CreateKind(AParent, AKind);
  292.   with Result do
  293.   try
  294.     if Kind in [cbNum0..cbNum9] then Caption := IntToStr(Tag)
  295.     else if Kind = cbDcm then Caption := DecimalSeparator
  296.     else if Kind in [cbSgn..cbMC] then Caption := StrPas(BtnCaptions[Kind]);
  297.     Left := BtnPos[Kind].X;
  298.     Top := BtnPos[Kind].Y;
  299.     Width := 30;
  300.     Height := 22;
  301.     OnClick := AOnClick;
  302.     Parent := AParent;
  303.   except
  304.     Free;
  305.     raise;
  306.   end;
  307. end;
  308. { TCalculatorPanel }
  309. type
  310.   TCalculatorPanel = class(TbsSkinPanel)
  311.   private
  312.     FText: string;
  313.     FStatus: TbsCalcState;
  314.     FOperator: Char;
  315.     FOperand: Double;
  316.     FMemory: Double;
  317.     FPrecision: Byte;
  318.     FBeepOnError: Boolean;
  319.     FMemoryLabel: TbsSkinStdLabel;
  320.     FOnError: TNotifyEvent;
  321.     FOnOk: TNotifyEvent;
  322.     FOnCancel: TNotifyEvent;
  323.     FOnResult: TNotifyEvent;
  324.     FOnTextChange: TNotifyEvent;
  325.     FOnCalcKey: TKeyPressEvent;
  326.     FOnDisplayChange: TNotifyEvent;
  327.     FControl: TControl;
  328.     procedure SetText(const Value: string);
  329.     procedure CheckFirst;
  330.     procedure CalcKey(Key: Char);
  331.     procedure Clear;
  332.     procedure Error;
  333.     procedure SetDisplay(R: Double);
  334.     function GetDisplay: Double;
  335.     procedure UpdateMemoryLabel;
  336.     function FindButton(Key: Char): TbsSkinSpeedButton;
  337.     procedure BtnClick(Sender: TObject);
  338.   protected
  339.     procedure TextChanged; virtual;
  340.   public
  341.     constructor CreateLayout(AOwner: TComponent);
  342.     procedure CalcKeyPress(Sender: TObject; var Key: Char);
  343.     procedure Copy;
  344.     procedure Paste;
  345.     property DisplayValue: Double read GetDisplay write SetDisplay;
  346.     property Text: string read FText;
  347.     property OnOkClick: TNotifyEvent read FOnOk write FOnOk;
  348.     property OnCancelClick: TNotifyEvent read FOnCancel write FOnCancel;
  349.     property OnResultClick: TNotifyEvent read FOnResult write FOnResult;
  350.     property OnError: TNotifyEvent read FOnError write FOnError;
  351.     property OnTextChange: TNotifyEvent read FOnTextChange write FOnTextChange;
  352.     property OnCalcKey: TKeyPressEvent read FOnCalcKey write FOnCalcKey;
  353.     property OnDisplayChange: TNotifyEvent read FOnDisplayChange write FOnDisplayChange;
  354.   end;
  355. constructor TCalculatorPanel.CreateLayout(AOwner: TComponent);
  356. var
  357.   I: TCalcBtnKind;
  358. const
  359.     BtnCaptions: array[cbSgn..cbCancel] of PChar =
  360.     ('+/-', ',', '/', '*', '-', '+', 'sqrt', '%', '1/x', '=', '', '',
  361.     'MP', 'MS', 'MR', 'MC', '', '');
  362. begin
  363.   inherited Create(AOwner);
  364.   Height := 150;
  365.   Width := 210;
  366.   try
  367.     for I := cbNum0 to cbCancel do begin
  368.       if BtnPos[I].X > 0 then
  369.         with CreateCalcBtn(Self, I, BtnClick) do
  370.         begin
  371.           NumGlyphs := 1;
  372.           case I of
  373.             cbClr: Glyph.LoadFromResourceName(HInstance, 'BS_CALC_CLEAR');
  374.             cbBck: Glyph.LoadFromResourceName(HInstance, 'BS_CALC_BACKSPACE');
  375.             cbOK: Glyph.LoadFromResourceName(HInstance, 'BS_CALC_OK');
  376.             cbCancel: Glyph.LoadFromResourceName(HInstance, 'BS_CALC_CANCEL');
  377.           end;
  378.           if (Kind in [cbBck, cbClr]) then Width := 46;
  379.           if (Kind in [cbSgn..cbCancel]) then Caption := BtnCaptions[Kind];
  380.         end;
  381.     end;
  382.     FMemoryLabel := TbsSkinStdLabel.Create(Self);
  383.     with FMemoryLabel do begin
  384.       SetBounds(6, 7, 34, 20);
  385.       Parent := Self;
  386.       Alignment := taCenter;
  387.     end;
  388.   finally
  389.   end;
  390.   FText := '0';
  391.   FMemory := 0.0;
  392.   FPrecision := DefCalcPrecision;
  393.   FBeepOnError := True;
  394. end;
  395. procedure TCalculatorPanel.SetText(const Value: string);
  396. begin
  397.   if FText <> Value then begin
  398.     FText := Value;
  399.     TextChanged;
  400.   end;
  401. end;
  402. procedure TCalculatorPanel.TextChanged;
  403. begin
  404.   if Assigned(FControl) then TLabel(FControl).Caption := FText;
  405.   if Assigned(FOnTextChange) then FOnTextChange(Self);
  406. end;
  407. procedure TCalculatorPanel.Error;
  408. begin
  409.   FStatus := csError;
  410.   SetText(BS_ERROR);
  411.   if FBeepOnError then MessageBeep(0);
  412.   if Assigned(FOnError) then FOnError(Self);
  413. end;
  414. procedure TCalculatorPanel.SetDisplay(R: Double);
  415. var
  416.   S: string;
  417. begin
  418.   S := FloatToStrF(R, ffGeneral, Max(2, FPrecision), 0);
  419.   if FText <> S then begin
  420.     SetText(S);
  421.     if Assigned(FOnDisplayChange) then FOnDisplayChange(Self);
  422.   end;
  423. end;
  424. function TCalculatorPanel.GetDisplay: Double;
  425. begin
  426.   if FStatus = csError then Result := 0.0
  427.   else Result := StrToFloat(Trim(FText));
  428. end;
  429. procedure TCalculatorPanel.CheckFirst;
  430. begin
  431.   if FStatus = csFirst then begin
  432.     FStatus := csValid;
  433.     SetText('0');
  434.   end;
  435. end;
  436. procedure TCalculatorPanel.UpdateMemoryLabel;
  437. begin
  438.   if FMemoryLabel <> nil then
  439.     if FMemory <> 0.0 then FMemoryLabel.Caption := 'M'
  440.     else FMemoryLabel.Caption := '';
  441. end;
  442. procedure TCalculatorPanel.CalcKey(Key: Char);
  443. var
  444.   R: Double;
  445. begin
  446.   Key := UpCase(Key);
  447.   if (FStatus = csError) and (Key <> 'C') then Key := #0;
  448.   if Assigned(FOnCalcKey) then FOnCalcKey(Self, Key);
  449.   if Key in [DecimalSeparator, '.', ','] then begin
  450.     CheckFirst;
  451.     if Pos(DecimalSeparator, FText) = 0 then
  452.       SetText(FText + DecimalSeparator);
  453.     Exit;
  454.   end;
  455.   case Key of
  456.     'R':
  457.       if FStatus in [csValid, csFirst] then begin
  458.         FStatus := csFirst;
  459.         if GetDisplay = 0 then Error else SetDisplay(1.0 / GetDisplay);
  460.       end;
  461.     'Q':
  462.       if FStatus in [csValid, csFirst] then begin
  463.         FStatus := csFirst;
  464.         if GetDisplay < 0 then Error else SetDisplay(Sqrt(GetDisplay));
  465.       end;
  466.     '0'..'9':
  467.       begin
  468.         CheckFirst;
  469.         if FText = '0' then SetText('');
  470.         if Pos('E', FText) = 0 then begin
  471.           if Length(FText) < Max(2, FPrecision) + Ord(Boolean(Pos('-', FText))) then
  472.             SetText(FText + Key)
  473.           else if FBeepOnError then MessageBeep(0);
  474.         end;
  475.       end;
  476.     #8:
  477.       begin
  478.         CheckFirst;
  479.         if (Length(FText) = 1) or ((Length(FText) = 2) and (FText[1] = '-')) then
  480.           SetText('0')
  481.         else
  482.           SetText(System.Copy(FText, 1, Length(FText) - 1));
  483.       end;
  484.     '_': SetDisplay(-GetDisplay);
  485.     '+', '-', '*', '/', '=', '%', #13:
  486.       begin
  487.         if FStatus = csValid then begin
  488.           FStatus := csFirst;
  489.           R := GetDisplay;
  490.           if Key = '%' then
  491.             case FOperator of
  492.               '+', '-': R := FOperand * R / 100.0;
  493.               '*', '/': R := R / 100.0;
  494.             end;
  495.           case FOperator of
  496.             '+': SetDisplay(FOperand + R);
  497.             '-': SetDisplay(FOperand - R);
  498.             '*': SetDisplay(FOperand * R);
  499.             '/': if R = 0 then Error else SetDisplay(FOperand / R);
  500.           end;
  501.         end;
  502.         FOperator := Key;
  503.         FOperand := GetDisplay;
  504.         if Key in ResultKeys then
  505.           if Assigned(FOnResult) then FOnResult(Self);
  506.       end;
  507.     #27, 'C': Clear;
  508.     ^C: Copy;
  509.     ^V: Paste;
  510.   end;
  511. end;
  512. procedure TCalculatorPanel.Clear;
  513. begin
  514.   FStatus := csFirst;
  515.   SetDisplay(0.0);
  516.   FOperator := '=';
  517. end;
  518. procedure TCalculatorPanel.CalcKeyPress(Sender: TObject; var Key: Char);
  519. var
  520.   Btn: TbsSkinSpeedButton;
  521. begin
  522.   Btn := FindButton(Key);
  523.   if Btn <> nil then Btn.ButtonClick
  524.   else CalcKey(Key);
  525. end;
  526. function TCalculatorPanel.FindButton(Key: Char): TbsSkinSpeedButton;
  527. const
  528.   ButtonChars = '0123456789_./*-+Q%R='#8'C';
  529. var
  530.   I: Integer;
  531.   BtnTag: Longint;
  532. begin
  533.   if Key in [DecimalSeparator, '.', ','] then Key := '.'
  534.   else if Key = #13 then Key := '='
  535.   else if Key = #27 then Key := 'C';
  536.   BtnTag := Pos(UpCase(Key), ButtonChars) - 1;
  537.   if BtnTag >= 0 then
  538.     for I := 0 to ControlCount - 1 do begin
  539.       if Controls[I] is TbsSkinSpeedButton then begin
  540.         Result := TbsSkinSpeedButton(Controls[I]);
  541.         if Result.Tag = BtnTag then Exit;
  542.       end;
  543.     end;
  544.   Result := nil;
  545. end;
  546. procedure TCalculatorPanel.BtnClick(Sender: TObject);
  547. begin
  548.   case TCalcButton(Sender).Kind of
  549.     cbNum0..cbNum9: CalcKey(Char(TComponent(Sender).Tag + Ord('0')));
  550.     cbSgn: CalcKey('_');
  551.     cbDcm: CalcKey(DecimalSeparator);
  552.     cbDiv: CalcKey('/');
  553.     cbMul: CalcKey('*');
  554.     cbSub: CalcKey('-');
  555.     cbAdd: CalcKey('+');
  556.     cbSqr: CalcKey('Q');
  557.     cbPcnt: CalcKey('%');
  558.     cbRev: CalcKey('R');
  559.     cbEql: CalcKey('=');
  560.     cbBck: CalcKey(#8);
  561.     cbClr: CalcKey('C');
  562.     cbMP:
  563.       if FStatus in [csValid, csFirst] then begin
  564.         FStatus := csFirst;
  565.         FMemory := FMemory + GetDisplay;
  566.         UpdateMemoryLabel;
  567.       end;
  568.     cbMS:
  569.       if FStatus in [csValid, csFirst] then begin
  570.         FStatus := csFirst;
  571.         FMemory := GetDisplay;
  572.         UpdateMemoryLabel;
  573.       end;
  574.     cbMR:
  575.       if FStatus in [csValid, csFirst] then begin
  576.         FStatus := csFirst;
  577.         CheckFirst;
  578.         SetDisplay(FMemory);
  579.       end;
  580.     cbMC:
  581.       begin
  582.         FMemory := 0.0;
  583.         UpdateMemoryLabel;
  584.       end;
  585.     cbOk:
  586.       begin
  587.         if FStatus <> csError then begin
  588.           CalcKey('=');
  589.           DisplayValue := DisplayValue; { to raise exception on error }
  590.           if Assigned(FOnOk) then FOnOk(Self);
  591.         end
  592.         else if FBeepOnError then MessageBeep(0);
  593.       end;
  594.     cbCancel: if Assigned(FOnCancel) then FOnCancel(Self);
  595.   end;
  596. end;
  597. procedure TCalculatorPanel.Copy;
  598. begin
  599.   Clipboard.AsText := FText;
  600. end;
  601. procedure TCalculatorPanel.Paste;
  602. begin
  603.   if Clipboard.HasFormat(CF_TEXT) then
  604.     try
  605.       SetDisplay(StrToFloat(Trim(ReplaceStr(Clipboard.AsText,
  606.         CurrencyString, ''))));
  607.     except
  608.       SetText('0');
  609.     end;
  610. end;
  611. { TbsCalculator }
  612. constructor TbsSkinCalculator.Create(AOwner: TComponent);
  613. begin
  614.   inherited Create(AOwner);
  615.   FTitle := BS_CALC_CAP;
  616.   FPrecision := DefCalcPrecision;
  617.   FBeepOnError := True;
  618.   FButtonSkinDataName := 'toolbutton';
  619.   FDisplayLabelSkinDataName := 'label';
  620.   FDefaultFont := TFont.Create;
  621.   with FDefaultFont do
  622.   begin
  623.     Name := 'Arial';
  624.     Style := [];
  625.     Height := 14;
  626.   end;
  627. end;
  628. destructor TbsSkinCalculator.Destroy;
  629. begin
  630.   FOnChange := nil;
  631.   FOnDisplayChange := nil;
  632.   FDefaultFont.Free;
  633.   inherited Destroy;
  634. end;
  635. procedure TbsSkinCalculator.SetDefaultFont;
  636. begin
  637.   FDefaultFont.Assign(Value);
  638. end;
  639. procedure TbsSkinCalculator.Notification;
  640. begin
  641.   inherited Notification(AComponent, Operation);
  642.   if (Operation = opRemove) and (AComponent = FSD) then FSD := nil;
  643.   if (Operation = opRemove) and (AComponent = FCtrlFSD) then FCtrlFSD := nil;
  644. end;
  645. function TbsSkinCalculator.GetTitle: string;
  646. begin
  647.   Result := FTitle;
  648. end;
  649. procedure TbsSkinCalculator.SetTitle(const Value: string);
  650. begin
  651.   FTitle := Value;
  652. end;
  653. function TbsSkinCalculator.TitleStored: Boolean;
  654. begin
  655.   Result := Title <> BS_CALC_CAP;
  656. end;
  657. function TbsSkinCalculator.GetDisplay: Double;
  658. begin
  659.   if Assigned(FCalc) then
  660.     Result := TCalculatorPanel(FCalc.FCalcPanel).GetDisplay
  661.   else Result := FValue;
  662. end;
  663. procedure TbsSkinCalculator.CalcKey(var Key: Char);
  664. begin
  665.   if Assigned(FOnCalcKey) then FOnCalcKey(Self, Key);
  666. end;
  667. procedure TbsSkinCalculator.DisplayChange;
  668. begin
  669.   if Assigned(FOnDisplayChange) then FOnDisplayChange(Self);
  670. end;
  671. procedure TbsSkinCalculator.Change;
  672. begin
  673.   if Assigned(FOnChange) then FOnChange(Self);
  674. end;
  675. function TbsSkinCalculator.Execute: Boolean;
  676. var
  677.   i: Integer;
  678.   FW, FH: Integer;
  679. begin
  680.   FCalc := CreateCalculatorForm(Self, HelpContext);
  681.   if (SkinData <> nil) and (SkinData.ResourceStrData <> nil)
  682.   then
  683.     FCalc.Caption := SkinData.ResourceStrData.GetResStr('CALC_CAP');
  684.   with FCalc do
  685.   try
  686.     FCalcPanel.SkinData := Self.CtrlSkinData;
  687.     FDisplayLabel.DefaultFont := FDefaultFont;
  688.     FDisplayLabel.SkinDataName := FDisplayLabelSkinDataName;
  689.     FDisplayLabel.SkinData := Self.CtrlSkinData;
  690.     for i := 0 to FCalcPanel.ControlCount - 1 do
  691.     if FCalcPanel.Controls[i] is TbsSkinSpeedButton then
  692.     with TbsSkinSpeedButton(FCalcPanel.Controls[i]) do
  693.     begin
  694.       DefaultFont := Self.DefaultFont;
  695.       DefaultHeight := 25;
  696.       SkinDataName := FButtonSkinDataName;
  697.       SkinData := CtrlSkinData;
  698.     end
  699.     else
  700.     if FCalcPanel.Controls[i] is TbsSkinStdLabel then
  701.     with TbsSkinStdLabel(FCalcPanel.Controls[i]) do
  702.     begin
  703.       DefaultFont := Self.DefaultFont;
  704.       SkinData := CtrlSkinData;
  705.     end;
  706.     Caption := Self.Title;
  707.     TCalculatorPanel(FCalcPanel).FMemory := Self.FMemory;
  708.     TCalculatorPanel(FCalcPanel).UpdateMemoryLabel;
  709.     TCalculatorPanel(FCalcPanel).FPrecision := Max(2, Self.Precision);
  710.     TCalculatorPanel(FCalcPanel).FBeepOnError := Self.BeepOnError;
  711.     if Self.FValue <> 0 then begin
  712.       TCalculatorPanel(FCalcPanel).DisplayValue := Self.FValue;
  713.       TCalculatorPanel(FCalcPanel).FStatus := csFirst;
  714.       TCalculatorPanel(FCalcPanel).FOperator := '=';
  715.     end;
  716.     BSF.BorderIcons := [];
  717.     BSF.SkinData := Self.SkinData;
  718.     BSF.MenusSkinData := Self.CtrlSkinData;
  719.     BSF.AlphaBlend := AlphaBlend;
  720.     BSF.AlphaBlendAnimation := AlphaBlendAnimation;
  721.     BSF.AlphaBlendValue := AlphaBlendValue;
  722.     FW := 205;
  723.     FH := FCalcPanel.Height + FDisplayLabel.Height;
  724.     if (SkinData <> nil) and not SkinData.Empty
  725.     then
  726.       begin
  727.         if FW < BSF.GetMinWidth then FW := BSF.GetMinWidth;
  728.         if FH < BSF.GetMinHeight then FH := BSF.GetMinHeight;  
  729.       end;
  730.     ClientWidth := FW;
  731.     ClientHeight := FH;
  732.     Result := (ShowModal = mrOk);
  733.     if Result then begin
  734.       Self.FMemory := TCalculatorPanel(FCalcPanel).FMemory;
  735.       if (TCalculatorPanel(FCalcPanel).DisplayValue <> Self.FValue) then begin
  736.         Self.FValue := TCalculatorPanel(FCalcPanel).DisplayValue;
  737.         Change;
  738.       end;
  739.     end;
  740.   finally
  741.     Free;
  742.     FCalc := nil;
  743.   end;
  744. end;
  745. { TbsCalculatorForm }
  746. constructor TbsCalculatorForm.Create(AOwner: TComponent);
  747. begin
  748.   inherited CreateNew(AOwner);
  749.   BorderStyle := bsDialog;
  750.   Caption := BS_CALC_CAP;
  751.   KeyPreview := True;
  752.   PixelsPerInch := 96;
  753.   Position := poScreenCenter;
  754.   OnKeyPress := FormKeyPress;
  755.   { DisplayPanel }
  756.   FDisplayLabel := TbsSkinLabel.Create(Self);
  757.   with FDisplayLabel do begin
  758.     Align := alTop;
  759.     Parent := Self;
  760.     AutoSize := False;
  761.     Alignment := taRightJustify;
  762.     Caption := '0';
  763.     BorderStyle := bvFrame;
  764.     DefaultHeight := 20;
  765.   end;
  766.   { CalcPanel }
  767.   FCalcPanel := TCalculatorPanel.CreateLayout(Self);
  768.   with TCalculatorPanel(FCalcPanel) do begin
  769.     Align := alTop;
  770.     Parent := Self;
  771.     OnOkClick := Self.OkClick;
  772.     OnCancelClick := Self.CancelClick;
  773.     OnCalcKey := Self.CalcKey;
  774.     OnDisplayChange := Self.DisplayChange;
  775.     FControl := FDisplayLabel;
  776.     BorderStyle := bvNone;
  777.   end;
  778.   BSF := TbsBusinessSkinForm.Create(Self);
  779. end;
  780. procedure TbsCalculatorForm.FormKeyPress(Sender: TObject; var Key: Char);
  781. begin
  782.   TCalculatorPanel(FCalcPanel).CalcKeyPress(Sender, Key);
  783. end;
  784. procedure TbsCalculatorForm.OkClick(Sender: TObject);
  785. begin
  786.   ModalResult := mrOk;
  787. end;
  788. procedure TbsCalculatorForm.CancelClick(Sender: TObject);
  789. begin
  790.   ModalResult := mrCancel;
  791. end;
  792. procedure TbsCalculatorForm.CalcKey(Sender: TObject; var Key: Char);
  793. begin
  794.   if (Owner <> nil) and (Owner is TbsSkinCalculator) then
  795.     TbsSkinCalculator(Owner).CalcKey(Key);
  796. end;
  797. procedure TbsCalculatorForm.DisplayChange(Sender: TObject);
  798. begin
  799.   if (Owner <> nil) and (Owner is TbsSkinCalculator) then
  800.     TbsSkinCalculator(Owner).DisplayChange;
  801. end;
  802. constructor TbsSkinCalcEdit.Create(AOwner: TComponent);
  803. begin
  804.   inherited;
  805.   ButtonMode := True;
  806.   FValue := 0;
  807.   FIncrement := 1;
  808.   FDecimal := 2;
  809.   StopCheck := True;
  810.   Text := '0';
  811.   StopCheck := False;
  812.   FromEdit := False;
  813.   Width := 120;
  814.   Height := 20;
  815.   FSkinDataName := 'buttonedit';
  816.   OnButtonClick := ButtonClick;
  817.   FCalc := TbsPopupCalculatorForm.Create(Self);
  818.   FCalc.Visible := False;
  819.   FCalc.CalcEdit := Self;
  820.   FCalc.Parent := Self;
  821.   FMemory := 0.0;
  822.   FPrecision := DefCalcPrecision;
  823.   FCalcButtonSkinDataName := 'toolbutton';
  824.   FCalcDisplayLabelSkinDataName := 'label';
  825.   FAlphaBlend := False;
  826.   FAlphaBlendValue := 0;
  827. end;
  828. destructor TbsSkinCalcEdit.Destroy;
  829. begin
  830.   FCalc.Free;
  831.   inherited;
  832. end;
  833. procedure TbsSkinCalcEdit.CMCancelMode(var Message: TCMCancelMode);
  834. begin
  835.   if (Message.Sender <> FCalc) and
  836.      not FCalc.ContainsControl(Message.Sender)
  837.   then
  838.     CloseUp;
  839. end;
  840. procedure TbsSkinCalcEdit.CloseUp;
  841. begin
  842.   if FCalc.Visible then FCalc.Hide;
  843.   if CheckW2KWXP and FAlphaBlend
  844.   then
  845.     SetWindowLong(FCalc.Handle, GWL_EXSTYLE,
  846.                   GetWindowLong(Handle, GWL_EXSTYLE) and not WS_EX_LAYERED);
  847. end;
  848. procedure TbsSkinCalcEdit.DropDown;
  849. var
  850.   i, Y: Integer;
  851.   P: TPoint;
  852. begin
  853.  with FCalc do
  854.   begin
  855.     SkinData := Self.SkinData;
  856.     FCalcPanel.SkinData := Self.SkinData;
  857.     FDisplayLabel.DefaultFont := FDefaultFont;
  858.     FDisplayLabel.SkinDataName := FCalcDisplayLabelSkinDataName;
  859.     FDisplayLabel.SkinData := Self.SkinData;
  860.     for i := 0 to FCalcPanel.ControlCount - 1 do
  861.     if FCalcPanel.Controls[i] is TbsSkinSpeedButton then
  862.     with TbsSkinSpeedButton(FCalcPanel.Controls[i]) do
  863.     begin
  864.       DefaultFont := Self.DefaultFont;
  865.       DefaultHeight := 25;
  866.       SkinDataName := FCalcButtonSkinDataName;
  867.       SkinData := Self.SkinData;
  868.     end
  869.     else
  870.     if FCalcPanel.Controls[i] is TbsSkinStdLabel then
  871.     with TbsSkinStdLabel(FCalcPanel.Controls[i]) do
  872.     begin
  873.       DefaultFont := Self.DefaultFont;
  874.       SkinData := Self.SkinData;
  875.     end;
  876.     TCalculatorPanel(FCalcPanel).FMemory := Self.FMemory;
  877.     TCalculatorPanel(FCalcPanel).UpdateMemoryLabel;
  878.     TCalculatorPanel(FCalcPanel).FPrecision := Max(2, Self.Precision);
  879.     TCalculatorPanel(FCalcPanel).FBeepOnError := False;
  880.     if Self.FValue <> 0 then begin
  881.       TCalculatorPanel(FCalcPanel).DisplayValue := Self.FValue;
  882.       TCalculatorPanel(FCalcPanel).FStatus := csFirst;
  883.       TCalculatorPanel(FCalcPanel).FOperator := '=';
  884.     end;
  885.     Width := 209;
  886.     //
  887.     if FIndex = -1
  888.     then
  889.       Height := FCalcPanel.Height + FDisplayLabel.Height + 2
  890.     else
  891.       Height := FCalcPanel.Height + FDisplayLabel.Height +
  892.       (RectHeight(SkinRect) - RectHeight(ClRect));
  893.     //
  894.     P := Self.Parent.ClientToScreen(Point(Self.Left, Self.Top));
  895.     Y := P.Y + Self.Height;
  896.     if Y + FCalc.Height > Screen.Height then Y := P.Y - FCalc.Height;
  897.     if P.X + FCalc.Width > Screen.Width
  898.     then P.X := Screen.Width - FCalc.Width;
  899.     if P.X < 0 then P.X := 0;
  900.     FCalc.Left := P.X;
  901.     FCalc.Top := Y;
  902.     //
  903.     if CheckW2KWXP and FAlphaBlend
  904.     then
  905.       begin
  906.         SetWindowLong(FCalc.Handle, GWL_EXSTYLE,
  907.                       GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
  908.         SetAlphaBlendTransparent(FCalc.Handle, 0)
  909.       end;
  910.     FCalc.Show(P.X, Y);
  911.     //
  912.     if FAlphaBlend and not FAlphaBlendAnimation and CheckW2KWXP
  913.     then
  914.       begin
  915.         Application.ProcessMessages;
  916.         SetAlphaBlendTransparent(FCalc.Handle, FAlphaBlendValue)
  917.       end
  918.     else
  919.     if CheckW2KWXP and FAlphaBlend and FAlphaBlendAnimation
  920.     then
  921.       begin
  922.         Application.ProcessMessages;
  923.         I := 0;
  924.         repeat
  925.           Inc(i, 2);
  926.           if i > FAlphaBlendValue then i := FAlphaBlendValue;
  927.           SetAlphaBlendTransparent(FCalc.Handle, i);
  928.         until i >= FAlphaBlendValue;
  929.       end;
  930.   end;
  931. end;
  932. procedure TbsSkinCalcEdit.ButtonClick(Sender: TObject);
  933. begin
  934.   if FCalc.Visible then CloseUp else DropDown;
  935. end;
  936. procedure TbsSkinCalcEdit.SetValueType(NewType: TbsValueType);
  937. begin
  938.   if FValueType <> NewType
  939.   then
  940.     begin
  941.       FValueType := NewType;
  942.       if FValueType = vtInteger
  943.       then
  944.         begin
  945.           FIncrement := Round(FIncrement);
  946.           if FIncrement = 0 then FIncrement := 1;
  947.         end;
  948.   end;
  949. end;
  950. procedure TbsSkinCalcEdit.SetDecimal(NewValue: Byte);
  951. begin
  952.   if FDecimal <> NewValue then begin
  953.     FDecimal := NewValue;
  954.   end;
  955. end;
  956. function TbsSkinCalcEdit.CheckValue;
  957. begin
  958.   Result := NewValue;
  959.   if (FMaxValue <> FMinValue)
  960.   then
  961.     begin
  962.       if NewValue < FMinValue then
  963.       Result := FMinValue
  964.       else if NewValue > FMaxValue then
  965.       Result := FMaxValue;
  966.     end;
  967. end;
  968. procedure TbsSkinCalcEdit.SetMinValue;
  969. begin
  970.   FMinValue := AValue;
  971. end;
  972. procedure TbsSkinCalcEdit.SetMaxValue;
  973. begin
  974.   FMaxValue := AValue;
  975. end;
  976. function TbsSkinCalcEdit.IsNumText;
  977. function GetMinus: Boolean;
  978. var
  979.   i: Integer;
  980.   S: String;
  981. begin
  982.   S := AText;
  983.   i := Pos('-', S);
  984.   if i > 1
  985.   then
  986.     Result := False
  987.   else
  988.     begin
  989.       Delete(S, i, 1);
  990.       Result := Pos('-', S) = 0;
  991.     end;
  992. end;
  993. function GetP: Boolean;
  994. var
  995.   i: Integer;
  996.   S: String;
  997. begin
  998.   S := AText;
  999.   i := Pos(DecimalSeparator, S);
  1000.   if i = 1
  1001.   then
  1002.     Result := False
  1003.   else
  1004.     begin
  1005.       Delete(S, i, 1);
  1006.       Result := Pos(DecimalSeparator, S) = 0;
  1007.     end;
  1008. end;
  1009. const
  1010.   EditChars = '01234567890-';
  1011. var
  1012.   i: Integer;
  1013.   S: String;
  1014. begin
  1015.   S := EditChars;
  1016.   Result := True;
  1017.   if ValueType = vtFloat
  1018.   then
  1019.     S := S + DecimalSeparator;
  1020.   if (Text = '') or (Text = '-')
  1021.   then
  1022.     begin
  1023.       Result := False;
  1024.       Exit;
  1025.     end;
  1026.   for i := 1 to Length(Text) do
  1027.   begin
  1028.     if Pos(Text[i], S) = 0
  1029.     then
  1030.       begin
  1031.         Result := False;
  1032.         Break;
  1033.       end;
  1034.   end;
  1035.   Result := Result and GetMinus;
  1036.   if ValueType = vtFloat
  1037.   then
  1038.     Result := Result and GetP;
  1039. end;
  1040. procedure TbsSkinCalcEdit.Change;
  1041. var
  1042.   NewValue, TmpValue: Double;
  1043. begin
  1044.   if FromEdit then Exit;
  1045.   if not StopCheck and IsNumText(Text)
  1046.   then
  1047.     begin
  1048.       if ValueType = vtFloat
  1049.       then TmpValue := StrToFloat(Text)
  1050.       else TmpValue := StrToInt(Text);
  1051.       NewValue := CheckValue(TmpValue);
  1052.       if NewValue <> FValue
  1053.       then
  1054.         begin
  1055.           FValue := NewValue;
  1056.         end;
  1057.       if NewValue <> TmpValue
  1058.       then
  1059.         begin
  1060.           FromEdit := True;
  1061.           if ValueType = vtFloat
  1062.           then Text := FloatToStrF(NewValue, ffFixed, 15, FDecimal)
  1063.           else Text := IntToStr(Round(FValue));
  1064.           FromEdit := False;
  1065.         end;
  1066.     end;
  1067.   inherited;  
  1068. end;
  1069. procedure TbsSkinCalcEdit.CMTextChanged;
  1070. begin
  1071.   inherited;
  1072. end;
  1073. procedure TbsSkinCalcEdit.SetValue;
  1074. begin
  1075.   FValue := CheckValue(AValue);
  1076.   StopCheck := True;
  1077.   if ValueType = vtFloat
  1078.   then
  1079.     Text := FloatToStrF(CheckValue(AValue), ffFixed, 15, FDecimal)
  1080.   else
  1081.     Text := IntToStr(Round(CheckValue(AValue)));
  1082.   StopCheck := False;
  1083. end;
  1084. procedure TbsSkinCalcEdit.KeyPress(var Key: Char);
  1085. begin
  1086.   if not IsValidChar(Key) then
  1087.   begin
  1088.     Key := #0;
  1089.     MessageBeep(0)
  1090.   end;
  1091.   if Key <> #0 then
  1092.   if FCalc.Visible
  1093.   then
  1094.     CloseUp
  1095.   else
  1096.     inherited KeyPress(Key);
  1097. end;
  1098. function TbsSkinCalcEdit.IsValidChar(Key: Char): Boolean;
  1099. begin
  1100.   if ValueType = vtInteger
  1101.   then
  1102.     Result := (Key in ['-', '0'..'9']) or
  1103.      ((Key < #32) and (Key <> Chr(VK_RETURN)))
  1104.   else
  1105.   Result := (Key in [DecimalSeparator, '-', '0'..'9']) or
  1106.     ((Key < #32) and (Key <> Chr(VK_RETURN)));
  1107.   if ReadOnly and Result and ((Key >= #32) or
  1108.      (Key = Char(VK_BACK)) or (Key = Char(VK_DELETE)))
  1109.   then
  1110.     Result := False;
  1111.   if (Key = DecimalSeparator) and (Pos(DecimalSeparator, Text) <> 0)
  1112.   then
  1113.     Result := False
  1114.   else
  1115.   if (Key = '-') and (Pos('-', Text) <> 0)
  1116.   then
  1117.     Result := False;
  1118. end;
  1119. procedure TbsSkinCalcEdit.WMKillFocus(var Message: TWMKillFocus);
  1120. begin
  1121.   inherited;
  1122.   CloseUp;
  1123. end;
  1124. constructor TbsPopupCalculatorForm.Create(AOwner: TComponent);
  1125. begin
  1126.   inherited Create(AOwner);
  1127.   BorderStyle := bvFrame;
  1128.   ControlStyle := ControlStyle + [csNoDesignVisible, csReplicatable];
  1129.   CalcEdit := nil;
  1130.   { DisplayPanel }
  1131.   FDisplayLabel := TbsSkinLabel.Create(Self);
  1132.   with FDisplayLabel do begin
  1133.     Align := alTop;
  1134.     Parent := Self;
  1135.     AutoSize := False;
  1136.     Alignment := taRightJustify;
  1137.     Caption := '0';
  1138.     BorderStyle := bvNone;
  1139.     DefaultHeight := 20;
  1140.     Visible := True;
  1141.   end;
  1142.   { CalcPanel }
  1143.   FCalcPanel := TCalculatorPanel.CreateLayout(Self);
  1144.   with TCalculatorPanel(FCalcPanel) do begin
  1145.     Align := alTop;
  1146.     Parent := Self;
  1147.     FControl := FDisplayLabel;
  1148.     BorderStyle := bvNone;
  1149.     OnOkClick := OkClick;
  1150.     OnCancelClick := CancelClick;
  1151.     Visible := True;
  1152.   end;
  1153. end;
  1154. destructor TbsPopupCalculatorForm.Destroy;
  1155. begin
  1156.   FDisplayLabel.Free;
  1157.   FCalcPanel.Free;
  1158.   inherited;
  1159. end;
  1160. procedure TbsPopupCalculatorForm.Show(X, Y: Integer);
  1161. begin
  1162.   SetWindowPos(Handle, HWND_TOP, X, Y, 0, 0,
  1163.       SWP_NOSIZE or SWP_NOACTIVATE or SWP_SHOWWINDOW);
  1164.   Visible := True;
  1165. end;
  1166. procedure TbsPopupCalculatorForm.Hide;
  1167. begin
  1168.   SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or
  1169.       SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
  1170.   Visible := False;
  1171. end;
  1172. procedure TbsPopupCalculatorForm.CreateParams(var Params: TCreateParams);
  1173. begin
  1174.   inherited CreateParams(Params);
  1175.   with Params do
  1176.   begin
  1177.     Style := WS_POPUP;
  1178.     ExStyle := WS_EX_TOOLWINDOW;
  1179.     AddBiDiModeExStyle(ExStyle);
  1180.     WindowClass.Style := CS_SAVEBITS;
  1181.     if CheckWXP then
  1182.       WindowClass.Style := WindowClass.style or CS_DROPSHADOW_;
  1183.   end;
  1184. end;
  1185. procedure TbsPopupCalculatorForm.WMMouseActivate(var Message: TMessage);
  1186. begin
  1187.   Message.Result := MA_NOACTIVATE;
  1188. end;
  1189. procedure TbsPopupCalculatorForm.OkClick(Sender: TObject);
  1190. begin
  1191.   if CalcEdit <> nil
  1192.   then
  1193.     begin
  1194.       CalcEdit.Value := TCalculatorPanel(FCalcPanel).DisplayValue;
  1195.       CalcEdit.CloseUp;
  1196.     end;
  1197. end;
  1198. procedure TbsPopupCalculatorForm.CancelClick(Sender: TObject);
  1199. begin
  1200.   if CalcEdit <> nil then CalcEdit.CloseUp;
  1201. end;
  1202. end.