home *** CD-ROM | disk | FTP | other *** search
/ Chip Hitware 6 B / CHIP_HITWARE6_B.iso / biuro / BaseCalculator / Sources / BCalcWin.pas < prev    next >
Pascal/Delphi Source File  |  1996-11-06  |  25KB  |  788 lines

  1. unit BCalcWin;
  2.  
  3. {************************************************************************
  4. *                                                                       *
  5. *                        Calculator User Interface                      *
  6. *                                                                       *
  7. ************************************************************************}
  8.  
  9. { Author:    John Zaitseff <J.Zaitseff@unsw.edu.au>
  10.   Date:      6th November, 1996.
  11.   Version:   1.2
  12.  
  13.   This file provides the user interface code for the Base Calculator.
  14.   Note that the Tag property of buttons, radio buttons and check-boxes
  15.   is used for two purposes:  as the context-sensitive help identifier,
  16.   and as the "keypress value" + some offset.  The TagOfsXXX identifiers
  17.   list the offsets used.  If these are changed, the help file and parts
  18.   of this code must also be changed.
  19.  
  20.   This program, including this file, is under the terms of the GNU
  21.   General Public License.
  22. }
  23.  
  24. interface
  25.  
  26. uses
  27.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  28.   StdCtrls, ExtCtrls, Menus, Clipbrd, ComCtrls, Registry, Calc;
  29.  
  30. const
  31.   BeepType     = mb_IconExclamation;
  32.   RegKeyPrefix = '\Software\Zaitseff\Base Calculator\1.2';
  33.  
  34.   TagOfsNumKey = 2000;
  35.   TagOfsOpsKey = 3000;
  36.  
  37. type
  38.   { Base Calculator window class }
  39.   TBaseCalcWin = class(TForm)
  40.                    Result        : TLabel;
  41.                    Background    : TLabel;
  42.                    MemOcc        : TLabel;
  43.                    BaseGB        : TGroupBox;
  44.                    DecRB         : TRadioButton;
  45.                    HexRB         : TRadioButton;
  46.                    BinRB         : TRadioButton;
  47.                    OctRB         : TRadioButton;
  48.                    SizeGB        : TGroupBox;
  49.                    Size8RB       : TRadioButton;
  50.                    Size16RB      : TRadioButton;
  51.                    Size32RB      : TRadioButton;
  52.                    SignedCB      : TCheckBox;
  53.                    ClrBtn        : TButton;
  54.                    LeftBtn       : TButton;
  55.                    MInBtn        : TButton;
  56.                    MRBtn         : TButton;
  57.                    NotBtn        : TButton;
  58.                    AndBtn        : TButton;
  59.                    OrBtn         : TButton;
  60.                    NegBtn        : TButton;
  61.                    XorBtn        : TButton;
  62.                    EqvBtn        : TButton;
  63.                    Btn0          : TButton;
  64.                    Btn1          : TButton;
  65.                    Btn2          : TButton;
  66.                    Btn3          : TButton;
  67.                    Btn4          : TButton;
  68.                    Btn5          : TButton;
  69.                    Btn6          : TButton;
  70.                    Btn7          : TButton;
  71.                    Btn8          : TButton;
  72.                    Btn9          : TButton;
  73.                    BtnA          : TButton;
  74.                    BtnB          : TButton;
  75.                    BtnC          : TButton;
  76.                    BtnD          : TButton;
  77.                    BtnE          : TButton;
  78.                    BtnF          : TButton;
  79.                    MulBtn        : TButton;
  80.                    DivBtn        : TButton;
  81.                    SubBtn        : TButton;
  82.                    ModBtn        : TButton;
  83.                    AddBtn        : TButton;
  84.                    MPlusBtn      : TButton;
  85.                    EqualsBtn     : TButton;
  86.                    MainMenu      : TMainMenu;
  87.                    FileMenu      : TMenuItem;
  88.                    ExitMI        : TMenuItem;
  89.                    EditMenu      : TMenuItem;
  90.                    CopyMI        : TMenuItem;
  91.                    PasteMI       : TMenuItem;
  92.                    HelpMenu      : TMenuItem;
  93.                    HelpTopicsMI  : TMenuItem;
  94.                    AboutMI       : TMenuItem;
  95.                    N1            : TMenuItem;
  96.                    ValueMI       : TMenuItem;
  97.                    N2            : TMenuItem;
  98.                    PopupEditMenu : TPopupMenu;
  99.                    CopyPMI       : TMenuItem;
  100.                    PastePMI      : TMenuItem;
  101.                    N3            : TMenuItem;
  102.                    ValuePMI      : TMenuItem;
  103.                    PopupWhatMenu : TPopupMenu;
  104.                    WhatPMI       : TMenuItem;
  105.  
  106.                    procedure FormCreate (Sender : TObject);
  107.                    procedure FormClose (Sender : TObject; var Action : TCloseAction);
  108.                    procedure FormDestroy (Sender : TObject);
  109.                    procedure FormKeyDown (Sender : TObject; var Key : Word; Shift : TShiftState);
  110.                    procedure BaseRBClick (Sender : TObject);
  111.                    procedure SignedCBClick (Sender : TObject);
  112.                    procedure SizeCBClick (Sender : TObject);
  113.                    procedure NumBtnClick (Sender : TObject);
  114.                    procedure OpBtnClick (Sender : TObject);
  115.                    procedure ClrBtnClick (Sender : TObject);
  116.                    procedure LeftBtnClick (Sender : TObject);
  117.                    procedure MInBtnClick (Sender : TObject);
  118.                    procedure MRBtnClick (Sender : TObject);
  119.                    procedure MPlusBtnClick (Sender : TObject);
  120.                    procedure ExitMIClick (Sender : TObject);
  121.                    procedure EditMenuClick (Sender : TObject);
  122.                    procedure CopyMIClick (Sender : TObject);
  123.                    procedure PasteMIClick (Sender : TObject);
  124.                    procedure ValueMIClick (Sender : TObject);
  125.                    procedure HelpTopicsMIClick (Sender : TObject);
  126.                    procedure AboutMIClick (Sender : TObject);
  127.                    procedure WhatPMIClick (Sender : TObject);
  128.  
  129.                  private
  130.                    Calc    : TCalculator;
  131.                    RegData : TRegistry;
  132.  
  133.                    procedure CalcUpdateDisplay;
  134.                    procedure CalcUpdateButtons;
  135.                    procedure CalcEnableNumKeys;
  136.                    procedure CalcEnableClipboardOps;
  137.                  end;
  138.  
  139. var
  140.   BaseCalcWin : TBaseCalcWin;
  141.  
  142. implementation
  143.  
  144. uses
  145.   About, Value;
  146.  
  147. {$R *.DFM}
  148.  
  149. type
  150.   { Items to store in the Registry }
  151.   TRegStorage = packed record
  152.                   Mode   : TCalcMode;
  153.                   Signed : boolean;
  154.                   Size   : TCalcSize
  155.                 end;
  156.  
  157.  
  158. { Update the calculator display }
  159. procedure TBaseCalcWin.CalcUpdateDisplay;
  160.  
  161. begin
  162.   { Set the Memory indicator on or off }
  163.   if Calc.MemoryOccupied then
  164.     MemOcc.Caption := 'M'
  165.   else
  166.     MemOcc.Caption := ' ';
  167.  
  168.   { Display the actual value }
  169.   if Calc.InError then
  170.     Result.Caption := 'Error'
  171.   else
  172.     Result.Caption := Calc.CurrentString
  173. end;
  174.  
  175. { Update the various radio buttons and check boxes to reflect the current
  176.   state of the calculator.  Note that setting Checked to True for any
  177.   radio button automatically resets the others in that group. }
  178. procedure TBaseCalcWin.CalcUpdateButtons;
  179.  
  180. begin
  181.   case Calc.Mode of
  182.     Decimal     : DecRB.Checked := True;
  183.     Hexadecimal : HexRB.Checked := True;
  184.     Binary      : BinRB.Checked := True;
  185.     Octal       : OctRB.Checked := True
  186.   end;
  187.   SignedCB.Checked := Calc.Signed;
  188.  
  189.   case Calc.Size of
  190.     Size8  : Size8RB.Checked := True;
  191.     Size16 : Size16RB.Checked := True;
  192.     Size32 : Size32RB.Checked := True
  193.   end
  194. end;
  195.  
  196. { Enable the number keys, depending on the current mode }
  197. procedure TBaseCalcWin.CalcEnableNumKeys;
  198.  
  199. begin
  200.   { The brute-force method! }
  201.   case Calc.Mode of
  202.     Decimal     : begin
  203.                     Btn2.Enabled := True;
  204.                     Btn3.Enabled := True;
  205.                     Btn4.Enabled := True;
  206.                     Btn5.Enabled := True;
  207.                     Btn6.Enabled := True;
  208.                     Btn7.Enabled := True;
  209.                     Btn8.Enabled := True;
  210.                     Btn9.Enabled := True;
  211.                     BtnA.Enabled := False;
  212.                     BtnB.Enabled := False;
  213.                     BtnC.Enabled := False;
  214.                     BtnD.Enabled := False;
  215.                     BtnE.Enabled := False;
  216.                     BtnF.Enabled := False
  217.                   end;
  218.     Hexadecimal : begin
  219.                     Btn2.Enabled := True;
  220.                     Btn3.Enabled := True;
  221.                     Btn4.Enabled := True;
  222.                     Btn5.Enabled := True;
  223.                     Btn6.Enabled := True;
  224.                     Btn7.Enabled := True;
  225.                     Btn8.Enabled := True;
  226.                     Btn9.Enabled := True;
  227.                     BtnA.Enabled := True;
  228.                     BtnB.Enabled := True;
  229.                     BtnC.Enabled := True;
  230.                     BtnD.Enabled := True;
  231.                     BtnE.Enabled := True;
  232.                     BtnF.Enabled := True
  233.                   end;
  234.     Binary      : begin
  235.                     Btn2.Enabled := False;
  236.                     Btn3.Enabled := False;
  237.                     Btn4.Enabled := False;
  238.                     Btn5.Enabled := False;
  239.                     Btn6.Enabled := False;
  240.                     Btn7.Enabled := False;
  241.                     Btn8.Enabled := False;
  242.                     Btn9.Enabled := False;
  243.                     BtnA.Enabled := False;
  244.                     BtnB.Enabled := False;
  245.                     BtnC.Enabled := False;
  246.                     BtnD.Enabled := False;
  247.                     BtnE.Enabled := False;
  248.                     BtnF.Enabled := False
  249.                   end;
  250.     Octal       : begin
  251.                     Btn2.Enabled := True;
  252.                     Btn3.Enabled := True;
  253.                     Btn4.Enabled := True;
  254.                     Btn5.Enabled := True;
  255.                     Btn6.Enabled := True;
  256.                     Btn7.Enabled := True;
  257.                     Btn8.Enabled := False;
  258.                     Btn9.Enabled := False;
  259.                     BtnA.Enabled := False;
  260.                     BtnB.Enabled := False;
  261.                     BtnC.Enabled := False;
  262.                     BtnD.Enabled := False;
  263.                     BtnE.Enabled := False;
  264.                     BtnF.Enabled := False
  265.                   end
  266.   end
  267. end;
  268.  
  269. { Enable menu items under the Edit menu and popup depending on the
  270.   calculator state }
  271. procedure TBaseCalcWin.CalcEnableClipboardOps;
  272.  
  273. var
  274.   B : boolean;
  275.  
  276. begin
  277.   { Copy and Value menu items enabled if calculator is not in error }
  278.   B := not Calc.InError;
  279.   CopyMI.Enabled := B;
  280.   CopyPMI.Enabled := B;
  281.   ValueMI.Enabled := B;
  282.   ValuePMI.Enabled := B;
  283.  
  284.   { Paste menu item enabled if clipboard has appropriate format available }
  285.   B := Clipboard.HasFormat(CF_TEXT);
  286.   PasteMI.Enabled := B;
  287.   PastePMI.Enabled := B
  288. end;
  289.  
  290.  
  291. { Create the actual calculator state machine and initialise it with values
  292.   stored in the Registry }
  293. procedure TBaseCalcWin.FormCreate (Sender : TObject);
  294.  
  295. var
  296.   CalcState : TRegStorage;
  297.  
  298. begin
  299.   Calc := TCalculator.Create;
  300.   RegData := TRegistry.Create;
  301.  
  302.   Calc.ClearAll;
  303.  
  304.   { Use Registry to get the previous calculator settings }
  305.   RegData.RootKey := HKEY_CURRENT_USER;
  306.   if RegData.OpenKey(RegKeyPrefix, False) and
  307.      (RegData.ReadBinaryData('CalcState', CalcState,
  308.          sizeof(CalcState)) = sizeof(CalcState)) then
  309.     begin
  310.       { Registry path RegKeyPrefix exists and registry key "CalcState"
  311.         contains valid data }
  312.       with CalcState do
  313.         begin
  314.           Calc.Mode := Mode;
  315.           Calc.Signed := Signed;
  316.           Calc.Size := Size
  317.         end
  318.     end
  319.   else
  320.     begin
  321.       { The registry key does not exist or is not valid: use default values }
  322.       Calc.Mode := Decimal;
  323.       Calc.Signed := True;
  324.       Calc.Size := Size32
  325.     end;
  326.   RegData.CloseKey;
  327.  
  328.   CalcUpdateDisplay;
  329.   CalcUpdateButtons;
  330.   CalcEnableNumKeys;
  331.  
  332.   CalcEnableClipboardOps
  333. end;
  334.  
  335. { Save the current settings of the calculator into the registry }
  336. procedure TBaseCalcWin.FormClose (Sender : TObject; var Action : TCloseAction);
  337.  
  338. var
  339.   CalcState : TRegStorage;
  340.  
  341. begin
  342.   { Close WinHelp, if it was opened }
  343.   Application.HelpCommand(Help_Quit,0);
  344.  
  345.   { Use Registry to save the current calculator settings }
  346.   RegData.RootKey := HKEY_CURRENT_USER;
  347.   if RegData.OpenKey(RegKeyPrefix, True) then
  348.     begin
  349.       with CalcState do
  350.         begin
  351.           Mode := Calc.Mode;
  352.           Signed := Calc.Signed;
  353.           Size := Calc.Size
  354.         end;
  355.  
  356.       RegData.WriteBinaryData('CalcState', CalcState, sizeof(CalcState))
  357.     end;
  358.   RegData.CloseKey
  359. end;
  360.  
  361. { Free up memory associated with this application }
  362. procedure TBaseCalcWin.FormDestroy (Sender : TObject);
  363.  
  364. begin
  365.   RegData.Free;
  366.   Calc.Free
  367. end;
  368.  
  369. { Handle keypresses in the application.  Note that the active control
  370.   will still get the key, even if Key is set to 0.  Hence, <ENTER> will
  371.   still activate the control, even if handled here.  Menu shortcuts are
  372.   also handled automatically. }
  373. procedure TBaseCalcWin.FormKeyDown (Sender : TObject; var Key : Word; Shift : TShiftState);
  374.  
  375. const
  376.   VK_PLEQ  = 187;    { '+' '=' }
  377.   VK_UNDER = 189;    { '_' '-' }
  378.   VK_QUEST = 191;    { '?' '/' }
  379.   VK_TILDE = 192;    { '~' '`' }
  380.   VK_BAR   = 220;    { '|' '\' }
  381.  
  382. type
  383.   TBtnType = (bt_None, bt_Btn, bt_RadioBtn, bt_CheckBox);
  384.  
  385. var
  386.   Btn      : ^TWinControl;
  387.   BtnType  : TBtnType;
  388.  
  389. begin
  390.   { If keypress is simply <SHIFT> or <CTRL>, abort trying to handle it }
  391.   if (Key = VK_SHIFT) or (Key = VK_CONTROL) then
  392.     exit;
  393.  
  394.   BtnType := bt_None;
  395.  
  396.   if (Shift = []) or (Shift = [ssShift]) then
  397.     begin
  398.       { Handle shifted and unshifted keys in (almost) the same way }
  399.       BtnType := bt_Btn;
  400.       case Key of
  401.         VK_BACK     : Btn := @LeftBtn;
  402.         VK_RETURN   : Btn := @EqualsBtn;
  403.         VK_ESCAPE   : Btn := @ClrBtn;
  404.         Ord('0')    : if Shift = [] then
  405.                         Btn := @Btn0
  406.                       else                    { ')' }
  407.                         BtnType := bt_None;
  408.         Ord('1')    : if Shift = [] then
  409.                         Btn := @Btn1
  410.                       else                    { '!' }
  411.                         Btn := @NotBtn;
  412.         Ord('2')    : if Shift = [] then
  413.                         Btn := @Btn2
  414.                       else                    { '@' }
  415.                         BtnType := bt_None;
  416.         Ord('3')    : if Shift = [] then
  417.                         Btn := @Btn3
  418.                       else                    { '#' }
  419.                         Btn := @EqvBtn;
  420.         Ord('4')    : if Shift = [] then
  421.                         Btn := @Btn4
  422.                       else                    { '$' }
  423.                         BtnType := bt_None;
  424.         Ord('5')    : if Shift = [] then
  425.                         Btn := @Btn5
  426.                       else                    { '%' }
  427.                         Btn := @ModBtn;
  428.         Ord('6')    : if Shift = [] then
  429.                         Btn := @Btn6
  430.                       else                    { '^' }
  431.                         Btn := @XorBtn;
  432.         Ord('7')    : if Shift = [] then
  433.                         Btn := @Btn7
  434.                       else                    { '&' }
  435.                         Btn := @AndBtn;
  436.         Ord('8')    : if Shift = [] then
  437.                         Btn := @Btn8
  438.                       else                    { '*' }
  439.                         Btn := @MulBtn;
  440.         Ord('9')    : if Shift = [] then
  441.                         Btn := @Btn9
  442.                       else                    { '(' }
  443.                         BtnType := bt_None;
  444.         Ord('A')    : Btn := @BtnA;
  445.         Ord('B')    : Btn := @BtnB;
  446.         Ord('C')    : Btn := @BtnC;
  447.         Ord('D')    : Btn := @BtnD;
  448.         Ord('E')    : Btn := @BtnE;
  449.         Ord('F')    : Btn := @BtnF;
  450.         Ord('I')    : Btn := @MInBtn;
  451.         Ord('M')    : Btn := @MPlusBtn;
  452.         Ord('R')    : Btn := @MRBtn;
  453.         VK_NUMPAD0  : Btn := @Btn0;
  454.         VK_NUMPAD1  : Btn := @Btn1;
  455.         VK_NUMPAD2  : Btn := @Btn2;
  456.         VK_NUMPAD3  : Btn := @Btn3;
  457.         VK_NUMPAD4  : Btn := @Btn4;
  458.         VK_NUMPAD5  : Btn := @Btn5;
  459.         VK_NUMPAD6  : Btn := @Btn6;
  460.         VK_NUMPAD7  : Btn := @Btn7;
  461.         VK_NUMPAD8  : Btn := @Btn8;
  462.         VK_NUMPAD9  : Btn := @Btn9;
  463.         VK_MULTIPLY : Btn := @MulBtn;
  464.         VK_ADD      : Btn := @AddBtn;
  465.         VK_SUBTRACT : Btn := @SubBtn;
  466.         VK_DIVIDE   : Btn := @DivBtn;
  467.         VK_PLEQ     : if Shift = [] then      { '=' }
  468.                         Btn := @EqualsBtn
  469.                       else                    { '+' }
  470.                         Btn := @AddBtn;
  471.         VK_UNDER    : if Shift = [] then      { '-' }
  472.                         Btn := @SubBtn
  473.                       else                    { '_' }
  474.                         Btn := @NegBtn;
  475.         VK_QUEST    : if Shift = [] then      { '/' }
  476.                         Btn := @DivBtn
  477.                       else                    { '?' }
  478.                         BtnType := bt_None;
  479.         VK_TILDE    : if Shift = [] then      { '`' }
  480.                         BtnType := bt_None
  481.                       else                    { '~' }
  482.                         Btn := @NotBtn;
  483.         VK_BAR      : if Shift = [] then      { '\' }
  484.                         Btn := @ModBtn
  485.                       else                    { '|' }
  486.                         Btn := @OrBtn;
  487.       else
  488.         BtnType := bt_None
  489.       end
  490.     end
  491.   else if Shift = [ssCtrl] then
  492.     begin
  493.       { Handle unshifted control keys }
  494.       BtnType := bt_RadioBtn;
  495.       case Key of
  496.         Ord('1')  : Btn := @Size16RB;
  497.         Ord('2')  : Btn := @Size32RB;
  498.         Ord('3')  : Btn := @Size32RB;
  499.         Ord('6')  : Btn := @Size16RB;
  500.         Ord('8')  : Btn := @Size8RB;
  501.         Ord('B')  : Btn := @BinRB;
  502.         Ord('D')  : Btn := @DecRB;
  503.         Ord('H')  : Btn := @HexRB;
  504.         Ord('O')  : Btn := @OctRB;
  505.         Ord('S')  : begin
  506.                       Btn := @SignedCB;
  507.                       BtnType := bt_CheckBox
  508.                     end
  509.       else
  510.         BtnType := bt_None
  511.       end
  512.     end;
  513.  
  514.   { Handle "clicking" the appropriate control type }
  515.   case BtnType of
  516.     bt_None     : { Nothing };
  517.     bt_Btn      : begin
  518.                     if Btn^.Enabled then
  519.                       begin
  520.                         Btn^.SetFocus;
  521.                         TButton(Btn^).Click
  522.                       end
  523.                     else
  524.                       MessageBeep(BeepType);
  525.                     Key := 0
  526.                   end;
  527.     bt_RadioBtn : begin
  528.                     if Btn^.Enabled then
  529.                       begin
  530.                         Btn^.SetFocus;
  531.                         TRadioButton(Btn^).Checked := True
  532.                       end
  533.                     else
  534.                       MessageBeep(BeepType);
  535.                     Key := 0
  536.                   end;
  537.     bt_CheckBox : begin
  538.                     if Btn^.Enabled then
  539.                       begin
  540.                         Btn^.SetFocus;
  541.                         TCheckBox(Btn^).Checked := not TCheckBox(Btn^).Checked
  542.                       end
  543.                     else
  544.                       MessageBeep(BeepType);
  545.                     Key := 0
  546.                   end
  547.   end
  548. end;
  549.  
  550. { Handle selecting one of the base (mode) radio buttons }
  551. procedure TBaseCalcWin.BaseRBClick (Sender : TObject);
  552.  
  553. begin
  554.   if Calc.InError then
  555.     Calc.ClearOperations;
  556.  
  557.   if Sender = DecRB then
  558.     Calc.Mode := Decimal
  559.   else if Sender = HexRB then
  560.     Calc.Mode := Hexadecimal
  561.   else if Sender = BinRB then
  562.     Calc.Mode := Binary
  563.   else if Sender = OctRB then
  564.     Calc.Mode := Octal;
  565.  
  566.   CalcEnableNumKeys;
  567.   CalcUpdateButtons;
  568.   CalcUpdateDisplay
  569. end;
  570.  
  571. { Handle checking or unchecking the Signed check box }
  572. procedure TBaseCalcWin.SignedCBClick (Sender : TObject);
  573.  
  574. begin
  575.   if Calc.InError then
  576.     Calc.ClearOperations;
  577.  
  578.   Calc.Signed := TCheckBox(Sender).Checked;
  579.  
  580.   CalcUpdateButtons;
  581.   CalcUpdateDisplay
  582. end;
  583.  
  584. { Handle selecting one of the size radio buttons }
  585. procedure TBaseCalcWin.SizeCBClick (Sender : TObject);
  586.  
  587. begin
  588.   if Calc.InError then
  589.     Calc.ClearOperations;
  590.  
  591.   if Sender = Size8RB then
  592.     Calc.Size := Size8
  593.   else if Sender = Size16RB then
  594.     Calc.Size := Size16
  595.   else if Sender = Size32RB then
  596.     Calc.Size := Size32;
  597.  
  598.   CalcUpdateButtons;
  599.   CalcUpdateDisplay
  600. end;
  601.  
  602. { Handle selecting one of the number keys '0' - '9' and 'A' - 'F' }
  603. procedure TBaseCalcWin.NumBtnClick (Sender : TObject);
  604.  
  605. begin
  606.   if Calc.InError then
  607.     MessageBeep(BeepType)
  608.   else
  609.     begin
  610.       if Calc.AppendDigit(TControl(Sender).Tag - TagOfsNumKey) then
  611.         CalcUpdateDisplay
  612.       else
  613.         MessageBeep(BeepType)
  614.     end
  615. end;
  616.  
  617. { Handle selecting one of the operation keys, including Equals }
  618. procedure TBaseCalcWin.OpBtnClick (Sender : TObject);
  619.  
  620. begin
  621.   if Calc.InError then
  622.     MessageBeep(BeepType)
  623.   else
  624.     begin
  625.       if not Calc.HandleKey(TCalcKey(TControl(Sender).Tag - TagOfsOpsKey)) then
  626.         MessageBeep(BeepType);
  627.       CalcUpdateDisplay
  628.     end
  629. end;
  630.  
  631. { Handle selecting the Clear button }
  632. procedure TBaseCalcWin.ClrBtnClick (Sender : TObject);
  633.  
  634. begin
  635.   Calc.ClearOperations;
  636.   CalcUpdateDisplay
  637. end;
  638.  
  639. { Handle selecting the Backspace (<-) button }
  640. procedure TBaseCalcWin.LeftBtnClick (Sender : TObject);
  641.  
  642. begin
  643.   if Calc.Backspace then
  644.     CalcUpdateDisplay
  645.   else
  646.     MessageBeep(BeepType)
  647. end;
  648.  
  649. { Handle selecting the Memory In button }
  650. procedure TBaseCalcWin.MInBtnClick (Sender : TObject);
  651.  
  652. begin
  653.   if Calc.InError then
  654.     begin
  655.       MessageBeep(BeepType);
  656.       exit
  657.     end;
  658.  
  659.   Calc.StoreCurrentInMem;
  660.   CalcUpdateDisplay
  661. end;
  662.  
  663. { Handle selecting the Memory Retrieve button }
  664. procedure TBaseCalcWin.MRBtnClick (Sender : TObject);
  665.  
  666. begin
  667.   if Calc.InError then
  668.     begin
  669.       MessageBeep(BeepType);
  670.       exit
  671.     end;
  672.  
  673.   Calc.RetrieveMemory;
  674.   CalcUpdateDisplay
  675. end;
  676.  
  677. { Handle selecting the Memory Add button }
  678. procedure TBaseCalcWin.MPlusBtnClick (Sender : TObject);
  679.  
  680. begin
  681.   if not Calc.AddToMemoryKey then
  682.     MessageBeep(BeepType);
  683.   CalcUpdateDisplay
  684. end;
  685.  
  686. { Handle the Exit menu (or ALT+F4) }
  687. procedure TBaseCalcWin.ExitMIClick (Sender : TObject);
  688.  
  689. begin
  690.   Close
  691. end;
  692.  
  693. { Handle the user clicking on the Edit menu or selecting the popup
  694.   menu with the right mouse button }
  695. procedure TBaseCalcWin.EditMenuClick (Sender : TObject);
  696.  
  697. begin
  698.   CalcEnableClipboardOps
  699. end;
  700.  
  701. { Handle selecting the Copy menu item.  The Delphi encapsulation handles
  702.   almost all of the details }
  703. procedure TBaseCalcWin.CopyMIClick (Sender : TObject);
  704.  
  705. begin
  706.   Clipboard.AsText := Calc.CurrentString
  707. end;
  708.  
  709. { Handle selecting the Paste menu item.  Only text can be pasted, and
  710.   pasting is aborted if an illegal character is encountered }
  711. procedure TBaseCalcWin.PasteMIClick (Sender : TObject);
  712.  
  713. var
  714.   S    : string;
  715.   C    : char;
  716.   I, D : integer;
  717.  
  718. begin
  719.   if not Clipboard.HasFormat(CF_TEXT) then
  720.     begin
  721.       MessageBeep(BeepType);
  722.       exit
  723.     end;
  724.  
  725.   S := Clipboard.AsText;
  726.   for I := 1 to length(S) do
  727.     begin
  728.       C := UpCase(S[I]);
  729.       if C in ['0'..'9'] then
  730.         D := Ord(C) - Ord('0')
  731.       else if C in ['A'..'F'] then
  732.         D := Ord(C) - Ord('A') + 10
  733.       else
  734.         begin
  735.           MessageBeep(BeepType);
  736.           break   { Terminate the "for" loop }
  737.         end;
  738.  
  739.       if not Calc.AppendDigit(D) then
  740.         begin
  741.           MessageBeep(BeepType);
  742.           break
  743.         end
  744.     end;
  745.  
  746.   CalcUpdateDisplay
  747. end;
  748.  
  749. { Display the Value dialog box on selecting the menu item }
  750. procedure TBaseCalcWin.ValueMIClick (Sender : TObject);
  751.  
  752. begin
  753.   with Calc do
  754.     begin
  755.       ValueWin.SDecEdit.Text := ValToStr(CurrentValue, Decimal, True, Size);
  756.       ValueWin.UDecEdit.Text := ValToStr(CurrentValue, Decimal, False, Size);
  757.       ValueWin.HexEdit.Text := ValToStr(CurrentValue, Hexadecimal, False, Size);
  758.       ValueWin.BinEdit.Text := ValToStr(CurrentValue, Binary, False, Size);
  759.       ValueWin.OctEdit.Text := ValToStr(CurrentValue, Octal, False, Size)
  760.     end;
  761.   ValueWin.ShowModal
  762. end;
  763.  
  764. { Show the help topics available using WinHelp }
  765. procedure TBaseCalcWin.HelpTopicsMIClick (Sender : TObject);
  766.  
  767. begin
  768.   Application.HelpCommand(HELP_FINDER,0)
  769. end;
  770.  
  771. { Show the About dialog box }
  772. procedure TBaseCalcWin.AboutMIClick (Sender : TObject);
  773.  
  774. begin
  775.   AboutWin.ShowModal
  776. end;
  777.  
  778. { Display the context-sensitive help related to the button under which the
  779.   "What's This?" menu was chosen. }
  780. procedure TBaseCalcWin.WhatPMIClick (Sender : TObject);
  781.  
  782. begin
  783.   Application.HelpCommand(HELP_CONTEXTPOPUP,
  784.       TControl(PopupWhatMenu.PopupComponent).Tag)
  785. end;
  786.  
  787. end.
  788.