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

Delphi控件源码

开发平台:

Delphi

  1. unit wwcalculator;
  2. //Change from TBitBtn to TSpeedButton and remove tabstops from other controls.
  3. //Replace other controls with TLabel and TBevels and TShape.
  4. interface
  5. uses
  6.   Windows, messages, Sysutils, Forms, Classes, Controls, StdCtrls, extctrls, ComCtrls, Graphics, Buttons,wwcommon,wwdbedit, wwtypes, wwframe;
  7. type
  8.   TwwCalcButtonType = (btNone,bt0, bt1, bt2, bt3, bt4, bt5, bt6, bt7,
  9.     bt8, bt9, btDecimal, btPlusMinus, btMultiply, btDivide,
  10.     btAdd, btSubtract, btEquals, btSqrt, btPercent, btInverse,
  11.     btBackspace, btClear, btClearAll, btMRecall, btMStore, btMClear,
  12.     btMAdd);
  13.   TCalcState = (csNone, csAdd, csSubtract, csMultiply, csDivide);
  14.   TwwCalcOption = (cboHotTrackButtons, cboFlatButtons, cboHideBorder, cboHideEditor, cboShowStatus);
  15.   TwwCalcOptions = set of TwwCalcOption;
  16.   TwwCalcBitmapDrawStyle = (cbdStretch, cbdTile, cbdTopLeft, cbdCenter);
  17.   TwwCalcBevel = class(TBevel)
  18.   public
  19.     FColor:TColor;
  20.   protected
  21.     procedure Paint; override;
  22.   end;
  23.   TwwCalculator = class;
  24.   TwwCalcLabel = class(TLabel)
  25.   private
  26.     FCalc:TwwCalculator;
  27.     procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
  28.     procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP;
  29.   public
  30.     constructor Create(AOwner: TComponent); override;
  31.   end;
  32.   TwwCalcButton = class(TSpeedButton)
  33.   private
  34.     FCalc:TwwCalculator;
  35.     ButtonColor:TColor;
  36.     ButtonFontColor:TColor;
  37.     FOptions: TwwCalcOptions;
  38.     FTransparent:Boolean;
  39.     FBtnType:TwwCalcButtonType;
  40.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  41.     procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
  42.     procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  43.     procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBkgnd;
  44.     procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
  45.     procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP;
  46.   protected
  47.     procedure Paint; override;
  48.   public
  49.     constructor Create(AOwner: TComponent); override;
  50.     destructor Destroy; override;
  51.   end;
  52.   TButtonRecord = record
  53.     Top: Integer;
  54.     Left: Integer;
  55.     Width: Integer;
  56.     Height: Integer;
  57.     Caption: string;
  58.     Hint:string;
  59.     Color: TColor;
  60.     BtnType:TwwCalcButtonType;
  61.   end;
  62.   TwwCalculator = class(TCustomPanel)
  63.    private
  64.     FResultEdit: TwwdbEdit;
  65.     FStatusLabel: TLabel;
  66.     FMemoryValue: Double;
  67.     FLastValue: Double;
  68.     FCurrentValue: Double;
  69.     FResultValue: Double;
  70.     FLastOperand: Double;
  71.     FLastOP:TwwCalcButtonType;
  72.     FNextToLastOp:TwwCalcButtonType;
  73.     FDecimalEntered:Boolean;
  74.     FClearOnNextKey:Boolean;
  75.     FLastOperatorEquals:Boolean;
  76.     FLastStatus:String;
  77.     F3D:Boolean;
  78.     FStatusBevel: TwwCalcBevel;
  79.     FMemoryBevel: TwwCalcBevel;
  80.     FMemoryStatus: TwwCalcLabel;
  81.     FPanelColor:TColor;
  82.     FBackSpaceValid: Boolean;
  83.     FOptions: TwwCalcOptions;
  84.     FBackgroundBitmap: TPicture;
  85.     FPaintBitmap: TBitmap;
  86.     OldBoundsRect: TRect;
  87.     FMargin:integer;
  88.     FBackgroundBitmapDrawStyle: TwwCalcBitmapDrawStyle;
  89.     InitBitmapsFlag: boolean;
  90.     procedure SetOptions(Value: TwwCalcOptions);
  91.     procedure SetPanelColor(Value: TColor);
  92.     procedure SetMargin(Value: Integer);
  93.     procedure SetBackgroundBitmapDrawStyle(Value: TwwCalcBitmapDrawStyle);
  94.     procedure SetBackgroundBitmap(Value: TPicture);
  95.     procedure SetBorder3D(const Value:Boolean);
  96.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  97.     procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBkgnd;
  98.    protected
  99.      Btns: array [TwwCalcButtonType] of TButtonRecord;
  100.      procedure CalcButtons; virtual;
  101.      procedure Compute(Sender: TObject); virtual;
  102.      function GetText : string; virtual;
  103.      procedure SetText(const Value : string); virtual;
  104.      procedure Loaded; override;
  105.    public
  106.      constructor Create(AOwner: TComponent); override;
  107.      destructor Destroy; override;
  108.      procedure FullRepaint; virtual;
  109.      procedure RefreshSummary; virtual;
  110.      procedure Paint; override;
  111.      function IsBinaryOperator(ButtonType:TwwCalcButtonType):boolean; virtual;
  112.      procedure Reset; virtual;
  113.      function OpToChar(aOp:TwwCalcButtonType):Char; virtual;
  114.      function CharToOp(c:Char;Ctrl:Boolean):TwwCalcButtonType; virtual;
  115.      procedure ResultKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); virtual;
  116.      procedure DoCalc(ButtonType:TwwCalcButtonType); virtual;
  117.      property Value : Double read FCurrentValue write FCurrentValue;
  118.      property PaintBitmap: TBitmap read FPaintBitmap write FPaintBitmap;
  119.      property ResultEdit: TwwDBEdit read FResultEdit write FResultEdit;
  120.      property StatusLabel: TLabel read FStatusLabel write FStatusLabel;
  121.      property MemoryStatus:TwwCalcLabel read FMemoryStatus write FMemoryStatus;
  122.      property MemoryValue:Double read FMemoryValue write FMemoryValue;
  123.    published
  124.      property Align;
  125.      property BackgroundBitmap: TPicture read FBackgroundBitmap write SetBackgroundBitmap;
  126.      property BackgroundBitmapDrawStyle: TwwCalcBitmapDrawStyle read FBackgroundBitmapDrawStyle write SetBackgroundBitmapDrawStyle;
  127.      property Border3D: Boolean read F3D write SetBorder3D default False;
  128.      property ButtonMargin: integer read FMargin write SetMargin default 3;
  129.      property Font;
  130.      property Options: TwwCalcOptions read FOptions write SetOptions default [];
  131.      property PanelColor: TColor read FPanelColor write SetPanelColor default clBtnFace;
  132.      property Text : string read GetText write SetText;
  133.    end;
  134. procedure Register;
  135. implementation
  136. procedure GetColorByteValues(AColor: TColor; var Reserved, Blue, Green, Red: Byte);
  137.   var WinColor: COLORREF;
  138. begin
  139.   WinColor := ColorToRGB(AColor);
  140.   Reserved := ($FF000000 and WinColor) Shr 24;
  141.   Blue := ($00FF0000 and WinColor) Shr 16;
  142.   Green := ($0000FF00 and WinColor) Shr 8;
  143.   Red := ($000000FF and WinColor);
  144. end;
  145. function changecolor(acolor:TCOlor;brighten:boolean):TColor;
  146. var  red,green,blue,dummy:Byte;
  147.      dr,dg,db:integer;
  148. begin
  149.    GetColorByteValues(acolor,dummy,blue,green,red);
  150.    dr:=red;dg:=green;db:=blue;
  151.    if brighten then begin
  152.       red:=wwMin(255,dr+Trunc((255-dr)*0.50)) ;
  153.       green:=wwMin(255,dg+Trunc((255-dg)*0.50)) ;
  154.       blue:=wwMin(255,db+Trunc((255-db)*0.50)) ;
  155.    end
  156.    else begin
  157.       red:=wwMax(0,Trunc(dr*0.50)) ;
  158.       green:=wwMax(0,Trunc(dg*0.50)) ;
  159.       blue:=wwMax(0,Trunc(db*0.50)) ;
  160.    end;
  161.    result := TColor(RGB(red, Green, Blue))
  162. end;
  163. procedure Frame3D(Canvas: TCanvas; var Rect: TRect; TopColor, BottomColor: TColor;
  164.   Width: Integer);
  165.   procedure DoRect;
  166.   var
  167.     TopRight, BottomLeft: TPoint;
  168.   begin
  169.     with Canvas, Rect do
  170.     begin
  171.       TopRight.X := Right;
  172.       TopRight.Y := Top;
  173.       BottomLeft.X := Left;
  174.       BottomLeft.Y := Bottom;
  175.       Pen.Color := TopColor;
  176.       PolyLine([BottomLeft, TopLeft, TopRight]);
  177.       Pen.Color := BottomColor;
  178.       Dec(BottomLeft.X);
  179.       PolyLine([TopRight, BottomRight, BottomLeft]);
  180.     end;
  181.   end;
  182. begin
  183.   Canvas.Pen.Width := 1;
  184.   Dec(Rect.Bottom); Dec(Rect.Right);
  185.   while Width > 0 do
  186.   begin
  187.     Dec(Width);
  188.     DoRect;
  189.     InflateRect(Rect, -1, -1);
  190.   end;
  191.   Inc(Rect.Bottom); Inc(Rect.Right);
  192. end;
  193. function ButtonRecord(btnType:TwwCalcButtonType;
  194.   aTop, aLeft, aWidth, aHeight: Integer; aCaption: string;
  195.   aColor: TColor = clBlack; aHint:string = ''): TButtonRecord;
  196. begin
  197.   Result.btnType := btnType;
  198.   Result.Top := aTop;
  199.   Result.Left := aLeft;
  200.   Result.Width := aWidth;
  201.   Result.Height := aHeight;
  202.   Result.Caption := aCaption;
  203.   Result.Color := aColor;
  204.   Result.Hint := aHint;
  205. end;
  206. {procedure TwwCalcButton.CreateParams(var Params: TCreateParams);
  207. begin
  208.   inherited CreateParams(Params);
  209. //  with Params do Style := Style or BS_OWNERDRAW;
  210. end;}
  211. { TwwCalcBevel }
  212. procedure TwwCalcBevel.Paint;
  213. var R:TRect;
  214.     BtnShadow,BtnLight:TColor;
  215. begin
  216.    R:= Rect(0,0,Width,Height);
  217.    Frame3D(Canvas, R, clBlack, clWhite, 1);
  218.    BtnShadow:= changeColor(FColor,False);
  219.    BtnLight := changeColor(FColor,True);
  220.    R:= Rect(1,1,Width-1,Height-1);
  221.    Frame3D(Canvas, R, BtnShadow, BtnLight, 1);
  222. end;
  223. { TwwCalcButton }
  224. constructor TwwCalcButton.Create(AOwner: TComponent);
  225. begin
  226.   inherited Create(AOwner);
  227.   FCalc := AOwner as TwwCalculator;
  228.   ControlStyle := ControlStyle + [csCaptureMouse, csDoubleClicks, csReflector];
  229.   ButtonColor := clBtnFace;
  230.   ButtonFontColor := clWindowText;
  231. end;
  232. destructor TwwCalcButton.Destroy;
  233. begin
  234.   inherited Destroy;
  235. end;
  236. procedure TwwCalcButton.WMRButtonDown(var Message: TWMRButtonDown);
  237. begin
  238.   inherited;
  239.   if FCalc.StatusLabel <> nil then
  240.      FCalc.statuslabel.Caption := Self.Hint;
  241. end;
  242. procedure TwwCalcButton.WMRButtonUp(var Message: TWMRButtonUp);
  243. begin
  244.   inherited;
  245.   FCalc.RefreshSummary;
  246. end;
  247. constructor TwwCalcLabel.Create(AOwner: TComponent);
  248. begin
  249.   inherited Create(AOwner);
  250.   FCalc := AOwner as TwwCalculator;
  251. end;
  252. procedure TwwCalcLabel.WMRButtonDown(var Message: TWMRButtonDown);
  253. begin
  254.   inherited;
  255.   if FCalc.StatusLabel <> nil then
  256.      FCalc.statuslabel.Caption := FloatToStr(FCalc.MemoryValue);
  257. end;
  258. procedure TwwCalcLabel.WMRButtonUp(var Message: TWMRButtonUp);
  259. begin
  260.   inherited;
  261.   FCalc.RefreshSummary;
  262. end;
  263. procedure TwwCalcButton.WMEraseBkgnd(var Message: TWmEraseBkgnd);
  264. begin
  265.   Message.result:= 1;
  266. end;
  267. procedure TwwCalcButton.Paint;
  268. var
  269.   IsDown: Boolean;
  270.   R: TRect;
  271.   P:TPoint;
  272.   MouseinButton:BOolean;
  273.   Btnlight,Btnshadow:TColor;
  274.   SaveFontColor,SaveBrushColor,SavePenColor:TColor;
  275. begin
  276.   try
  277.      Canvas.Lock;
  278.      R := ClientRect;
  279.      GetCursorPos(P);
  280.      P:=(screenToClient(p));
  281.      if PtInRect(r,p) then
  282.         MouseInButton := True
  283.      else MouseInButton := False;
  284.      IsDown := (csLButtonDown in ControlState) and MouseInButton;
  285.      Canvas.Font := Self.Font;
  286.      Canvas.Pen.Color := clBlack;
  287.      Canvas.Font.Color := ButtonFontColor;
  288.      Canvas.Brush.Color := ButtonColor;
  289.      if FTransparent then begin
  290.         Canvas.CopyRect(ClientRect,(Parent as TwwCalculator).PaintBitmap.Canvas,
  291.           Rect(Left,Top,Left+WIdth,Top+Height));
  292.      end
  293.      else Canvas.FillRect(r);
  294.      if MouseInButton and (cboHotTrackButtons in FOptions) and not (cboFlatButtons in FOptions) then
  295.     begin
  296.        Canvas.Pen.Color := clWindowFrame;
  297.        Canvas.Pen.Width := 1;
  298.        Canvas.Brush.Style := bsClear;
  299.        Canvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
  300.     { DrawFrameControl must draw within this border }
  301.       InflateRect(R, -1, -1);
  302.      end;
  303.      Canvas.Pen.Color := clBtnShadow;
  304.      Canvas.Pen.Width := 1;
  305.      Canvas.Brush.Color := ButtonColor;
  306.      BTnShadow:= changeColor(ButtonColor,False);
  307.      BtnLight := changeColor(ButtonColor,True);
  308.   { DrawFrameControl does not draw a pressed button correctly }
  309.   if IsDown then
  310.   begin
  311.     Canvas.Brush.Style := bsClear;
  312.     Canvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
  313.     Canvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
  314.     Canvas.Pen.Color := BtnShadow;
  315.     Canvas.Polyline([Point(r.left,r.bottom),Point(r.left,r.top),Point(r.right,r.top)]);
  316.     Canvas.Pen.Color := clBlack;
  317.     Canvas.Polyline([Point(r.left+1,r.bottom-1),Point(r.left+1,r.top+1),Point(r.right-1,r.top+1)]);
  318.     Canvas.Pen.Color := BtnLight;
  319.     Canvas.Polyline([Point(r.left+2,r.bottom-2),Point(r.right-2,r.bottom-2),Point(r.right-2,r.top+2)]);
  320.     Canvas.Pen.Color := clWhite;
  321.     Canvas.Polyline([Point(r.left+1,r.bottom-1),Point(r.right-1,r.bottom-1),Point(r.right-1,r.top+1)]);
  322.     InflateRect(R, -1, -1);
  323.   end
  324.   else
  325.   begin
  326.     if not (cboFlatButtons in fOptions) or
  327.        (PtInRect(r,p) and ((cboHotTrackButtons in FOptions))) then begin
  328.       Canvas.Brush.Style := bsClear;
  329.        Canvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
  330.        Canvas.Pen.Color := BtnLight;
  331.        Canvas.Polyline([Point(r.left,r.bottom),Point(r.left,r.top),Point(r.right,r.top)]);
  332.        Canvas.Pen.Color := clWhite;
  333.        Canvas.Polyline([Point(r.left+1,r.bottom-1),Point(r.left+1,r.top+1),Point(r.right-1,r.top+1)]);
  334.        Canvas.Pen.Color := BtnShadow;
  335.        Canvas.Polyline([Point(r.left+2,r.bottom-2),Point(r.right-2,r.bottom-2),Point(r.right-2,r.top+1)]);
  336.        Canvas.Pen.Color := clBlack;
  337.        Canvas.Polyline([Point(r.left+1,r.bottom-1),Point(r.right-1,r.bottom-1),Point(r.right-1,r.top)]);
  338.     end;
  339. //    InflateRect(R, -1, -1);
  340.   end;
  341.  if PtInRect(r,p) and False then
  342.   begin
  343.     R := ClientRect;
  344.     InflateRect(R, -1, -1);
  345.   end;
  346.   if IsDown then
  347.     OffsetRect(R, 1, 1);
  348.   Canvas.Brush.Style := bsClear;
  349.   DrawText(Canvas.Handle,PChar(Caption),length(caption),R,DT_CENTER or DT_VCENTER or DT_SINGLELINE);
  350. { if PtInRect(r,p) or False then
  351.   begin
  352.     R := ClientRect;
  353.     InflateRect(R, -4, -4);
  354.     Canvas.Pen.Color := clWindowFrame;
  355.     Canvas.Brush.Color := clBtnFace;
  356. //    DrawFocusRect(Canvas.Handle, R);
  357.   end;}
  358.   finally
  359.      Canvas.Font.COlor := SaveFontColor;
  360.      Canvas.Brush.Color := SaveBrushColor;
  361.      Canvas.Pen.COlor := SavePenColor;
  362.      Canvas.Unlock;
  363.   end;
  364. end;
  365. procedure TwwCalcButton.CMMouseEnter(var Message: TMessage);
  366. begin
  367.   inherited;
  368.   if cboHotTrackButtons in FOptions then
  369.      Invalidate;
  370. end;
  371. procedure TwwCalcButton.CMMouseLeave(var Message: TMessage);
  372. begin
  373.   inherited;
  374.   if cboHotTrackButtons in FOptions then
  375.      Invalidate;
  376. end;
  377. procedure TwwCalcButton.CMEnabledChanged(var Message: TMessage);
  378. begin
  379.   inherited;
  380.   Invalidate;
  381. end;
  382. { TwwCalculator }
  383. constructor TwwCalculator.Create(AOwner: TComponent);
  384. begin
  385.   inherited Create(AOwner);
  386.   SetBounds(0,0,250,200);
  387.   FMemoryValue := 0;
  388.   FCurrentValue := 0;
  389.   FLastValue := 0;
  390.   Caption := '';
  391.   FMargin := 3;
  392.   FOptions := [];
  393. //  BorderStyle := bsRaisedPanel;
  394.   FPanelColor := clBtnFace;
  395.   FPaintBitmap:= TBitmap.create;
  396.   FBackgroundBitmap:= TPicture.create;
  397.   F3D := False;
  398. end;
  399. destructor TwwCalculator.Destroy;
  400. begin
  401.   inherited Destroy;
  402.   FPaintBitmap.Free;
  403.   FBackGroundBitmap.Free;
  404. end;
  405. procedure TwwCalculator.Loaded;
  406. var i:integer;
  407. begin
  408.   inherited;
  409.   CalcButtons;
  410.   if BackGroundBitmap.Graphic.empty then begin
  411.      for i:= 0 to ControlCount-1 do begin
  412.        if COntrols[i] is TwwCalcButton then
  413.          TwwCalcButton(controls[i]).FTransparent := False;
  414.      end;
  415.   end
  416.   else begin
  417.     for i:= 0 to ControlCount-1 do begin
  418.        if COntrols[i] is TwwCalcButton then
  419.          TwwCalcButton(controls[i]).FTransparent := True;
  420.     end;
  421.     InitBitmapsFlag := True;
  422.   end;
  423. end;
  424. function TwwCalculator.CharToOp(c:Char;Ctrl:Boolean):TwwCalcButtonType;
  425. begin
  426.   Result := btNone;
  427.   case c of
  428.       '0':Result :=bt0;
  429.       '1':Result :=bt1;
  430.       '2':Result :=bt2;
  431.       '3':Result :=bt3;
  432.       '4':Result :=bt4;
  433.       '5':Result :=bt5;
  434.       '6':Result :=bt6;
  435.       '7':Result :=bt7;
  436.       '8':Result :=bt8;
  437.       '9':Result :=bt9;
  438.       ',','.':Result:=btDecimal;
  439.       '_':Result := btPlusMinus;
  440.       '*':Result := btMultiply;
  441.       '/':Result := btDivide;
  442.       '+':Result := btAdd;
  443.       '-':Result := btSubtract;
  444.       '=':Result := btEquals;
  445.       '@':Result := btSqrt;
  446.       '%':Result := btPercent;
  447.       'r','R': if not Ctrl then Result := btInverse
  448.            else Result := btMRecall;
  449.       'c','C': if not Ctrl then Result := btClear
  450.            else Result := btMClear;
  451.       'e','E': Result := btClearAll;
  452.       'm','M': if Ctrl then Result := btMStore;
  453.       'p','P': if Ctrl then Result := btMAdd;
  454.       'b','B': Result := btBackSpace;
  455.     end;
  456. end;
  457. procedure TwwCalculator.ResultKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  458. var c:Char;
  459.     code:Integer;
  460.     KeyState: TKeyboardState;
  461.     s:String;
  462. begin
  463.   if Key=16 then begin
  464.     inherited;
  465.     exit;
  466.   end;
  467.   if Key=vk_Return then c:='='
  468.   else if Key=vk_Delete then c:='c'
  469.   else if Key=vk_Back then c:='b'
  470.   else if Key=vk_Escape then c:='e'
  471.   else begin
  472.     Code := MapVirtualKey(Key, 2);
  473.     c:=char(code);
  474.     if (ssShift in Shift) then begin
  475.        case c of
  476.        '=':c:='+';
  477.        '5':c:='%';
  478.        '8':c:='*';
  479.        end;
  480.     end;
  481.   end;
  482.   DoCalc(CharToOp(c,(ssCtrl in Shift)));
  483.   inherited;
  484.   FResultEdit.SelStart := Length(FResultEdit.Text);
  485. end;
  486. function TwwCalculator.OpToChar(aOp:TwwCalcButtonType):Char;
  487. begin
  488.   Result := ' ';
  489.     case aOP of
  490.         btNone : Result := ' ';
  491.         bt0 : Result := '0';
  492.         bt1 : Result := '1';
  493.         bt2 : Result := '2';
  494.         bt3 : Result := '3';
  495.         bt4 : Result := '4';
  496.         bt5 : Result := '5';
  497.         bt6 : Result := '6';
  498.         bt7 : Result := '7';
  499.         bt8 : Result := '8';
  500.         bt9 : Result := '9';
  501.         btDecimal : Result := DecimalSeparator;
  502.         btPlusMinus : Result := '_';
  503.         btMultiply: Result := '*';
  504.         btDivide: Result := '/';
  505.         btAdd: Result := '+';
  506.         btSubtract: Result := '-';
  507.         btEquals:Result :='=';
  508.         btSqrt:Result := '@';
  509.         btPercent:Result :='%';
  510.         btInverse:Result := 'i';
  511.         btBackspace:Result := 'b';
  512.         btClear :Result := 'd';
  513.         btClearAll: Result := 'e';
  514.         btMRecall: Result := 'r';
  515.         btMStore: Result := 'm';
  516.         btMClear: Result := 'c';
  517.         btMAdd: Result := 'a';
  518.     end;
  519. end;
  520. procedure TwwCalculator.WMSize(var Message: TWMSize);
  521. var NewBoundsRect: TRect;
  522.   function sameRect(rect1, rect2: TRect): boolean;
  523.   begin
  524.      result:=
  525.       (rect1.left = rect2.left) and
  526.       (rect1.right = rect2.right) and
  527.       (rect1.top = rect2.top) and
  528.       (rect1.bottom = rect2.bottom);
  529.   end;
  530. begin
  531.   inherited;
  532.   NewboundsRect:= Rect(0, 0, BoundsRect.right-BoundsRect.left, BoundsRect.bottom-BoundsRect.top);
  533.   if SameRect(OldBoundsRect, NewBoundsRect) then exit;
  534.   OldboundsRect:= NewBoundsRect;
  535.   InitBitmapsFlag:= True;
  536.   if csLoading in COmponentState then exit;
  537.   CalcButtons;
  538. end;
  539. procedure TwwCalculator.Paint;
  540. const
  541.   Alignments: array[TAlignment] of Longint = (DT_LEFT, DT_RIGHT, DT_CENTER);
  542. var NewboundsRect: TRect;
  543.     ARect: TRect;
  544.     TopColor, BottomColor: TColor;
  545.     i,j:integer;
  546.     BtnShadow,BtnLight:TColor;
  547.     procedure AdjustColors(Bevel: TPanelBevel);
  548.     begin
  549.       TopColor := clBtnHighlight;
  550.       if Bevel = bvLowered then TopColor := clBtnShadow;
  551.       BottomColor := clBtnShadow;
  552.       if Bevel = bvLowered then BottomColor := clBtnHighlight;
  553.     end;
  554. begin
  555.   if InitBitmapsFlag and ((not BackGroundBitmap.Bitmap.Empty) or (not BackGroundBitmap.Graphic.Empty)) then begin
  556.      NewboundsRect:= Rect(0, 0, BoundsRect.right-BoundsRect.left, BoundsRect.bottom-BoundsRect.top);
  557.      PaintBitmap.Width := NewBoundsRect.right;
  558.      PaintBitmap.Height:= NewBoundsRect.Bottom;
  559.      PaintBitmap.TransparentMode := tmFixed;
  560.      PaintBitmap.TransparentColor := clNone;
  561.      case BackgroundBitmapDrawStyle of
  562.         cbdTile:
  563.              begin
  564.                 with BackgroundBitmap do begin
  565.                   i := 0;
  566.                   while i < Self.Width do begin
  567.                     j := 0;
  568.                     while j < Self.Height do begin
  569.                        PaintBitmap.Canvas.Draw(i,j,Graphic);
  570.                       // r:=rect(i,j,i+Bitmap.width,j+Bitmap.height);
  571.                       // PaintBitmap.canvas.CopyRect(r,backgroundbitmap.bitmap.canvas,r);
  572.                        inc(j, Bitmap.Height);
  573.                     end;
  574.                     inc(i, Bitmap.Width);
  575.                   end;
  576.                 end
  577.              end;
  578.         cbdTopLeft:
  579.              begin
  580.                 with BackgroundBitmap do
  581.                    PaintBitmap.Canvas.Draw(0, 0, Graphic);
  582.              end;
  583.         cbdCenter:
  584.              begin
  585.                 with BackgroundBitmap do
  586.                    PaintBitmap.Canvas.Draw((self.width-Width)div 2,
  587.                                (self.Height-Height) div 2, Graphic);
  588.              end;
  589.         cbdStretch:
  590.              begin
  591.                 with BackgroundBitmap do
  592.                    PaintBitmap.Canvas.StretchDraw(Rect(0, 0, newBoundsRect.right, NewBoundsRect.bottom), Graphic);
  593.              end;
  594.    end;
  595.    InitBitmapsFlag:= False;
  596.   end;
  597.   ARect := GetClientRect;
  598.   if ((not BackGroundBitmap.Bitmap.Empty) or (not BackGroundBitmap.Graphic.Empty)) then
  599.      Canvas.CopyRect(ARect,PaintBitmap.Canvas,Rect(0,0,Width,Height))
  600.   else
  601.   begin
  602.     with Canvas do
  603.     begin
  604.       Brush.Color := PanelColor;
  605.       FillRect(ARect);
  606.     end;
  607.   end;
  608.   if cboHideBorder in Options then exit;
  609.   if Border3D then begin
  610.     BtnShadow:= changeColor(Color,False);
  611.     BtnLight := changeColor(Color,True);
  612.     Frame3D(Canvas, ARect, BtnLight, clBlack, 1);
  613.     Frame3D(Canvas, ARect, clWhite, BtnShadow, 1);
  614.   end
  615.   else begin
  616.     Frame3D(Canvas, ARect, clWhite, clBlack, 1);
  617.   end;
  618. end;
  619. procedure TwwCalculator.CalcButtons;
  620. var
  621.   j: integer;
  622.   i,bt:TwwCalcButtonType;
  623.   calccolor:TCOlor;
  624.   BtnWidth,BtnHeight :integer;
  625.   clrbtnw,clrbtnh:integer;
  626.   numbuttonsx,numbuttonsy:integer;
  627.   row,col:integer;
  628.   x,y:integer;
  629.   startoffset:integer;
  630.   pad:integer;
  631.   flag:boolean;
  632. begin
  633.   numbuttonsx:=6;
  634.   numbuttonsy:=5;
  635.   if not (cboHideEditor in Options) then inc(numbuttonsy);
  636.   if (cboShowStatus in Options) then inc(numbuttonsy);
  637.   x:= Width-ButtonMargin*(numbuttonsx-1)-(5+5+5);
  638.   y:= Height-ButtonMargin*(numbuttonsy-1)-10;
  639.   btnwidth := x div numbuttonsx;
  640.   btnHeight := y div numbuttonsy;
  641.   if cboHideEditor in Options then row := 1
  642.   else row := 2;
  643.   Btns[btMClear] := ButtonRecord(btMClear,5+row*(btnheight+ButtonMargin), 5, BtnWidth, btnHeight, 'MC',clRed,'Clears any number stored in memory.'+#13#10+#13#10+'Keyboard equivalent = CTRL + L');
  644.   inc(row);
  645.   Btns[btMRecall] := ButtonRecord(btMRecall,5+row*(btnheight+ButtonMargin), 5, btnwidth, btnHeight, 'MR',clRed,'Recalls the number stored in memory.');
  646.   inc(row);
  647.   Btns[btMStore] := ButtonRecord(btMStore,5+row*(btnheight+ButtonMargin), 5, btnwidth, btnHeight, 'MS',clRed,'Stores the displayed number in memory.');
  648.   inc(row);
  649.   Btns[btMAdd] := ButtonRecord(btMAdd,5+row*(btnheight+ButtonMargin), 5, btnwidth, btnHeight, 'M+',clRed,'Adds displayed number to number in memory.');
  650.   clrbtnw := (width - 15-btnwidth-ButtonMargin*3) div 3;
  651.   if cboHideEditor in Options then clrbtnh:=5
  652.   else clrbtnh:=5+btnheight+ButtonMargin;
  653.   Btns[btBackspace] := ButtonRecord(btBackSpace,clrbtnh,Width-5-clrbtnw-2*(clrbtnw+ButtonMargin), clrbtnw, btnHeight, 'Back',clRed,'Deletes last digit of displayed number.');
  654.   Btns[btClear] := ButtonRecord(btClear,clrbtnh, Width-5-(clrbtnw+ButtonMargin)-clrbtnw, clrbtnw, btnHeight, 'CE', clRed,'Clears displayed number.');
  655.   Btns[btClearAll] := ButtonRecord(btClearAll,clrbtnh, Width-5-clrbtnw, clrbtnw, btnHeight, 'C', clRed,'Clears the current calculation.');
  656.   pad := ((Width-5-BtnWidth)-4*(BtnWidth+ButtonMargin)) - (Width-5-clrbtnw-2*(clrbtnw+ButtonMargin));
  657.   if pad <= 0 then pad := 0;
  658.   if cboHideEditor in Options then row := 1
  659.   else row := 2;
  660.   Btns[bt7] := ButtonRecord(bt7,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-4*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '7',clBlue,'Puts this number in display.');
  661.   inc(row);
  662.   Btns[bt4] := ButtonRecord(bt4,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-4*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '4',clBlue,'Puts this number in display.');
  663.   inc(row);
  664.   Btns[bt1] := ButtonRecord(bt1,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-4*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '1',clBlue,'Puts this number in display.');
  665.   inc(row);
  666.   Btns[bt0] := ButtonRecord(bt0,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-4*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '0',clBlue,'Puts this number in display.');
  667.   if cboHideEditor in Options then row := 1
  668.   else row := 2;
  669.   Btns[bt8] := ButtonRecord(bt8,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-3*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '8',clBlue,'Puts this number in display.');
  670.   inc(row);
  671.   Btns[bt5] := ButtonRecord(bt5,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-3*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '5',clBlue,'Puts this number in display.');
  672.   inc(row);
  673.   Btns[bt2] := ButtonRecord(bt2,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-3*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '2',clBlue,'Puts this number in display.');
  674.   inc(row);
  675.   Btns[btPlusMinus] := ButtonRecord(btPlusMinus,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-3*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '+/-',clBlue,'Changes sign of displayed number.');
  676.   if cboHideEditor in Options then row := 1
  677.   else row := 2;
  678.   Btns[bt9] := ButtonRecord(bt9,5+row*(btnheight+ButtonMargin),-pad+(Width-5-BtnWidth)-2*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '9',clBlue,'Puts this number in display.');
  679.   inc(row);
  680.   Btns[bt6] := ButtonRecord(bt6,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-2*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '6',clBlue,'Puts this number in display.');
  681.   inc(row);
  682.   Btns[bt3] := ButtonRecord(bt3,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-2*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '3',clBlue,'Puts this number in display.');
  683.   inc(row);
  684.   Btns[btDecimal] := ButtonRecord(btDecimal,5+row*(btnheight+ButtonMargin),-pad+ (Width-5-BtnWidth)-2*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '.',clBlue,'Inserts a decimal point.');
  685.   if cboHideEditor in Options then row := 1
  686.   else row := 2;
  687.   Btns[btDivide] := ButtonRecord(btDivide,5+row*(btnheight+ButtonMargin), (Width-5-BtnWidth)-1*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '/',clRed,'Divides.');
  688.   inc(row);
  689.   Btns[btMultiply] := ButtonRecord(btMultiply,5+row*(btnheight+ButtonMargin), (Width-5-BtnWidth)-1*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '*',clRed,'Multiplies.');
  690.   inc(row);
  691.   Btns[btSubtract] := ButtonRecord(btSubtract,5+row*(btnheight+ButtonMargin), (Width-5-BtnWidth)-1*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '-',clRed,'Subtracts.');
  692.   inc(row);
  693.   Btns[btAdd] := ButtonRecord(btAdd,5+row*(btnheight+ButtonMargin), (Width-5-BtnWidth)-1*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '+',clRed,'Adds.');
  694.   if cboHideEditor in Options then row := 1
  695.   else row := 2;
  696.   Btns[btsqrt] := ButtonRecord(btsqrt,5+row*(btnheight+ButtonMargin), (Width-5-BtnWidth)-0*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, 'sqrt',clBlue,'Calculates squareroot of number.');
  697.   inc(row);
  698.   Btns[btPercent] := ButtonRecord(btPercent,5+row*(btnheight+ButtonMargin), (Width-5-BtnWidth)-0*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '%',clBlue,'Displays result of multiplication as percentage.');
  699.   inc(row);
  700.   Btns[btInverse] := ButtonRecord(btInverse,5+row*(btnheight+ButtonMargin), (Width-5-BtnWidth)-0*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '1/x',clBlue,'Calculates the reciprocal.');
  701.   inc(row);
  702.   Btns[btEquals] := ButtonRecord(btEquals,5+row*(btnheight+ButtonMargin), (Width-5-BtnWidth)-0*(BtnWidth+ButtonMargin), BtnWidth, btnHeight, '=',clRed,'Performs any operation on previous numbers.');
  703.   flag := False;
  704.   for j:= 0 to ControlCount-1 do
  705.     if COntrols[j] is TwwCalcButton then flag := True;
  706.   if flag then begin
  707.     for j:= 0 to ControlCount-1 do
  708.     if COntrols[j] is TwwCalcButton then
  709.       with  TwwCalcButton(Controls[j]) do begin
  710.          SetBounds(Btns[fbtntype].Left, Btns[fbtntype].Top, Btns[fbtntype].Width,Btns[fbtntype].Height);
  711.          ButtonFontColor := Btns[fbtntype].Color;
  712.          ButtonColor := PanelColor;
  713.          Hint := Btns[fbtnType].Hint;
  714.          FOptions := Options;
  715.          Font.Height := self.Font.Height;
  716.          Font.Name := self.Font.Name;
  717.          Font.Style := self.Font.Style;
  718.          if (FBackGroundBitmap <> nil) and (FBackGroundBitmap.Graphic <> nil) and not FBackgroundbitmap.Graphic.empty then
  719.             FTransparent := True
  720.          else FTransparent := False;
  721.       end;
  722.   end
  723.   else begin
  724.     for i := Low(TwwCalcButtonType) to High(TwwCalcButtonType) do
  725.       with TwwCalcButton.Create(Self) do begin
  726.         Parent := Self;
  727.         SetBounds(Btns[i].Left, Btns[i].Top, Btns[i].Width,Btns[i].Height);
  728.         fBtnType:=Btns[i].BtnType;
  729.         Hint := Btns[i].Hint;
  730.         Caption := Btns[i].Caption;
  731.         ButtonFontColor := Btns[i].Color;
  732.         ButtonColor := PanelColor;
  733.         OnClick := Compute;
  734.         FOptions := Options;
  735.         Font.Height := self.Font.Height;
  736.         Font.Name := self.Font.Name;
  737.         Font.Style := self.Font.Style;
  738.         if (FBackGroundBitmap <> nil) and (FBackGroundBitmap.Graphic <> nil) and not FBackgroundbitmap.Graphic.empty then
  739.            FTransparent := True
  740.         else FTransparent := False;
  741.         Tag := Ord(i);
  742.      end;
  743.   end;
  744.   if FMemoryBevel = nil then begin
  745.     FMemoryBevel := TwwCalcBevel.Create(Self);
  746.     FMemoryBevel.Parent := Self;
  747.   end;
  748.   with FMemoryBevel do begin
  749.     Parent := Self;
  750.     SetBounds(5,clrBtnh+1,BtnWidth,BtnHeight-1);
  751.     FColor := PanelColor;
  752.   end;
  753.   if FMemoryStatus = nil then begin
  754.     FMemoryStatus := TwwCalcLabel.Create(Self);
  755.     with FMemoryStatus do begin
  756.        Parent := Self;
  757.        Autosize := False;
  758.        Transparent := True;
  759.        Alignment := taCenter;
  760.     end;
  761.   end;
  762.   j := clrbtnh;
  763.   with FMemoryStatus do begin
  764.     Font.Height := self.Font.Height;
  765.     Font.Name := self.Font.Name;
  766.     Font.Style := self.Font.Style;
  767.     SetBounds(5,j+((BtnHeight-FMemoryStatus.Canvas.textheight('M'))div 2),BtnWidth,BtnHeight);
  768.   end;
  769.   if FResultEdit = nil then begin
  770.      FResultEdit := TwwDBEdit.Create(Self);
  771.      with FResultEdit do begin
  772.        Parent := Self;
  773.        Visible := not (cboHideEditor in Options);
  774.        AutoSize := False;
  775.        EditAlignment := eaRightAlignEditing;
  776.        TLabel(FResultEdit).Alignment := taRightJustify;
  777.        Font.Height := -13;
  778.        Font.Name := 'Arial';
  779.        Font.Style := [];
  780.        Text := '0';
  781.        ReadOnly := True;
  782.        OnKeyDown := ResultKeyDown;
  783.      end;
  784.   end;
  785.   if (cboHideEditor in Options) then FResultEdit.Visible := False
  786.   else if (csDesigning in ComponentState) then FResultEdit.Visible := True;
  787.   if not FResultEdit.Visible and (csDesigning in ComponentState) then
  788.      FResultEdit.SetBounds(5, 5, 0, 0)
  789.   else FResultEdit.SetBounds(5, 5, Width-10, btnHeight);
  790.   if (cboShowStatus in Options) then begin
  791.     if (FStatusBevel = nil) then begin
  792.        FStatusBevel := TwwCalcBevel.Create(Self);
  793.        FStatusBevel.Parent := Self;
  794.     end;
  795.     if (FStatusLabel = nil) then begin
  796.        FStatusLabel := TLabel.Create(Self);
  797.        with FStatusLabel do begin
  798.           Parent := Self;
  799.           Autosize := False;
  800.           Transparent := True;
  801.           Alignment := taLeftJustify;
  802.           Font.Height := self.Font.Height;
  803.           Font.Name := self.Font.Name;
  804.           Font.Style := self.Font.Style;
  805.        end;
  806.     end;
  807.     FStatusBevel.SetBounds(5, Height-5-btnHeight, Width-10,btnHeight);
  808.     FStatusLabel.SetBounds(9, Height-5-btnHeight+((BtnHeight-FMemoryStatus.Canvas.textheight('M'))div 2), Width-16,btnHeight-4);
  809.   end
  810.   else if not (cboShowStatus in Options) then begin
  811.     if FStatusBevel <> nil then begin
  812.        FStatusBevel.Visible := False;
  813.        FStatusBevel.SetBounds(5, Height-5-FStatusBevel.height, 0,0);
  814.        FStatusBevel.Free;
  815.        FStatusBevel := nil;
  816.     end;
  817.     if FStatusLabel <> nil then begin
  818.        FStatusLabel.Visible := False;
  819.        FStatusLabel.SetBounds(7, Height-5-btnHeight+2,0,0);
  820.        FStatusLabel.Free;
  821.        FStatusLabel := nil;
  822.     end;
  823.   end;
  824.   FullRepaint;
  825. end;
  826. procedure TwwCalculator.WMEraseBkgnd(var Message: TWmEraseBkgnd);
  827. begin
  828.   Message.result:= 1;
  829. end;
  830. Procedure TwwCalculator.Reset; {Clear everything out}
  831. begin
  832.     FCurrentValue := 0.0;
  833.     FResultEdit.Text := '0';
  834.     FDecimalEntered:=False;
  835.     FResultValue:=0.0;
  836.     if FStatusLabel <> nil then FStatusLabel.Caption:='';
  837.     FClearOnNextKey:=false;
  838.     FLastOp:=btNone;
  839.     FNextToLastOp:=btNone;
  840.     FLastStatus:='';
  841.     FLastOperatorEquals := false;
  842.     FLastOperand:=0.0;
  843. end;
  844. procedure TwwCalculator.Compute(Sender: TObject);
  845. begin
  846.   DoCalc(TwwCalcButtonType(TSpeedButton(Sender).Tag));
  847. end;
  848. procedure TwwCalculator.DoCalc(ButtonType:TwwCalcButtonType);
  849. const
  850.   MemoryStoreMap: array [Boolean] of string = (' M','');
  851. var
  852.   Temp: string;
  853.   TempValue: Double;
  854.   flag:boolean;
  855. begin
  856.   try
  857.    case ButtonType of
  858.     bt0..bt9:
  859.      begin
  860.         if FClearOnNextKey then begin
  861.            if FLastOperatorEquals then Reset
  862.            else FResultEdit.Text := '0';
  863.         end;
  864.         FClearOnNextKey := false;
  865.         if (FResultEdit.Text = '0') or (FCurrentValue = 0) then
  866.            FResultEdit.Text := '';
  867.         FBackSpaceValid := True;
  868.         FResultEdit.Text := FResultEdit.Text + Btns[ButtonType].Caption;
  869.         FCurrentValue := StrToFloat(FResultEdit.Text);
  870.         if (FStatusLabel <> nil) then
  871.            FStatusLabel.Caption:=FStatusLabel.Caption+OpToChar(ButtonType);
  872.      end;
  873.     btDecimal:
  874.      begin
  875.         if FClearOnNextKey then Reset;
  876.         If not FDecimalEntered then begin
  877.            FCurrentValue := StrToFloat(FResultEdit.Text);
  878.            FResultEdit.Text := FResultEdit.Text + Btns[ButtonType].Caption;
  879.            if (FStatusLabel <> nil) then
  880.               FStatusLabel.Caption:=FStatusLabel.Caption+OpToChar(ButtonType);
  881.            FDecimalEntered:=true;
  882.         end
  883.         else Beep;
  884.      end;
  885.     btPlusMinus:
  886.      begin
  887.       FCurrentValue := StrToFloat(FResultEdit.Text) * -1;
  888.       FResultEdit.Text := FloatToStr(FCurrentValue);
  889.       if FStatusLabel <> nil then begin
  890.          if FClearOnNextKey then
  891.            FStatusLabel.Caption := '0'
  892.          else
  893.            FStatusLabel.Caption := FLastStatus+FResultEdit.Text;
  894.       end;
  895.      end;
  896.     btClearAll:
  897.      begin
  898.       Reset;
  899.      end;
  900.     btClear:
  901.      begin
  902.       FCurrentValue := 0;
  903.       FResultEdit.Text := '0';
  904.       if FStatusLabel <> nil then begin
  905.          if FClearOnNextKey then
  906.            FStatusLabel.Caption := '0'
  907.          else
  908.            FStatusLabel.Caption := FLastStatus;
  909.       end;
  910.      end;
  911.     btPercent,btAdd,btSubtract,btDivide,btMultiply,btEquals:
  912.      begin
  913.        TempValue := StrToFloat(FResultEdit.Text);
  914.        if (Length(FResultEdit.Text) > 0) and (ButtonType <> btEquals) then begin
  915.           if (FLastOperatorEquals) then begin
  916.               FLastOperand := TempValue;
  917.               FLastOp := ButtonType;
  918.               FLastOperatorEquals := False;
  919.               if FStatusLabel <> nil then
  920.                  FStatusLabel.Caption:=FLastStatus+OpToChar(ButtonType);
  921.               FLastStatus := FStatusLabel.Caption;
  922.               FCurrentValue := 0;
  923.           end
  924.           else if not(FLastOp in [btMultiply,btDivide,btAdd,btSubtract,btPercent]) then
  925.           begin
  926.              FLastOperand := TempValue;
  927.              FLastOp := ButtonType;
  928.              FResultValue:=tempvalue;
  929.              if FStatusLabel <> nil then
  930.                 FStatusLabel.Caption:=FStatusLabel.Caption+OpToChar(ButtonType);
  931.              FLastStatus := FStatusLabel.Caption;
  932.              FCurrentValue := 0;
  933.           end
  934.           else if (FLastOp in [btMultiply,btDivide,btAdd,btSubtract]) then begin
  935.              if ButtonType = btPercent then begin
  936.                 fResultValue := (fResultValue * TempValue)/100.0;
  937.                 fLastOperand := TempValue;
  938.              end
  939.              else begin
  940.                case FLastOp of
  941.                  btMultiply: fResultValue := fResultValue * TempValue;
  942.                  btDivide: fResultValue := fResultValue / TempValue;
  943.                  btAdd: fResultValue := fResultValue + TempValue;
  944.                  btSubtract: fResultValue := fResultValue - TempValue;
  945.                end;
  946.                FLastOperand := TempValue;
  947.              end;
  948.              if (FStatusLabel <> nil) then begin
  949.                 If ((ButtonType = btMultiply) or (ButtonType=btDivide))
  950.                   and ((FLastOp = btAdd) or (FLastOp=btSubtract)) then
  951.                       FStatusLabel.Caption:='('+FStatusLabel.Caption+')';
  952.                 FStatusLabel.Caption := FStatusLabel.Caption+OpToChar(ButtonType);
  953.                 FLastStatus := FStatusLabel.Caption;
  954.                 if ButtonType = btPercent then begin
  955.                    FLastStatus := FStatusLabel.Caption;
  956.                    FStatusLabel.Caption := FlastStatus+OpToChar(btEquals) + FloatToStr(FResultValue);
  957.                 end;
  958.              end;
  959.              FCurrentValue := 0;
  960.           end;
  961.           FLastOp:=ButtonType;
  962.           FResultEdit.Text := FloatToStr(FResultValue);
  963.           FCurrentValue := 0;
  964.        end
  965.        else if (Length(FResultEdit.Text) > 0)then begin
  966.           if FLastOperatorEquals or (FLastOp = btPercent) then TempValue := FLastOperand
  967.           else FLastOperand := TempValue;
  968.           case FLastOp of
  969.             btPercent: fResultValue := (fResultValue * FLastOperand)/100.0;
  970.             btMultiply: fResultValue := fResultValue * TempValue;
  971.             btDivide: fResultValue := fResultValue / TempValue;
  972.             btAdd: fResultValue := fResultValue + TempValue;
  973.             btSubtract: fResultValue := fResultValue - TempValue;
  974.           end;
  975.           if StatusLabel <> nil then begin
  976.              if FLastOperatorEquals then begin
  977.                 FStatusLabel.Caption := FLastStatus;
  978.                 FStatusLabel.Caption := FStatusLabel.Caption + OpToChar(FLastOp) + FloatToStr(FLastOperand);
  979.              end
  980.              else if FLastOp = btPercent then begin
  981.                 FStatusLabel.Caption := FLastStatus;
  982.                 FStatusLabel.Caption:='('+FStatusLabel.Caption+')'+FloatToStr(FLastOperand)+Optochar(btPercent);
  983.              end;
  984.              FStatusLabel.Caption:='('+FStatusLabel.Caption+')';
  985.              FLastStatus := FStatusLabel.Caption;
  986.              FStatusLabel.Caption := FStatusLabel.Caption+OpToChar(ButtonType);
  987.              FStatusLabel.Caption := FStatusLabel.Caption + FloatToStr(FResultValue);
  988.           end;
  989.           FLastOperatorEquals := True;
  990.           FResultEdit.Text := FloatToStr(FResultValue);
  991.           FClearOnNextKey := True;
  992.           FCurrentValue := 0;
  993.        end
  994.        else Beep;
  995.     end;
  996.     btBackSpace:
  997.      if FBackSpaceValid then begin
  998.       Temp := FResultEdit.Text;
  999.       if Temp[Length(Temp)] in ['0'..'9'] then
  1000.       begin
  1001.         Delete(Temp, Length(Temp),1);
  1002.         if Temp = '' then begin
  1003.           FBackSpaceValid := False;
  1004.           Temp := '0';
  1005.         end;
  1006.         FCurrentValue := StrToFloat(Temp);
  1007.         FResultEdit.Text := FloatToStr(FCurrentValue);
  1008.         if FStatusLabel <> nil then begin
  1009.            Temp := FStatusLabel.Caption;
  1010.            Delete(Temp, Length(Temp),1);
  1011.            FStatusLabel.Caption := Temp;
  1012.         end;
  1013.       end
  1014.       else begin
  1015.         if FStatusLabel <> nil then begin
  1016.            Temp := FStatusLabel.Caption;
  1017.            if Temp[Length(Temp)] = DecimalSeparator then begin
  1018.               FDecimalEntered := False;
  1019.               Delete(Temp, Length(Temp),1);
  1020.               FStatusLabel.Caption := Temp;
  1021.            end
  1022.            else FBackSpaceValid := False;
  1023.         end;
  1024.       end;
  1025.      end
  1026.      else Beep;
  1027.     btInverse:
  1028.      begin
  1029.       FCurrentValue := 1 / StrToFloat(FResultEdit.Text);
  1030.       FResultEdit.Text := FloatToStr(FCurrentValue);
  1031.       if FStatusLabel <> nil then begin
  1032.          if FClearOnNextKey then
  1033.            FStatusLabel.Caption := '0'
  1034.          else
  1035.            FStatusLabel.Caption := FLastStatus+FResultEdit.Text;
  1036.       end;
  1037.      end;
  1038.     btSqrt:
  1039.      begin
  1040.       FCurrentValue := Sqrt(StrToFloat(FResultEdit.Text));
  1041.       FResultEdit.Text := FloatToStr(FCurrentValue);
  1042.       if FStatusLabel <> nil then begin
  1043.          if FClearOnNextKey then
  1044.            FStatusLabel.Caption := '0'
  1045.          else
  1046.            FStatusLabel.Caption := FLastStatus+FResultEdit.Text;
  1047.       end;
  1048.      end;
  1049.     btMStore:
  1050.      begin
  1051.       FMemoryValue := StrToFloat(FResultEdit.Text);
  1052.       FMemoryValue := FMemoryValue * 1;
  1053.       FCurrentValue := 0;
  1054.      end;
  1055.     btMAdd:
  1056.      begin
  1057.       TempValue := FMemoryValue;
  1058.       FMemoryValue := StrToFloat(FResultEdit.Text);
  1059.       FMemoryValue := (FMemoryValue * 1) + TempValue;
  1060.      end;
  1061.     btMRecall:
  1062.      begin
  1063.       FResultEdit.Text := FloatToStr(FMemoryValue);
  1064.       FCurrentValue := 0;
  1065.      end;
  1066.     btMClear:
  1067.      begin
  1068.       FMemoryValue := 0;
  1069.      end;
  1070.    end;   // case  ButtonType of...
  1071.    except
  1072.      on E: Exception do begin
  1073.       FResultEdit.Text := E.Message;
  1074.       Reset;
  1075.      end;
  1076.    end;
  1077.   FMemoryStatus.Caption := MemoryStoreMap[FMemoryValue = 0];
  1078. end;
  1079. function TwwCalculator.IsBinaryOperator(ButtonType: TwwCalcButtonType):boolean;
  1080. begin
  1081.  result := False;
  1082.  case ButtonType of
  1083.  btMultiply,btDivide,btAdd,btSubtract,btEquals: result := True;
  1084.  end;
  1085. end;
  1086. procedure TwwCalculator.SetBackgroundBitmapDrawStyle(Value: TwwCalcBitmapDrawStyle);
  1087. begin
  1088.    if Value<>FBackgroundBitmapDrawStyle then
  1089.    begin
  1090.       FBackgroundBitmapDrawStyle:= Value;
  1091.       FullRepaint;
  1092.    end
  1093. end;
  1094. procedure TwwCalculator.SetBackgroundBitmap(Value: TPicture);
  1095. var i:integer;
  1096. begin
  1097.    if (Value = nil) or (Value.Graphic=nil) or Value.Graphic.Empty then begin
  1098.      for i:= 0 to ControlCount-1 do begin
  1099.        if COntrols[i] is TwwCalcButton then
  1100.          TwwCalcButton(controls[i]).FTransparent := False;
  1101.      end;
  1102.    end
  1103.    else begin
  1104.     for i:= 0 to ControlCount-1 do begin
  1105.        if COntrols[i] is TwwCalcButton then
  1106.          TwwCalcButton(controls[i]).FTransparent := True;
  1107.     end;
  1108.    end;
  1109.    FBackGroundBitmap.Assign(Value);
  1110.    FPaintBitmap.FreeImage;
  1111.    InitBitmapsFlag := True;
  1112.    FullRepaint;
  1113. end;
  1114. function TwwCalculator.GetText: string;
  1115. begin
  1116.   Result := FResultEdit.Text;
  1117. end;
  1118. procedure TwwCalculator.SetBorder3D(const Value: Boolean);
  1119. begin
  1120.   if F3D <> Value then begin
  1121.     F3D := Value;
  1122.     invalidate;
  1123.   end;
  1124. end;
  1125. procedure TwwCalculator.SetText(const Value: string);
  1126. begin
  1127.   if FResultEdit <> nil then
  1128.      FResultEdit.Text := Value;
  1129. end;
  1130. procedure TwwCalculator.SetOptions(Value: TwwCalcOptions);
  1131. var ChangedOptions: TwwCalcOptions;
  1132. begin
  1133.   if FOptions <> Value then
  1134.   begin
  1135.     ChangedOptions := (FOptions - Value) + (Value - FOptions);
  1136.     FOptions := Value;
  1137.     if ChangedOptions <> [] then begin
  1138. {       for i:= 0 to ControlCount-1 do begin
  1139.          if COntrols[i] is TwwCalcButton then begin
  1140.            TwwCalcButton(controls[i]).FOptions := Value;
  1141.            if (FBackGroundBitmap <> nil) and (FBackGroundBitmap.Graphic <> nil) and not FBackgroundbitmap.Graphic.empty then
  1142.               TwwCalcButton(controls[i]).FTransparent := True
  1143.            else TwwCalcButton(controls[i]).FTransparent := False;
  1144.          end;
  1145.        end;}
  1146.        CalcButtons;
  1147.        FullRepaint;
  1148.     end;
  1149.   end;
  1150. end;
  1151. procedure TwwCalculator.RefreshSummary;
  1152. begin
  1153.   if StatusLabel <> nil then begin
  1154.      FStatusLabel.Caption := 'Calculator';
  1155.   end;
  1156. end;
  1157. procedure TwwCalculator.FullRepaint;
  1158. var i:integer;
  1159. begin
  1160.   InitBitmapsFlag:= True;
  1161.   invalidate;
  1162.   for i:= 0 to ControlCount-1 do begin
  1163.      controls[i].invalidate;
  1164.   end;
  1165. end;
  1166. procedure TwwCalculator.SetMargin(Value: Integer);
  1167. begin
  1168.   if FMargin <> Value then
  1169.   begin
  1170.      FMargin := Value;
  1171.      CalcButtons;
  1172.   end;
  1173. end;
  1174. procedure TwwCalculator.SetPanelColor(Value: TColor);
  1175. var i:integer;
  1176. begin
  1177.   if FPanelColor <> Value then
  1178.   begin
  1179.     FPanelColor := Value;
  1180.     Color := Value;
  1181.     if FMemoryStatus<>nil then
  1182.        FMemoryStatus.Color := Value;
  1183.     if FMemoryBevel <> nil then
  1184.        FMemoryBevel.FColor := Value;
  1185.     for i:= 0 to ControlCount-1 do begin
  1186.        if COntrols[i] is TwwCalcButton then
  1187.          TwwCalcButton(controls[i]).ButtonColor := Value;
  1188.     end;
  1189.     FullRepaint;
  1190.   end;
  1191. end;
  1192. procedure Register;
  1193. begin
  1194.   RegisterComponents('Samples', [TwwCalculator]);
  1195. end;
  1196. end.