Marco Cantù 1998, Mastering Delphi 4

Project: LISTDEMO.DPR


Project Structure


LISTDEMO.DPR

program ListDemo;

uses
  Forms,
  ListForm in 'ListForm.pas' {Form1},
  Dates in 'Dates.pas';

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

LISTFORM.PAS

unit ListForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    ButtonAddNum: TButton;
    ButtonListNum: TButton;
    ListBox1: TListBox;
    ButtonAddDate: TButton;
    ButtonListDate: TButton;
    ButtonWrong: TButton;
    procedure ButtonAddNumClick(Sender: TObject);
    procedure ButtonListNumClick(Sender: TObject);
    procedure ButtonAddDateClick(Sender: TObject);
    procedure ButtonListDateClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ButtonWrongClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    ListNum, ListDate: TList;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses
  Dates;

procedure TForm1.ButtonAddNumClick(Sender: TObject);
begin
  ListNum.Add (Pointer (Random (10000)));
end;

procedure TForm1.ButtonListNumClick(Sender: TObject);
var
  I: Integer;
begin
  ListBox1.Clear;
  for I := 0 to ListNum.Count - 1 do
    Listbox1.Items.Add (IntToStr (Integer (ListNum [I])));
end;

procedure TForm1.ButtonAddDateClick(Sender: TObject);
begin
  ListDate.Add (TDate.Create (
    1900 + Random (200),
    1 + Random (12),
    1 + Random (31)));
end;

procedure TForm1.ButtonListDateClick(Sender: TObject);
var
  I: Integer;
begin
  ListBox1.Clear;
  for I := 0 to ListDate.Count - 1 do
    Listbox1.Items.Add ((
      TObject(ListDate [I]) as TDate).GetText);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  ListNum := TList.Create;
  ListDate := TList.Create;
end;

procedure TForm1.ButtonWrongClick(Sender: TObject);
begin
  // add a button to both lists
  ListNum.Add (Sender);
  ListDate.Add (Sender);
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to ListDate.Count - 1 do
    TObject(ListDate [I]).Free;
end;

end.

DATES.PAS

unit Dates;

interface

uses
  Classes, SysUtils;

type
  TDate = class (TComponent)
  private
    fDate: TDateTime;
    FOnChange: TNotifyEvent;
    function GetYear: Integer;
    function GetDay: Integer;
    function GetMonth: Integer;
    procedure SetDay(const Value: Integer);
    procedure SetMonth(const Value: Integer);
    procedure SetYear(const Value: Integer);
  protected
    procedure DoChange; virtual;
  public
    constructor Create (AOwner: TComponent); overload; override;
    constructor Create (y, m, d: Integer); reintroduce; overload;
    procedure SetValue (y, m, d: Integer); overload;
    procedure SetValue (NewDate: TDateTime); overload;
    function LeapYear: Boolean;
    procedure Increase (NumberOfDays: Integer = 1);
    procedure Decrease (NumberOfDays: Integer = 1);
    function GetText: string; virtual;
    property Text: string read GetText;
  published
    property Day: Integer read GetDay write SetDay;
    property Month: Integer read GetMonth write SetMonth;
    property Year: Integer read GetYear write SetYear;
    property OnChange: TNotifyEvent
      read FonChange write FOnChange;
  end;

  // custom exception
  EDateOutOfRange = class (Exception)
  end;

procedure Register;

implementation

procedure TDate.SetValue (y, m, d: Integer);
begin
  fDate := EncodeDate (y, m, d);
  // fire the event
  DoChange;
end;

function TDate.LeapYear: Boolean;
begin
  // compute leap years, considering "exceptions"
  if (GetYear mod 4 <> 0) then
    LeapYear := False
  else if (GetYear mod 100 <> 0) then
    LeapYear := True
  else if (GetYear mod 400 <> 0) then
    LeapYear := False
  else
    LeapYear := True;
end;

procedure TDate.Increase (NumberOfDays: Integer = 1);
begin
  fDate := fDate + NumberOfDays;
  // fire the event
  DoChange;
end;

function TDate.GetText: string;
begin
  GetText := DateToStr (fDate);
end;

procedure TDate.Decrease (NumberOfDays: Integer = 1);
begin
  fDate := fDate - NumberOfDays;
  // fire the event
  DoChange;
end;

constructor TDate.Create (y, m, d: Integer);
begin
  fDate := EncodeDate (y, m, d);
end;

constructor TDate.Create (AOwner: TComponent);
begin
  inherited Create (AOwner);
  // today...
  fDate := Date;
end;

function TDate.GetYear: Integer;
var
  y, m, d: Word;
begin
  DecodeDate (fDate, y, m, d);
  Result := y;
end;

procedure TDate.SetValue(NewDate: TDateTime);
begin
  fDate := NewDate;
  // fire the event
  DoChange;
end;

function TDate.GetDay: Integer;
var
  y, m, d: Word;
begin
  DecodeDate (fDate, y, m, d);
  Result := d;
end;

function TDate.GetMonth: Integer;
var
  y, m, d: Word;
begin
  DecodeDate (fDate, y, m, d);
  Result := m;
end;

procedure TDate.SetDay(const Value: Integer);
begin
  if (Value < 0) or (Value > 31) then
    raise EDateOutOfRange.Create ('Invalid month');
  SetValue (Year, Month, Value);
end;

procedure TDate.SetMonth(const Value: Integer);
begin
  if (Value < 0) or (Value > 12) then
    raise EDateOutOfRange.Create ('Invalid month');
  SetValue (Year, Value, Day);
end;

procedure TDate.SetYear(const Value: Integer);
begin
  SetValue (Value, Month, Day);
end;

procedure TDate.DoChange;
begin
  if Assigned (FOnChange) then
    FOnChange (self);
end;

procedure Register;
begin
  RegisterComponents ('Md4', [TDate]);
end;

end.

LISTFORM.DFM

object Form1: TForm1
  Left = 205
  Top = 106
  Width = 408
  Height = 304
  Caption = 'List Demo'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = True
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object ButtonAddNum: TButton
    Left = 24
    Top = 24
    Width = 89
    Height = 25
    Caption = '&Add Number'
    TabOrder = 0
    OnClick = ButtonAddNumClick
  end
  object ButtonListNum: TButton
    Left = 24
    Top = 64
    Width = 89
    Height = 25
    Caption = '&List Numbers'
    TabOrder = 1
    OnClick = ButtonListNumClick
  end
  object ListBox1: TListBox
    Left = 136
    Top = 24
    Width = 225
    Height = 225
    ItemHeight = 13
    TabOrder = 2
  end
  object ButtonAddDate: TButton
    Left = 24
    Top = 128
    Width = 89
    Height = 25
    Caption = 'Add &Date'
    TabOrder = 3
    OnClick = ButtonAddDateClick
  end
  object ButtonListDate: TButton
    Left = 24
    Top = 168
    Width = 89
    Height = 25
    Caption = 'Lis&t Dates'
    TabOrder = 4
    OnClick = ButtonListDateClick
  end
  object ButtonWrong: TButton
    Left = 24
    Top = 224
    Width = 89
    Height = 25
    Caption = 'Add &Wrong'
    TabOrder = 5
    OnClick = ButtonWrongClick
  end
end


Copyright Marco Cantù 1998