A small RPN calculator based on vegaseat's stay-on-top calc. (Delphi 7)

pankleks 0 Tallied Votes 201 Views Share

It is a small two-in-one calculator that can work as a regular or RPN calculator, selected by a RPN checkbox. It has a four level stack similar to the HP 48 calculator made from four Tmemos. This code shows you how to make visual effects(RPN stack) from existing delphi components. I have also included 'calc.dfm' form code at the end to make it easy putting it together.

{------------------------  calc.pas  -------------------------}

unit calc;

{$X-}

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, Menus, StdCtrls, ExtCtrls, Buttons;

type
  Tcalcform = class(TForm)
    One: TButton;
    Two: TButton;
    Three: TButton;
    Four: TButton;
    Five: TButton;
    Six: TButton;
    Seven: TButton;
    Eight: TButton;
    Nine: TButton;
    Zero: TButton;
    Equal: TButton;
    Clear: TButton;
    AllClear: TButton;
    Multiply: TButton;
    Divide: TButton;
    Plus: TButton;
    Minus: TButton;
    Drop: TButton;
    Stack: TMemo;
    ExitButton: TBitBtn;
    Decimal: TButton;
    Enter: TButton;
    Entry: TMemo;
    RPN: TCheckBox;
    Stack2: TMemo;
    Stack3: TMemo;
    Stack4: TMemo;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    StaticText1: TStaticText;
    StaticText2: TStaticText;
    StaticText3: TStaticText;
    StaticText4: TStaticText;
    plusminus: TButton;
        procedure OneClick(Sender: TObject);
        procedure TwoClick(Sender: TObject);
        procedure ThreeClick(Sender: TObject);
        procedure FourClick(Sender: TObject);
        procedure FiveClick(Sender: TObject);
        procedure SixClick(Sender: TObject);
        procedure SevenClick(Sender: TObject);
        procedure EightClick(Sender: TObject);
        procedure NineClick(Sender: TObject);
        procedure PlusClick(Sender: TObject);
        procedure MinusClick(Sender: TObject);
        procedure MultiplyClick(Sender: TObject);
        procedure DivideClick(Sender: TObject);
        procedure ClearClick(Sender: TObject);
        procedure AllClearClick(Sender: TObject);
        procedure EntryChange(Sender: TObject);
        procedure EqualClick(Sender: TObject);
        procedure DecimalClick(Sender: TObject);
        procedure Display;
        procedure ExitButtonClick(Sender: TObject);
        procedure ZeroClick(Sender: TObject);
    procedure EntryKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormShow(Sender: TObject);
    procedure EnterClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure DropClick(Sender: TObject);
    procedure RPNClick(Sender: TObject);
    procedure plusminusClick(Sender: TObject);
  private
    { Private declarations }
    procedure CreateParams(var Params: TCreateParams); override;
    procedure WMNCHitTest(var Msg: TMessage);  message WM_NCHITTEST;
  public
    { Public declarations }
 end;


var
  calcform: Tcalcform;
  DecimalSeparator: string;
  DigitGrouping: string;
  Total   : Double;
  Complete: Boolean;
  Operator: Char;
  Sign    : Boolean;
  
implementation

{$R *.dfm}

procedure Tcalcform.FormCreate(Sender: TObject);
begin
{$ExtendedSyntax On}
end;

// the missing delay() procedure, delay in milliseconds
procedure Delay(msecs: integer);
var
FirstTickCount: longint;
begin
        FirstTickCount := GetTickCount;
        repeat
                Application.ProcessMessages; { allowing access to other controls }
        until ((GetTickCount-FirstTickCount) >= Longint(msecs));
end;

function DeletePoint(Str: string): string;
var
  i,position: Integer;
begin
  i := 0;
  position := AnsiPos(DigitGrouping, Str);
  if  position = 0 then
  Result:=Str
  else
  begin
  while  i<=Length(Str) do
    if Str[i] = DigitGrouping then Delete(Str, i, 1)
    else
    Inc(i);
  Result:=Str
  end
end;

// override form's style to create a window without titlebar
procedure Tcalcform.CreateParams(var Params: TCreateParams);
begin
        inherited CreateParams (Params);
        Params.Style := ws_Popup or ws_ClipChildren or ws_ClipSiblings or ws_Border;
end;

// left mouse button will drag form
procedure Tcalcform.WMNCHitTest(var Msg: TMessage);
begin
        if GetAsyncKeyState(VK_LBUTTON) < 0 then
        Msg.Result := HTCAPTION
        else
        Msg.Result := HTCLIENT;
end;

procedure Calculate(Number: Real; NextOp: Char);
begin
        if not Complete or (Total = 0.0) then
        case Operator of
        '+': Total := Total + Number;
        '-': Total := Total - Number;
        'x': Total := Total * Number;
        '/':
        begin
                if Number <> 0 then
                Total := Total / Number
                else
                begin
                        calcform.Entry.Text := 'Division by Zero!';
                        Delay(3000);
                end;
        end;
end;
Operator := NextOp;
Complete := True;
end;

procedure CalculateRPN(Number: Real; NextOp: Char);
var
No,No2: string;
begin
      No := DeletePoint(calcform.Stack.Text);
      No2 := DeletePoint(calcform.Stack2.Text);
        if Number = 0.0 then
        begin
        Number := StrToFloat(No2);
        case NextOP of
        '+': Total := Number + StrToFloat(No);
        '-': Total := Number - StrToFloat(No);
        'x': Total := Number * StrToFloat(No);
        '/':
        begin
                if Number <> 0 then
                Total := Number / StrToFloat(No)
                else
                begin
                        calcform.Entry.Text := 'Division by Zero!';
                        Delay(3000);
                end;
        end;
        end
        end
        else
        begin
        case NextOP of
        '+': Total := StrToFloat(No) + Number;
        '-': Total := StrToFloat(No) - Number;
        'x': Total := StrToFloat(No) * Number;
        '/':
        begin
                if Number <> 0 then
                Total := StrToFloat(No) / Number
                else
                begin
                        calcform.Entry.Text := 'Division by Zero!';
                        Delay(3000);
                end;
        end;
        end;

end;
Complete := True;
Sign := False;
end;

procedure Tcalcform.ZeroClick(Sender: TObject);
begin
        if Complete then Entry.Text := '';

        Entry.Text := Entry.Text + '0';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.OneClick(Sender: TObject);
begin
        if Complete then Entry.Text := '';
        Entry.Text := Entry.Text + '1';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.TwoClick(Sender: TObject);
begin
        if Complete then Entry.Text := '';
        Entry.Text := Entry.Text + '2';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.ThreeClick(Sender: TObject);
begin
        if Complete then Entry.Text := '';
        Entry.Text := Entry.Text + '3';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.FourClick(Sender: TObject);
begin
        if Complete then Entry.Text := '';
        Entry.Text := Entry.Text + '4';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.FiveClick(Sender: TObject);
begin
        if Complete then Entry.Text := '';
        Entry.Text := Entry.Text + '5';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.SixClick(Sender: TObject);
begin
        if Complete then Entry.Text := '';
        Entry.Text := Entry.Text + '6';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.SevenClick(Sender: TObject);
begin
        if Complete then Entry.Text := '';
        Entry.Text := Entry.Text + '7';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.EightClick(Sender: TObject);
begin
        if Complete then Entry.Text := '';
        Entry.Text := Entry.Text + '8';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.NineClick(Sender: TObject);
begin
        if Complete then Entry.Text := '';
        Entry.Text := Entry.Text + '9';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.PlusClick(Sender: TObject);
var
No: string;
begin
        if RPN.Checked then
        CalculateRPN(StrToFloat(Entry.Text), '+')
        else
        begin
        Sign := True;
        No := DeletePoint(Entry.Text);
        Calculate(StrToFloat(No), '+');
        end;
        Display;
end;

procedure Tcalcform.MinusClick(Sender: TObject);
var
No: string;
begin
        if RPN.Checked = TRUE then
        CalculateRPN(StrToFloat(Entry.Text), '-')
        else
        begin
        Sign := True;
        No := DeletePoint(Entry.Text);
        Calculate(StrToFloat(No), '-');
        end;
        Display;
end;

procedure Tcalcform.MultiplyClick(Sender: TObject);
var
No: string;
begin
        if RPN.Checked = TRUE then
        CalculateRPN(StrToFloat(Entry.Text), 'x')
        else
        begin
        Sign := True;
        No := DeletePoint(Entry.Text);
        Calculate(StrToFloat(No), 'x');
        end;
        Display;
end;

procedure Tcalcform.DivideClick(Sender: TObject);
var
No: string;
begin
        if RPN.Checked = TRUE then
        CalculateRPN(StrToFloat(Entry.Text), '/')
        else
        begin
        Sign := True;
        No := DeletePoint(Entry.Text);
        Calculate(StrToFloat(No), '/');
        end;
        Display;
end;

procedure Tcalcform.ClearClick(Sender: TObject);
var
Sf: string;
begin
        if Length(Entry.Text) = 1 then
        begin
        Complete := True;
        Entry.Text := '0'
        end
        else
        begin
        Sf := Entry.Text;
        if ((not Sign) and (not Complete)) then Delete(Sf, Length(Sf), Length(Sf)-1);
        Entry.Text := Sf;
        end;
        Entry.SetFocus;
end;

procedure Tcalcform.AllClearClick(Sender: TObject);
begin
        Entry.Text := '0';
        Stack.Lines.Clear;
        Stack2.Lines.Clear;
        Stack3.Lines.Clear;
        Stack4.Lines.Clear;
        Complete := True;
        Total := 0.0;
        Operator := '+';
        Sign := False;
        Entry.SetFocus;
end;

procedure Tcalcform.EntryChange(Sender: TObject);
begin
        if Entry.Text = '' then Complete := False;
end;

procedure Tcalcform.EqualClick(Sender: TObject);
var
No: string;
begin
        if RPN.Checked = FALSE then
        begin
        No := DeletePoint(Entry.Text);
        Calculate(StrToFloat(No), '+');
        Display;
        Complete := True;
        Total := 0.0;
        Sign := False;
        end;
        Entry.SetFocus;
end;

procedure Tcalcform.DecimalClick(Sender: TObject);
begin
        if Complete then
        begin
        Entry.Text := '0';
        Complete := False;
        end;
        if Pos(DecimalSeparator, Entry.Text) = 0 then
        Entry.Text := Entry.Text + DecimalSeparator;
        Entry.SetFocus;
end;

// format the result display
procedure Tcalcform.Display;
begin
        if RPN.Checked = TRUE then
        begin
        if (StrToFloat(Entry.Text)) = 0.0 then
        begin
        Stack2.Text := Stack3.Text;
        Stack3.Text := Stack4.Text;
        Stack4.Lines.Clear;
        Stack.Text := Format('%.2n',[Total]);
        Entry.Text := '0';
        end
        else
        begin
        Stack.Text := Format('%.2n',[Total]);
        Entry.Text := '0';
        end
        end
        else
        Entry.Text := Format('%.2n',[Total]);
        Entry.SetFocus;
end;

procedure Tcalcform.ExitButtonClick(Sender: TObject);
begin
        Close;
end;

procedure Tcalcform.EntryKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
if Key = 39 then ClearClick(Sender);
if Key = 40 then DropClick(Sender);
if Key = VK_NUMPAD0 then ZeroClick(Sender);
if Key = VK_NUMPAD1 then OneClick(Sender);
if Key = VK_NUMPAD2 then TwoClick(Sender);
if Key = VK_NUMPAD3 then ThreeClick(Sender);
if Key = VK_NUMPAD4 then FourClick(Sender);
if Key = VK_NUMPAD5 then FiveClick(Sender);
if Key = VK_NUMPAD6 then SixClick(Sender);
if Key = VK_NUMPAD7 then SevenClick(Sender);
if Key = VK_NUMPAD8 then EightClick(Sender);
if Key = VK_NUMPAD9 then NineClick(Sender);
if Key = VK_DECIMAL then DecimalClick(Sender);
if Key = VK_ADD then PlusClick(Sender);
if Key = VK_SUBTRACT then MinusClick(Sender);
if Key = VK_DIVIDE then DivideClick(Sender);
if Key = VK_MULTIPLY then MultiplyClick(Sender);
if Key = VK_BACK then ClearClick(Sender);
if Key = VK_RETURN then
if RPN.Checked = TRUE then
EnterClick(Sender)
else
EqualClick(Sender);
Entry.SetFocus;
end;

procedure Tcalcform.FormShow(Sender: TObject);
begin
Entry.SetFocus;
end;

procedure Tcalcform.EnterClick(Sender: TObject);
var
No: string;
begin
No := DeletePoint(Entry.Text);
Stack4.Text := Stack3.Text;
Stack3.Text := Stack2.Text;
Stack2.Text := Stack.Text;
Stack.Text := Format('%.2n',[StrToFloat(No)]);
Entry.Text := '0';
Complete := True;
Total := 0.0;
Operator := '+';
Entry.SetFocus;
end;

procedure Tcalcform.DropClick(Sender: TObject);
begin
Stack.Text := Stack2.Text;
Stack2.Text := Stack3.Text;
Stack3.Text := Stack4.Text;
Stack4.Lines.Clear;
Entry.SetFocus;

end;

procedure Tcalcform.RPNClick(Sender: TObject);
begin
Total := 0.0;
Entry.SetFocus;
end;

procedure Tcalcform.plusminusClick(Sender: TObject);
var
str,str2,str3: string;
it: integer;
begin
str2 := DeletePoint(calcform.Stack.Text);
str3 := DeletePoint(Entry.Text);
it := ansipos('-', Entry.Text);
if it > 0 then
begin
        str := Entry.Text;
        if not Sign then Delete(str, it, 1);
        Entry.Text := str;
end
else
        if ((StrToFloat(str3) > 0.0) and (not Sign)) then
        Entry.Text := '-' + Entry.Text
        else
        if ((RPN.Checked) and (StrToFloat(str2) > 0.0)) then
        Stack.Text := '-' + Stack.Text
        else
        if ((RPN.Checked) and (ansipos('-', Stack.Text) > 0)) then
        begin
        str := Stack.Text;
        Delete(str, 1, 1);
        Stack.Text := str;
        end;

Entry.SetFocus;
end;

Initialization

DecimalSeparator := ',';
DigitGrouping := '.';
Complete := True;
Total := 0.0;
Operator := '+';
Sign := False;

end.


{------------------------  calc.dfm  -------------------------}
object calcform: Tcalcform
  Left = 388
  Top = 203
  Width = 315
  Height = 328
  Caption = 'Calculator'
  Color = 12615808
  TransparentColorValue = clMaroon
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object Stack4: TMemo
    Left = 16
    Top = 16
    Width = 281
    Height = 24
    Alignment = taRightJustify
    Color = 102
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clRed
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    MaxLength = 20
    ParentFont = False
    ReadOnly = True
    TabOrder = 26
  end
  object Stack3: TMemo
    Left = 16
    Top = 35
    Width = 281
    Height = 24
    Alignment = taRightJustify
    Color = 102
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clRed
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    MaxLength = 20
    ParentFont = False
    ReadOnly = True
    TabOrder = 25
  end
  object Stack2: TMemo
    Left = 16
    Top = 54
    Width = 281
    Height = 24
    Alignment = taRightJustify
    Color = 102
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clRed
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    MaxLength = 20
    ParentFont = False
    ReadOnly = True
    TabOrder = 24
  end
  object Stack: TMemo
    Left = 16
    Top = 73
    Width = 281
    Height = 24
    Alignment = taRightJustify
    Color = 102
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clRed
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    Lines.Strings = (
      '')
    MaxLength = 20
    ParentFont = False
    ReadOnly = True
    TabOrder = 0
    WordWrap = False
  end
  object One: TButton
    Left = 16
    Top = 148
    Width = 33
    Height = 33
    Caption = '1'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 1
    OnClick = OneClick
  end
  object Two: TButton
    Left = 56
    Top = 148
    Width = 33
    Height = 33
    Caption = '2'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 2
    OnClick = TwoClick
  end
  object Three: TButton
    Left = 96
    Top = 148
    Width = 33
    Height = 33
    Caption = '3'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 3
    OnClick = ThreeClick
  end
  object Four: TButton
    Left = 16
    Top = 188
    Width = 33
    Height = 33
    Caption = '4'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 4
    OnClick = FourClick
  end
  object Five: TButton
    Left = 56
    Top = 188
    Width = 33
    Height = 33
    Caption = '5'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 5
    OnClick = FiveClick
  end
  object Six: TButton
    Left = 96
    Top = 188
    Width = 33
    Height = 33
    Caption = '6'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 6
    OnClick = SixClick
  end
  object Seven: TButton
    Left = 16
    Top = 228
    Width = 33
    Height = 33
    Caption = '7'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 7
    OnClick = SevenClick
  end
  object Eight: TButton
    Left = 56
    Top = 228
    Width = 33
    Height = 33
    Caption = '8'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 8
    OnClick = EightClick
  end
  object Nine: TButton
    Left = 96
    Top = 228
    Width = 33
    Height = 33
    Caption = '9'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 9
    OnClick = NineClick
  end
  object Zero: TButton
    Left = 16
    Top = 268
    Width = 33
    Height = 33
    Caption = '0'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 10
    OnClick = ZeroClick
  end
  object Equal: TButton
    Left = 56
    Top = 268
    Width = 73
    Height = 33
    Caption = '='
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -17
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 11
    OnClick = EqualClick
  end
  object Clear: TButton
    Left = 144
    Top = 148
    Width = 33
    Height = 33
    Caption = '<--'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -13
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 12
    OnClick = ClearClick
  end
  object AllClear: TButton
    Left = 184
    Top = 148
    Width = 33
    Height = 33
    Caption = 'C'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 13
    OnClick = AllClearClick
  end
  object Multiply: TButton
    Left = 144
    Top = 228
    Width = 33
    Height = 33
    Caption = 'X'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 14
    OnClick = MultiplyClick
  end
  object Divide: TButton
    Left = 184
    Top = 228
    Width = 33
    Height = 33
    Caption = '/'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -12
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 15
    OnClick = DivideClick
  end
  object Plus: TButton
    Left = 144
    Top = 188
    Width = 33
    Height = 33
    Caption = '+'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -19
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
    TabOrder = 16
    OnClick = PlusClick
  end
  object Minus: TButton
    Left = 184
    Top = 188
    Width = 33
    Height = 33
    Caption = '--'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 17
    OnClick = MinusClick
  end
  object Drop: TButton
    Left = 224
    Top = 148
    Width = 73
    Height = 33
    Caption = 'DROP'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 18
    OnClick = DropClick
  end
  object ExitButton: TBitBtn
    Left = 224
    Top = 271
    Width = 73
    Height = 30
    Caption = 'Exit'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 19
    OnClick = ExitButtonClick
  end
  object Decimal: TButton
    Left = 184
    Top = 268
    Width = 33
    Height = 33
    Caption = ','
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -19
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 20
    OnClick = DecimalClick
  end
  object Enter: TButton
    Left = 224
    Top = 188
    Width = 73
    Height = 33
    Caption = 'Enter'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -13
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 21
    OnClick = EnterClick
  end
  object Entry: TMemo
    Left = 17
    Top = 108
    Width = 280
    Height = 25
    Alignment = taRightJustify
    Color = 8323329
    Font.Charset = DEFAULT_CHARSET
    Font.Color = 12368963
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    Lines.Strings = (
      '0')
    MaxLength = 20
    ParentFont = False
    ReadOnly = True
    TabOrder = 22
    OnChange = EntryChange
    OnKeyDown = EntryKeyDown
  end
  object RPN: TCheckBox
    Left = 240
    Top = 236
    Width = 49
    Height = 17
    Caption = 'RPN'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 23
    OnClick = RPNClick
  end
  object Edit1: TEdit
    Left = 18
    Top = 73
    Width = 277
    Height = 2
    BorderStyle = bsNone
    Color = 102
    TabOrder = 27
  end
  object Edit2: TEdit
    Left = 18
    Top = 54
    Width = 277
    Height = 2
    BorderStyle = bsNone
    Color = 102
    TabOrder = 28
  end
  object Edit3: TEdit
    Left = 18
    Top = 35
    Width = 277
    Height = 2
    BorderStyle = bsNone
    Color = 102
    TabOrder = 29
  end
  object StaticText1: TStaticText
    Left = 22
    Top = 18
    Width = 19
    Height = 21
    AutoSize = False
    Caption = '4:'
    Color = 102
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clRed
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentColor = False
    ParentFont = False
    TabOrder = 30
  end
  object StaticText2: TStaticText
    Left = 22
    Top = 37
    Width = 19
    Height = 21
    AutoSize = False
    Caption = '3:'
    Color = 102
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clRed
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentColor = False
    ParentFont = False
    TabOrder = 31
  end
  object StaticText3: TStaticText
    Left = 22
    Top = 56
    Width = 19
    Height = 21
    AutoSize = False
    Caption = '2:'
    Color = 102
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clRed
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentColor = False
    ParentFont = False
    TabOrder = 32
  end
  object StaticText4: TStaticText
    Left = 22
    Top = 75
    Width = 19
    Height = 20
    AutoSize = False
    Caption = '1:'
    Color = 102
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clRed
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentColor = False
    ParentFont = False
    TabOrder = 33
  end
  object plusminus: TButton
    Left = 144
    Top = 268
    Width = 33
    Height = 33
    Caption = '+/-'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -16
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
    TabOrder = 34
    OnClick = plusminusClick
  end
end

Dani AI

Generated

Nice, compact little two-mode calculator — good use of a lightweight UI and the WM_NCHITTEST drag trick. A few focused notes and fixes that make the code safer and easier to extend without changing the user-visible behavior you already get from .

  • Parsing/formatting: avoid rolling your own separator removal loop; it currently initializes the loop index to 0 (Delphi strings are 1-based), which is a common off-by-one source of crashes. Replace the manual loop with StringReplace and use TryStrToFloat to validate input before converting. Example pattern:

    s := StringReplace(Entry.Text, DigitGrouping, '', [rfReplaceAll]);
    if not TryStrToFloat(s, value) then Exit; 

    For output prefer FormatFloat (e.g. FormatFloat('0.00', value)) so the display is predictable across locales.

  • Naming and locale: don’t declare unit-level variables named DecimalSeparator or DigitGrouping — those identifiers are already used by SysUtils/format settings and cause confusion or shadowing. Either remove the local variables and use the system DecimalSeparator/FormatSettings, or rename your unit variables (e.g. StackDecimalSep).

  • Architecture and robustness: keep the numeric stack as an internal array/TList<Double> and update the four TMemo controls from that model. That separates UI from logic and makes it trivial to change stack depth later. Use TryStrToFloat everywhere you parse; wrap risky operations (division) with checks and avoid long blocking delays using Application.ProcessMessages — use a TTimer or a transient message instead.

  • Key handling and polish: use the VK_* constants (VK_RIGHT, VK_DOWN, etc.) rather than magic numbers, and centralize key-to-action mapping so numpad, desktop keys and UI buttons stay consistent.

These changes preserve the UI and RPN behavior while eliminating fragile parsing, improving localization, and making extension (more functions, deeper stack) straightforward.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.