maXbox Starter 2      

Start with OO Programming

 

1.1      First Step

Today we spend some time in OO Programming (Object Oriented). Hope you did already work with the first Starter and the box at:

 

http://www.softwareschule.ch/download/maxbox_starter.pdf

 

This lesson will introduce you to objects, classes and events. So what’s an object? An object consists of methods, properties and in many cases events. I’ll show you all three of them.

Properties represent the data contained in the object. Methods are the actions the object can perform. Events are conditions or signals the object can react to. All objects descend from an ancestor object (class), in our case from TObject.

 

1.2      Get the Code

As you already know the tool is split up into the toolbar across the top, the editor or code part in the centre and the output window at the bottom.

G In maXbox you can’t create new classes, because we use the classes from the inbuilt VCL (Visual Component Library).

 

Before this starter code will work you will need to download maXbox from the website. It can be down-loaded from http://sourceforge.net/projects/maxbox or from http://www.softwareschule.ch/maxbox.htm (you’ll find the download maxbox2.zip top left on the site). Once the download has finished, unzip the file, making sure that you preserve the folder structure as it is. If you double-click maxbox2.exe the box opens a default program. Test it with F9 or press Compile and you should hear a sound. So far so good now we’ll open our example.

 

59_timerobject_starter2.txt

 

The Load button will present you in /examples with a list of Programs stored within your directory as well as a list of /exercises with defective Pascal code to be fixed for training purposes. Alternatively you can download the file from: http://www.softwareschule.ch/download/59_timerobject_starter2.txt

Use the Save Page as… function of your browser[1] or load it from examples (or wherever you stored it). Now let’s take a look at the code of this project. Our first line is

1 program TimerEvent_Object;

We have to name the game, means the program’s name is TimerEvent_Object.

F This example requires a TTimer object and a TObject too. The program makes a series of calls to an event handler named timer1Event(), which is triggered as many times you wish (invoked) from the onTimer event.

 

Most of the functions and objects we use like showMessage() or TTimer are implicit in a library (or unit). A library is a collection of code, which you can include in your program. By storing your commonly used code in a library, you can reuse code for many times in different projects and also hide difficult sections of code from the developer. Once a unit or an object is tested it’s stable to use.

1: The maXbox

 

Next we learn how a constant works. Constants are fixed numeric or character values represented by a name. Constants can’t be changed[2] while a program runs. A section starts with the word const:

 

06 Const  MILLISECONDS = 1000; //one second

The lines 8 to 9 of the program contain the declaration of 2 variables myTimer and glob_count. So line 8 is our object variable, namely an object of type TTimer (as its name suggests an object with clock or watch functions). So each variable has a type.

F A type is essentially a name for a kind of data. When you declare a variable you must specify its type, which determines the set, range and storage of values the variable can hold and the operations (functions, procedures or methods) that can be performed on it. A method is just a procedure or function associated with a class!

08 var myTimer: TTimer; //is an object of class TTimer!
09     glob_count: byte;

A variable is a place to store data. In this case you are setting up a variable of type TTimer and byte. Imagine a variable as a small box (in maXbox;)) where you can keep things. A variable is called a variable because its value can change during the programs execution. But watch out not every name can hold a variable because you can’t use any keywords like object, class, set, while, case, if then etc as variable names.

Now comes the time to explain the difference between an object and a class, for many of my students a bit dark chapter ;). An Object is a software bundle of related state and behaviour (methods). So myTimer is a special variable, it’s an object variable of a special type called a class:

 

G A Class is a blueprint or prototype from which individual objects are created (later on we create an object). Methods appear in a class declaration as function or procedure headings, with no body. Defining declarations for each method occur elsewhere in the program.

 

&       So far we have learned something about constants and variables and the difference between an object and a class. We say an object is an instance of a class. Now it’s time to run our program at first with F9 (if you haven’t done yet). The program generates 6 message boxes, the first to start and the next five messages to show the time in an interval of a second.

2: The Output Window

The Compile button is also used to check that your code is correct, by verifying the syntax before the program starts. When you run this code you will see that we catch 6 message boxes in a set count up from 1 to 5.

CSo let’s jump to line 12. This line is our procedure called timer1Event().[3]

12 procedure timer1Event(Sender: TObject);

FA procedure (call) consists of the name of a procedure (with or without qualifiers), followed by a parameter list like (Sender: TObject). Functions return a value where procedures must not! Most functions and procedures require parameters of specific types.

3

12 procedure timer1Event(Sender: TObject);
13 begin
14  incb(glob_count)
15  //ShowMessage('this '+intToStr(glob_count)+' time') //never get
16  if glob_count >= 5 then begin
17    myTimer.enabled:= false;
18    myTimer.Free;
19  end;
20  ShowMessage('this is from timer event '+intToStr(glob_count)+' time: '
21                 +timeToStr(time))
22 end;

In line 12 we have a parameter named sender of type TObject. In a Delphi event handler, the sender parameter indicates which component has produced the event and therefore is called the sender. I know you need some time or experience to understand this; anyway when the timer starts, the event handler timer1Event gets the event from the myTimer.onTimer event.

G It is also possible to get information back from the handler.

Once you determine when the event occurs (later on in the main program), you must define how you want the event handled. And this goes like this:

 

$In our first if Statement we check how often we want to receive the event:

 

16  if glob_count >= 5 then begin

If the condition (glob_count >=5) is true, then we stop and close the timer but as long it’s not true we show in each call the time in a message box.

G The else keyword of the if statement is optional;

We could run this code as many times as we like simply by changing the global count condition for example from 5 to 10. After each event of the loop, the counter in line 14 is incremented. Consequently, glob_count is called a loop counter.

 

14 incb (glob_count);

After we got called 5 times we close the event

 

18 myTimer.Free;

Free (Destroy) deactivates the timer object by setting Enabled to False before freeing the resources required by the timer object.

7F If we don’t’ close the timer event by a condition the showmessage would go on by infinitive, as long your machine is running, so you can use it like a clock or heart beat.

 

7 Try to change the const declaration for example from 1000 to 2000 in line 6! How many messages you get and how long it’ll last?

G A package or unit is a namespace for organizing classes and interfaces in a logical manner.

1.3      The Main Routine (TimeTime)

An OP program must have a main routine between begin and end. The main routine is run once and once only at the start of the program (after you compiled) and is where you will do the general instruct-ions and the main control of the program.

Now main part: Use the Timer component to trigger an event, either one time or repeatedly, after a measured interval. Write the code that you want to occur at the specified time inside the timer component's OnTimer event. I would say line 30 is the core of your program:

 

30  myTimer.onTimer:= @timer1Event;

Of course the main program starts in line 25. In line 26 we initialise the global counter with 0. What‘s the meaning of initialising? It has the purpose to set glob_count to a known value, to 0 in this case.

In line 29 we create our object. Call create to instance a timer at runtime. Given the declaration of line 8 (var myTimer: TTimer;) you can NOW create an instance of TTimer as follows:

 

29  myTimer:= TTimer.Create(self);

The identifier self references the object in which the method is called.

G A class type must be declared and given a name before it can be instantiated.

For example, here is the declaration of the TTimer class from the ExtCtrls unit.

TTimer is used to simplify the calling of the Windows API timer functions SetTimer and KillTimer, and to simplify the processing of WM_TIMER messages. Use one timer component for each timer in the application. TTimer descends from TComponent (in the Classes unit), inheriting most of its members. Each member is declared as private, protected, or public (this class has no published members); for explanations of these terms, see 1.4 Appendix declaration of class members.

3

24 //main program
25 begin
26  glob_count:= 0;
27  ShowMessage('Press OK to start with timer at: '
28                +dateToStr(date)+': '+timeToStr(time))
29  myTimer:= TTimer.Create(self);
30  myTimer.onTimer:= @timer1Event;
31  myTimer.interval:= MILLISECONDS;
32 end.

In line 27 we are telling the compiler to call a procedure named ShowMessage; It simply returns the current system date and time. Date and time are also functions ? We pass no parameters to it (empty parenthesis or no parenthesis).

In line 31 we specify the amount of elapsed time in milliseconds before the timer event is triggered, we use the interval property. To discontinue a timed event, set the timer component's enabled property to false, which we set in line 17.

30  myTimer.onTimer:= @timer1Event;
31  myTimer.interval:= MILLISECONDS;

The interval determines how frequently the OnTimer event occurs. Each time the specified interval passes, the OnTimer event occurs and calls our event handler in line 12.

G Use Interval to specify any cardinal value as the interval between OnTimer events. The default value is 1000 (one second). Interesting point: A 0 value is valid, however the timer will not call an OnTimer event for a value of 0 ;).

So an event handler is called a handler because it responds to events that occur while the program is running. Event handlers are assigned to specific events like we do in line 30.

7How can you change the situation that every minute an event occurs? Yes, you define a constant with sum of 60000:

 

Const
  const MILLISECONDS = 1000 * 60;

And then you get every minute a message box five times.

& In conclusion the TTimer is used to simplify calling the system timer functions. Use one timer component for each timer in the application. The execution of the timer occurs through its OnTimer event. TTimer has an Interval property that determines how often the timer event occurs.

We can state that for educational reasons its better to begin in a procedural way of programming followed by OOP. In procedural programming (which predates OOP), you create constants, variables, functions, and statements. Those have to be learned before OOP. I would say that even OOP is tougher to learn and much harder to master than procedural coding, you learn it better after procedural thinking. The truth is that almost anything that can be done procedurally can be done using objects and vice versa.

$ With a right mouse click on the pop up menu in the editor you can set so called breakpoints and study the source from which point you want or use different steps to execute and stop from. As a last exercise you may reuse the program as a game:

7         Try to shoot down the messagebox before the next event occurs. Set the interval back to one second or try it faster with half second.

7         Think about the so called Call Tree: [1]
29 myTimer:= TTimer.Create(self);

30 myTimer.onTimer:= @timer1Event

12 timer1Event;

C That’s all folks of primetime, may the source be with you for the second step and I hope to see you from time to time in maXbox.

 

 

Feedback @

max@kleiner.com

 

Many thanks to the Reviewer Team

Literature:

Kleiner et al., Patterns konkret, 2003, Software & Support

Links of maXbox:

http://www.softwareschule.ch/maxbox.htm

http://www.softwareschule.ch/


http://sourceforge.net/projects/maxbox

 

The Document itself:

 

http://www.softwareschule.ch/download/maxbox_starter2.pdf

 


 

1.4      Appendix

1.4.1   TTimer Declaration

 

  TTimer = class(TComponent)

  private

    FInterval: Cardinal;

    FWindowHandle: HWND;

    FOnTimer: TNotifyEvent;

    FEnabled: Boolean;

    procedure UpdateTimer;

    procedure SetEnabled(Value: Boolean);

    procedure SetInterval(Value: Cardinal);

    procedure SetOnTimer(Value: TNotifyEvent);

    procedure WndProc(var Msg: TMessage);

  protected

    procedure Timer; dynamic;

  public

    constructor Create(AOwner: TComponent); override;

    destructor Destroy; override;

  published

    property Enabled: Boolean read FEnabled write SetEnabled default True;

    property Interval: Cardinal read FInterval write SetInterval default 1000;

    property OnTimer: TNotifyEvent read FOnTimer write SetOnTimer;

  end;

 

1.4.2   Code in OP

program TimerEvent_Object;

// timerevent with time dialog synchronisation or event triggering, loc's=59

// when messagebox is to early (line 25) the break condition never arrives

 

const MILLISECONDS = 1000 * 60; //one minute

 

var myTimer: TTimer; //is an object of class TTimer!

    glob_count: byte;  

 

procedure timer1Event(Sender: TObject);

begin

  incb(glob_count)

  //ShowMessage('this '+intToStr(glob_count)+' time') //never get

  if glob_count >= 5 then begin

    myTimer.enabled:= false;

    myTimer.Free;

  end;

  ShowMessage('this is from timer event '+intToStr(glob_count)+' time: '

                 +timeToStr(time))

end; 

 

//main program

begin

  glob_count:= 0;

  ShowMessage('Press OK to start with timer at: '

                 +dateToStr(date)+': '+timeToStr(time))

  myTimer:= TTimer.Create(self);

  myTimer.onTimer:= @timer1Event;

  myTimer.interval:= MILLISECONDS;

end.

 

---------------------------------------------------------------------

 

P     Aim

F       Introduction to a new topic

G          Important Information

3 Code example

$ Analysis of Code

7 Lesson

þ        Test

& Summary

C Congratulation

 



[1] Or copy & paste

[2] You can only change before

[3] In this case an event handler