Using code templates
There’s a scorned but ever-popular coding technique often called ‘clipboard inheritance’. This is where you find yourself needing to write some code that is nearly, but not quite the same as something you have already written, perhaps in the same project. With clipboard inheritance, you select the old code and paste it somewhere else, then amend it as needed. This usually results in a bloated and unmaintainable project. If you find a bug in the original code, you might fix it, but forget about the pasted copy. In general, duplicated code is a clue that your project needs refactoring, perhaps by creating a new class that can accommodate both the original and new requirement with suitable parameters.
More about code templates
A code template is stored as XML and has some intelligence. Code templates have their own tool window, and Delphi 2006 comes with a selection of templates for each language. To invoke a code template, you can right-click the template and choose ‘Execute’, or else double-click the template name. This inserts the template into your code.
There are two template types. Normally, the template code is pasted into the editor at the insertion point. However, there are also surround templates, which paste code above and below any selected text in the editor. An example is the brace template, which comments out selected code by inserting a brace top and bottom. Surround templates are also accessible from a right-click Surround menu in the editor. Once the template is pasted into your code, it remains live. Press [TAB], and the first hot spot in the template highlights, so you can customise it. Press [TAB] again, and the next hot-spot highlights until you’re done.
You can try this with the procedure template. Insert this template and skeleton code appears, with the name of the procedure highlighted. Type the name, then press [TAB], and the cursor jumps to the procedure parameters. Press [TAB] again, and the cursor jumps to the body of the code.
You can edit code templates and create your own. The XML schema allows for hints that display when completing the template, so this could be a simple way to include prompts that help you to conform to coding standards. Overall it’s considerably more useful than the old code snippets.
Creating the mail app
For this application, we will use the MapiMail unit kindly made available as freeware by Scalabium Software (www.scalabium.com/smcmpnts.htm). Download mapimail.zip and add sendmail.pas to a new Win32 VCL forms application. Add this unit to the uses clause of the main form, then test it with the following code:
procedure SendMail;
var
mapimail: TMapiMail;
begin
mapimail := TMapiMail.Create(application.MainForm);
try
mapimail.Subject := ‘PC Plus email example’;
mapimail.Body := ‘This email is sent from Delphi 2006’;
mapimail.Recipients.Add(‘you@somefakeisp.co.uk’);
if not mapimail.Send then
application.MessageBox(‘Error sending mail’, 0);
finally
mapimail.Free;
end;
end;
Naturally you need to use an email address that is both valid and safe to use, probably your own. Run the code, and all being well it will open your default email client with the message ready to send. The code does not actually send the mail, as that’s down to the user. However, if the message is not sent, an error is returned to the application.
This kind of code is well suited to a code template. Working with a late preview of Delphi 2006, here is how we created one. However, please note that the final release may differ slightly, though major change is unlikely.
First, from the template toolbar, click ‘New’ to open a new skeleton template. This is actually itself a code template, and prompts you for the template name. Type ‘MapiMail’, then press [TAB]. Tab through and enter values for the Description, Author, and finally the language.
Now you can proceed to edit the template. For a simple template, all you need to do is paste the code that forms the SendMail procedure in the CDATA section. Note exactly where it goes, between the second square brackets in CDATA:
<code language=”Delphi” context=”methoddecl” delimiter=”|”><![CDATA[ your code here]]>
You may also need to add the context and delimiter attributes.The template so far is not much more than a code snippet. Here is where we add some intelligence. The first thing the user will need to do is to name the procedure. To make this editable, we define a <point> element as a child of the <template> element, which looks like this:
<template name=”MapiMail” invoke=”manual”>
<point name=”procname”>
<text>
SendMail
</text>
<hint>
The procedure name
</hint>
</point>
What we have done is to define a kind of variable called ‘procname’. We can now amend the CDATA section as follows:
procedure |procname|;
When the template is executed, procname will be the first hot spot in the template. The text SendMail will be highlighted, the hint appears, and you can type the procedure name you want to use instead. To complete the template, make point elements for subject, body and recipient, then save it in the correct location for the Delphi IDE to pick it up. Be warned: in the preview release, if you mess up and save a faulty template, the IDE may start misbehaving. If this happens, delete or move your template manually and try again.
Now you can test the template. Open the code editor and execute the MapiMail template. You can type the name of the new procedure and press [TAB], press [TAB] and type the subject, [TAB] again, and enter the recipient, [TAB] again and enter the body of the message. The template greatly reduces your typing to the bare minimum, automating the creation of a complete Delphi procedure.
Also new in Delphi 2006: Class fields
Delphi 2006 introduces class fields, also known as static fields, to Win32 as well as .NET. This is a field that belongs to the type, rather than to any of its instances. Class fields are defined with the keywords ‘class var’ instead of the familiar ‘var’. For example, one simple way of tracking object usage and catching possible memory leaks is to program a static field that maintains a count of live instances. This instance count is incremented in the constructor and then decremented in the destructor:
TSomeClass = class(TObject)
public
{ public declarations }
class var
HowManyLive: integer;
var
SomeVar: integer;
constructor create;
destructor Destroy; override;
end;
implementation
constructor TSomeClass.create;
begin
inc(HowManyLive);
end;
destructor TSomeClass.destroy;
begin
dec(HowManyLive);
end;
This lets you write code like this:
procedure TForm1.
Button1Click(Sender: TObject);
var
SomeObject : TSomeClass;
begin
SomeObject := TSomeClass.Create;
self.Caption := ‘There are ‘ + inttostr(TSomeClass.HowManyLive) + ‘ instances of TSomeClass live’;
end;
There are times when a class field is the most intuitive way to handle what is, in effect, a global variable. They can also fulfil a similar role to enumerated types:
TTrafficLight = class(TObject)
public
{ public declarations }
class var
Red: integer;
Amber: integer;
Green: integer;
end;
You will need to initialise the values somewhere, such as in the initialisation section of the unit defining the class. However, if you do not have Delphi 2006, there are other ways of achieving a similar result, such as declaring variables at the unit level, outside any class.
Enhanced Record type
The Record type in Delphi 2006 has a bunch of new class-like abilities. A Record is similar to a struct in C and allows several fields in one type. A classic example is TPoint:
type
TMyPoint = record
x: integer;
y: integer;
end;
Records can have constructors, such as the following:
typeTMyPoint = record
x: integer;
y: integer;
constructor create(InitX: integer;
InitY: integer);
end;
implementation
constructor TMYpoint.create(InitX:
Integer; InitY: Integer);
begin
self.x := InitX;
self.y := InitY;
end;
This is only a convenience, since you cannot prevent the record being used without calling the constructor, and you cannot override the default constructor that takes no parameters. You can also do operator overloading with records in Win32. Normally, adding two record types would raise the error ‘Operator not applicable to this operand type’. However, you might decide that adding two points should sum the individual fields. Add the following to the interface:
class operator Add(a, b: TMyPoint): TMyPoint;
And to the implementation:
class operator TMyPoint.Add(a, b: TMyPoint): TMyPoint;
begin
result.x := a.x + b.x;
result.y := a.y + b.y;
end;
Then you can add two records of this type:
mypoint3 := mypoint1 + mypoint2;
Oddly, this is supported for records, but not classes in Win32, whereas in Delphi .NET it’s supported for both records and classes. So this is one area in which records have the advantage.
Colour-coded history
A neat feature of the Delphi 2006 editor is colour coding that helps you keep track of your edits throughout your programming. Changes you have made during the session, and saved, are highlighted in green in the editor’s gutter or left margin. Changes you have not yet saved are highlighted in yellow, making it easy to see what you’ve changed, and whether it’s better to go back a bit.

