In the early days of Delphi (1995, to be exact, when Delphi 1.0 was known simply as Delphi),
the worlds greatest software development tool shipped with a paltry 43 demo
programs. There wasnt much recourse for us poor Delphi neophytes looking for
guidance but to scour the Web and ask questions on the newsgroups.
Here in the latter part of 2001, the
situation has improved dramatically. If we take a renewed look at the number
of Borland-supplied Delphi demos, we see that upwards of 150 are included with Delphi
6. And many of them are far from trivial.
Delphi developers will benefit by going through these demo programs "with
a knife and a flashlight," as Jeff Duntemann put it in
Delphi Programming
Explorer. Aspiring writers are told that in order to acquire a
sense of what is good and what is bad regarding writing style and technique, they
should read good writing: Read the classics, the best authors. The same
holds true for writing good software. Read good source code! The demos that
ship with Delphi provide a plethora of instructive examples, answers to FAQs,
and elegant solutions to common coding problems.
As proof that there is gold in them thar hills, and to whet your
appetite for prospecting there, I will now present a few of the gems I found
on a recent expedition.
{ List all the fields in a dataset (from DBFilter) }
for I := 0 to DM1.CustomerSource.Dataset.FieldCount - 1 do
ListBox1.Items.Add(DM1.Customer.Fields[I].FieldName);
{ "Home-made" primary key generator (from DBMastApp) }
with NextOrd do
begin
Open;
try
Edit;
OrdersOrderNo.Value := NextOrdNewKey.Value;
NextOrdNewKey.Value := NextOrdNewKey.Value + 1;
Post;
finally
Close;
end;
. . .
{ Map computer definitions and human definitions (from Docking) }
const
Colors: array[0..6] of TColor = (clWhite, clBlue,
clGreen, clRed, clTeal, clPurple, clLime);
ColStr: array[0..6] of string = ('White', 'Blue',
'Green', 'Red', 'Teal', 'Purple', 'Lime');
{ Sort a DBGrid (from MIDASAlchtest) }
procedure TDBClientTest.GridTitleClick(Column: TColumn);
var
DataSet: TDataSet;
begin
DataSet := Column.Field.DataSet;
if DataSet is TClientDataSet then
TClientDataSet(DataSet).IndexFieldNames :=
Column.Field.FieldName
else if DataSet is TTable then
begin
if TTable(DataSet).IndexDefs.GetIndexForFields(
Column.Field.FieldName, False) = nil then
Exit;
TTable(DataSet).IndexFieldNames :=
Column.Field.FieldName;
end;
StatusMsg := 'Sorted on '+Column.Field.FieldName;
end;
{ Example of owner draw in a grid (from MIDASMstrDtl) }
procedure TClientForm.MemberGridDrawColumnCell(Sender:
TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State:
TGridDrawState);
begin
if DM.ProjectTEAM_LEADER.Value =
DM.Emp_ProjEMP_NO.Value then
MemberGrid.Canvas.Font.Style := [fsBold];
MemberGrid.DefaultDrawColumnCell(
Rect, DataCol, Column, State);
end;
{ Display the available fonts... }
procedure TForm1.FormCreate(Sender: TObject);
begin
Listbox1.Items := Screen.Fonts;
end;
{ ...using the appropriate font... }
procedure TForm1.DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
begin
with ListBox1.Canvas do
begin
FillRect(Rect);
Font.Name := ListBox1.Items[Index];
Font.Size := 0; // use font's preferred size
TextOut(Rect.Left+1, Rect.Top+1,
ListBox1.Items[Index]);
end;
end;
{ ...and size them correctly (from Ownerlst) }
procedure TForm1.ListBox1MeasureItem(Control: TWinControl;
Index: Integer; var Height: Integer);
begin
with ListBox1.Canvas do
begin
Font.Name := Listbox1.Items[Index];
Font.Size := 0; // use font's preferred size
Height := TextHeight('Wg') + 2; // measure ascenders
// and descenders
end;
end;
{ Show total/available memory (from CoolStuff) }
var
MS: TMemoryStatus;
begin
GlobalMemoryStatus(MS);
PhysMem.Caption := FormatFloat('#,###" KB"',
MS.dwTotalPhys / 1024);
FreeRes.Caption := Format('%d %%', [MS.dwMemoryLoad]);
. . .
{ If appropriate, allow user to select a Save option (from RichEdit) }
procedure TMainForm.CheckFileSave;
var
SaveResp: Integer;
begin
if not Editor.Modified then Exit;
SaveResp := MessageDlg(Format(sSaveChanges, [FFileName]),
mtConfirmation, mbYesNoCancel, 0);
case SaveResp of
idYes: FileSave(Self);
idNo: {Nothing};
idCancel: Abort;
end;
end;
{ File | Save code (from RichEdit)}
procedure TMainForm.FileSave(Sender: TObject);
begin
if FFileName = sUntitled then
FileSaveAs(Sender)
else
begin
Editor.Lines.SaveToFile(FFileName);
Editor.Modified := False;
SetModified(False);
end;
end;
{ File | Save As code (from RichEdit)}
procedure TMainForm.FileSaveAs(Sender: TObject);
begin
if SaveDialog.Execute then
begin
if FileExists(SaveDialog.FileName) then
if MessageDlg(Format(sOverWrite,
[SaveDialog.FileName]),
mtConfirmation, mbYesNoCancel, 0) <> idYes then
Exit;
Editor.Lines.SaveToFile(SaveDialog.FileName);
SetFileName(SaveDialog.FileName);
Editor.Modified := False;
SetModified(False);
end;
end;
{ Undo code (from RichEdit) }
procedure TMainForm.EditUndo(Sender: TObject);
begin
with Editor do
if HandleAllocated then SendMessage(
Handle, EM_UNDO, 0, 0);
end;
{ Display cursor position in TMemo or TRichEdit in status bar (from RichEdit) }
procedure TMainForm.UpdateCursorPos;
var
CharPos: TPoint;
begin
CharPos.Y := SendMessage(
Editor.Handle, EM_EXLINEFROMCHAR, 0,
Editor.SelStart);
CharPos.X := (Editor.SelStart -
SendMessage(
Editor.Handle, EM_LINEINDEX, CharPos.Y, 0));
Inc(CharPos.Y);
Inc(CharPos.X);
StatusBar.Panels[0].Text :=
Format(sColRowInfo, [CharPos.Y, CharPos.X]);
end;
{ Process virtual key codes (from VirtualListView) }
procedure TForm1.ListViewKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of
VK_RETURN:
ListViewDblClick(Sender);
VK_BACK:
btnBackClick(Sender);
end;
end;
{ Alternate grids background color (from WebServIIS) }
procedure TCustomerInfoModule.EmployeeListFormatCell(Sender: TObject;
CellRow, CellColumn: Integer; var BgColor: THTMLBgColor;
var Align: THTMLAlign; var VAlign: THTMLVAlign; var
CustomAttrs, CellData: String);
begin
if CellRow = 0 then BgColor := 'Gray'
else if CellRow mod 2 = 0 then BgColor := 'Silver';
end;
Maybe Im easily amused, but I got a thrill out of many of these snippets.
And there are many other gems lying just below the surface
in the demos. (Finding the remainder is an AELTTR, an exercise left to the
reader.)
Ive included here many of the useful bits that are applicable across most types of projects. The more
specific and lower-level types of things (such as BinToHex conversions,
streaming components, converting a .bmp to a .jpg, enumerating mapped
drives, user-defined messages, callbacks, sort implementations, and so on) have not been included in this article. Depending
on your particular area of interest, you will probably want to concentrate your focus
on particular demos.
As Benjamin Franklin said, "An investment in knowledge always pays the best interest."
Clay Shannon doesnt know if he is a programmer who also happens to be a
writer, or vice versa. He is the author of The Tomes of Delphi: Developers Guide to
Troubleshooting (Wordware 2001) and the novel Twisted Roads, which features a Delphi developer as one of the
main characters. Clay has just finished his latest novel, entitled The Resurrection
of Samuel Clemens, set in the year 2061. You can contact him at BClayShannon@aol.com.