Delphi Informant 95 2001

You are on page 1of 51

August 1995 - Volume 1, Number 4

Application Development
Implementing MDI, On-Line Help,
and .INI Files

ON THE COVER
9 Creating MDI Apps — Jonathan Matcho
In the Microsoft Windows development environment, there
are two ways you can go with the basic interface of any
application you create: MDI or SDI. This month, Mr
Matcho gets us started with the basics of the Multiple
Document Interface.

14 A Topical Search — Robert Palomo


Now, more than ever, any major Windows applications fea- Cover Art By: Victor Kongkadee
tures an on-line, hypertext, context-sensitive help system
based on the Windows help engine. Mr Palomo introduces
us to the basics and then gets to the nitty gritty of imple- 40 On-Line — Rand McKinney
menting such a system in Delphi. Remarkably, a wide assortment of Delphi-centric World-
Wide Web sites have already stepped onto the Internet
20 Initialization Rites — Douglas Horn stage. From the official Borland sites to “Delphi Hacker’s
There’s an accepted Windows standard for storing infor- Corner”, Mr McKinney picks his favorites and offers an
mation from one session of an application to another: the HTML to make it all easy.
humble .INI file. Delphi makes manipulating these initial-
ization files particularly straightforward by encapsulating 43 At Your Fingertips — David Rippy
them with its TINIFile object, as Mr Horn explains. Our popular bi-monthly tips column is back. This
month, Mr Rippy shows us how to implement a “hot
FEATURES regions” user interface, a poor-man’s glossary system,
and a quick-and-dirty way to copy a record from one
25 OP Basics — Charles Calvert table to another.
If you come from a non-Pascal background, you may have
already noticed that the Object Pascal string type is unlike REVIEWS
its C/C++ cousin. However, Pascal does offer null-termi-
nated strings as well. Mr Calvert makes it all plain in this 45 InfoPower
first of a three-part series on strings. Product review by Joseph Fung
50 Delphi Nuts & Bolts
29 DBNavigator — Cary Jensen, Ph.D. Book review by Larry Clark
In this month’s DBNavigator, Mr Jensen kicks off a
two-part series on data validation. The focus this 50 Delphi Unleashed
month is on checking non-table data, featuring a Book review by Cary Jensen, Ph.D.
try...except block and a discussion of field-level ver- 51 Delphi Programming EXplorer
sus record-level validation. Book review by Tim Feldman
34 Sights and Sounds — David Faulkner
Mr Faulkner adds a little color to the issue with his “color DEPARTMENTS
triangle”. Make that, lots of color and a good measure of 2 Editorial/Letters
algebra to boot! In any case, it’s a fine example of 4 Delphi Tools
Delphi’s screen-painting capabilities, compiler options, 7 Newsline
uses tricks, and more.

AUGUST 1995 Delphi INFORMANT ▲ 1


You gotta take it down to the drums. It’s the only way you’re gonna get it right.
— Iggy Pop

he obscure Metallic KO is a live recording of the apocalyptic final concert of Iggy Pop and the Stooges.

T It captures an odd moment in music history and is remarkable in several respects, not the least of
which is that it was ever released. It records the Stooges playing abominably in front of an overtly
hostile audience. You can even hear bottles breaking as they hit the stage. At one point the band is so out
of sync that Iggy Pop shouts over the cacophony and orders them to “take it down to the drums.” Slowly,
agonizingly, in front of a hooting crowd, the Stooges comply. Apocalyptic — yes. Good music — hardly.

In this business, the readers set the Love the mag ner, but can already follow (and near-
tempo and I have no intention of letting us Hi Jerry: The last three issues of ly understand) most of your articles.
get out of sync, so I decided to take it Delphi Informant have been fabulous. This does not mean that the level is
“down to the drums” from the get-go. In I read a ton of magazines and this one not right — it is. A good mix of intro-
June I asked you to let us know how we’re is tops. It is just right in length and ductory and more advanced in fact.
doing and what types of articles you’d like wonderful in layout. ... (3) I like the little tips in “At Your
to see. And you did. How about an article that carefully Fingertips”. Please do keep little
I was greatly relieved to see from your dissects a simple (not too simple) snippets like the “incremental search
letters that we’re on track so far. In fact object? An article that hits on the con- field”. It reminds me to not waste
the response has been overwhelmingly structor, destructor, and all the parts money on some third-party product
positive — and for that I thank you. You of a custom component would be very that offers such simple stuff!
also did a fine job of burying us in article nice. ... I prefer reading about the <smile> I know that lots of powerful
requests, and they are also very much basics of objects. stuff is just a matter of reading the
appreciated. All have been duly noted and This is virgin territory for a lot of us manuals and practicing and the tips
a list has been made available to all cur- out here. And keep hitting the data- help with this. ... (4) Third-party
rent and prospective DI writers. base stuff a lot too. product and book reviews are very
Taking your messages as a whole, sever- Congrats on a fine publication. Well useful. Yes — I’ll buy good-value
al points came through loud and clear. worth the money. — Chip Mayer third-party components. I’ve also got
For one, you do want an editorial section the Dummies book and it is very good
with letters to the editor, so here you are. Thank you Chip! Although we want to hear as you said (lots of tips again). Still
I’ve attempted to capture most of the all comments — positive and negative — waiting to buy the Sams Delphi
other major points with representative this is the kind of message that keeps us Developer’s Guide and Waite Groups’
letters, so I’m going to let you do the rest going. Feel free to send them any time. <g> Borland Delphi How-To. ... Maybe
of the talking. And don’t worry — I won’t run a couple of you have some reviews coming on
I’d like to avoid the sort of humiliating, pages of “you guys are great” messages. But these before I buy? (5) Don’t waste
public course correction that the Stooges keep in mind that I can if I need to. <g> too much space on VB! Give those
suffered in the early 70’s (oh yeah — long fellas a short while to convert, but
before punk), so you can bet I’ll be listen- Suggestions, suggestions, suggestions don’t waste valuable space when it’s
ing. Let’s keep in sync. Jerry. A few comments on your new Delphi stuff we want. (6) Object
mag as requested. ... (1) Yes, I do like Pascal basic-to-intermediate level
the editorial page. A useful communi- articles would be helpful for many. ...
cation that makes the magazine seem Thanks for an interesting and useful
— Jerry Coffey, Editor-in-Chief more complete. Nice to hear from the magazine. Looking forward to my next
CompuServe ID: 70304,3633 busy Editor-in-Chief. (2) I’m a begin- one. — Richard Entwistle, Hong Kong

AUGUST 1995 Delphi INFORMANT ▲ 2


Editorial

This pithy message from Mr Entwistle is enough of it. Could you please get a little behind (one of them follows). We fully intend
fairly typical. Most of you have responded more between the covers? That’s the to keep a good balance by offering articles
with such thoughtful critiques. Thank you! only negative thing I can say about DI. for programmers at all levels of expertise.
Thank you! Thank you! Regarding the book DI seems to have a pretty good balance
reviews — we plan to review every Delphi of material. Anyway, thanks for a great Too technical
book as soon as it is available. The two you magazine. I’ve already cleared a spot on Dear Sir,
mention aren’t out yet, but three that are the bookshelf for future volumes. ... I am frustrated with some of the
available are reviewed in this issue. By the way, have you noticed how articles provided in the first two issues
many WWW sites are forming of DI. I am brand new to Delphi, Pascal,
Not too much database please around Delphi? Amazing! Do you and OOP. My background is DOS and
First, I like the editorial ... How you think DI will talk about the offerings BASIC, so Delphi is quite a big under-
are doing? IMHO, wonderfully! It is of these sites? — bt taking for me. ... My subscription to DI
an information-packed magazine with is part of this process.
something for everyone, and don’t One thing virtually everyone agreed on was In particular, I find that there are
change that! ... Topic spread: Pretty that DI could be a bit bigger. All of you some assumptions made on the part of
good, considering you have only pub- should be happy to note that this month’s some writers that their readers know
lished two issues as of yet. Keep it up! issue is 16 pages longer (that’s one “signa- certain terms or lingo. For example, in
Object Pascal: Like many coming from ture” in the biz). It certainly makes me issue one, you had an article by Dan
a strong Visual Basic background ... I happier. From an editorial stand-point it Ehrmann called “Data-Aware Delphi”.
don’t know everything in the Object allows us to offer broader coverage. Our It dealt with modifying a query compo-
Pascal language itself yet. Thus, the WWW coverage begins on page 40. nent via a tabbed interface. ... even
more of it, the better! though this article is identified for
Databases: Eeeiiiii! Everybody seems Not technical enough “Beginner/Intermediate”, nowhere could
to assume that VB programmers pro- I just read the first issue of the DI. I I find information on what a table is! ...
gram databases! As a game/edutain- was very excited to read some articles Questions arose in my mind: 1) What is
ment author, I take umbrage at that. ... with deep insight into Delphi and the a table? 2) How are tables created? Do
There are a lot of database program- VCL ... I think, DI has a good chance they float down out of the sky? 3) How
mers, so I’m not suggesting that you to become a major Delphi developers does one add data to a table? 4) Is a
remove those articles from the maga- information magazine, but I would .DBF file a table? ... then the author
zine, but keep it under control if you recommend that you offer articles that throws the term query around as if
don’t want to lose the general program- are more technical. ... One could write everyone knew what a query was. ...
ming contingent. ... More graphics-ori- about the architecture and implemen- Thank you for your time.
ented articles would be nice. tation of the VCL database compo- — Philip Kapusta
... I noticed something missing from nents ... OLE programming with
your magazine; a letters department ... Delphi ... a dockable toolbar ... Mail- Too technical, not technical enough —
it would be nice to see what other peo- access components ... There are lots of these are the kinds of things that keep edi-
ple think of Delphi Informant. complicated things to write about. tors awake nights. I’m afraid there’s little I
In general, I really like the maga- This criticism should not be taken as a can do except try to steer down the middle.
zine, and will most likely subscribe to very strong one. I can imagine it is a lot As long as these letters are in balance, we’re
it soon if this quality continues! Keep of work to start a new magazine. It on course — and your feedback is critical.
up the great work! — Michael should be taken as a friendly hint ... Let me close with a final question. Philip
what a Delphi developer with some refers to a practice we used only in the pre-
Thanks Michael. And don’t worry — we practice would like to read. miere issue of DI (which is sold out BTW —
won’t let the magazine be dominated by Thanks for your work on Delphi thank you very much), that of labeling arti-
any one programming area. There’s a cool Informant — Christian Abeln cles as Beginner, Intermediate, etc. In prac-
graphics article beginning on page 34. tice, I found this distinction a highly subjec-
BTW, have you subscribed yet? <g> Are there ever lots of technical things to write tive one and simply quit doing it. A number
about! And thank you Christian for the of you have asked for its return however, so
Give us more! “friendly hint” to supply more advanced please let me know how you feel. I can
Mr. Coffey, you asked for feedback. articles. (There were a couple of similar let- always bring it back if you find it
Well, here is mine. I just received my ters that weren’t as kind.) However, there were useful.
first issue (V1N2) of Delphi Informant. also many letters exhorting us not to become Thanks again for all your
In short, I loved it. In fact, I couldn’t get too technical and leave those learning Delphi messages. — J.C.

AUGUST 1995 Delphi INFORMANT ▲ 3


Delphi MKS’ Source Integrity Released
Mortice Kern Systems of by configuring particular tomizable toolbar and easy-
T O O L S Waterloo, ON has released a events to automatically trigger to-use configuration.
new version of MKS Source a second event. For example,
New Products Integrity (formerly MKS MKS Source Integrity can be Price: US$449, upgrade for current users
and Solutions RCS). It brings users a new configured to automatically US$149.
and complete configuration mail a confirmation message
Contact: MKS 185 Colombia Street
management system that to the project leader each time
West, Waterloo, ON, Canada, N2L 5Z5
encourages multi-user develop- a team member checks in a
ment. Version 7.1 fits into new file. Phone: (519) 884-2251
development environments, In addition, Source
and will include Visual Merge, Integrity features a fully-cus- Fax: (519) 884-8861
enhanced reporting capabili-
ties, event triggers, a new con-
figuration language, integra-
tion into Visual C++ and
Borland C++, and other pro-
New Delphi Books
ject management facilities.
Teach Yourself Delphi in 21 Days MKS Source Integrity is the
Andrew J. Wozniewicx
& Namir Shammas only PC version control system
Sams Publishing offering an interactive, visual
ISBN: 0-672-30470-8
Teach Yourself uses example and merge facility. Developers will
full code listings to explain how to save time by merging files with
combine visual programming with
Object Pascal. It covers DLLs, a mouse click.
DDE, and OLE components, Source Integrity automates
exception handling, program
architecture, and more. your configuration manage-
Price: US$29.99 (912 pages) ment system even more with
Phone: (800) 488-5233
event triggers. Time is saved
Borland Delphi How-To
Gary Frerking, Wayne Niddery,
& Nathan Wallace
Access Btrieve Data with Titan for Delphi
Waite Group Press AmiSys Inc., of Concord, tools such as the Database
ISBN: 1-57169-019-0
Price: Titan for Delphi Runtime Version,
Borland Delphi How-To presents CA has released Titan for Form Expert, Field Editor, US$295.
over 100 programming problems Delphi, a Btrieve interface and Master/Detail relation-
and their solutions. It covers
graphics, document, multimedia, for Delphi developers. Titan ships between tables. Contact: AmiSys Incorporated, 1390
database, OLE, and DDE issues. is a drop-in replacement for In the future, AmiSys plans Willow Pass Road, Suite 930, Concord,
This book ships with a CD-ROM
containing resources, bitmaps, the IDAPI used in Delphi. It to release a TQuery compo- CA 94520-5253
and custom components. allows Delphi users to access nent, integrate calls to the
Price: US$39.95 Phone: (510) 671-2103
(700 pages, CD-ROM) Btrieve data files without IDAPI, and enable Titan to
Phone: (800) 368-9369 using the ODBC layer pro- access non-Borland databases. Fax: (510) 671-2104
vided through IDAPI. Also,
Titan allows the developer to
use all the standard Delphi Delphi Btrieve Data Flow Titan for Delphi Data Flow
data-aware components, such
as grid, edit, checkbox, and Application Application
list box controls without
modifications.
Delphi Database Components Delphi Database Components
Titan doesn’t require any
IDAPI dynamic link library
(DLL) files to be installed or Borland Database Engine
configured on the target sys- Titan for Delphi
tem. It supports multiple High Performance Engine
databases through the use of ODBC Interface
Btrieve standard Data Defi-
nition files (DDFs).
Btrieve Btrieve
Titan supports all the
Delphi visual development

AUGUST 1995 Delphi INFORMANT ▲ 4


Delphi Delphi Component Creates Paradox for Windows Reports
T O O L S Kirsch & Partners Limited page orientation, overflow con-
of Markham, ON has trol, the base table for reporting,
New Products announced the release of aliases, page numbering and off-
and Solutions PdoxRept, a reporting compo- sets, and previewing.
nent for Delphi. PdoxRept ships with the lat-
With PdoxRept, Delphi est run-time version of
developers can create reports Paradox for Windows, so users
using Paradox for Windows, do not need to own or learn
and deliver executables to Paradox. The license agree-
users along with the Paradox ment allows developers to dis-
report files (RDLs or RSLs). tribute executable code with-
PdoxRept will print without out additional license or fee.
displaying splash screens or
start-time requests. And with Price: Introductory price, US$99.95
RDLs, developers can be sure (regularly US$149.95).
Delphi Training the reports won’t be acciden-
tally modified. Contact: Kirsch & Partners Limited,
UDP Solutions Center, a
Borland training member, is offer- PdoxRept offers approximately 3105 Markham Industrial Park, Markham,
ing an advanced course in Delphi 24 properties, giving developers ON, Canada L3R 6G4
Client/Server application devel-
opment. Borland’s official course full control over printing,
material is taught at an accelerat- including the number of copies, Phone: (416) 967-1660
ed pace, and concludes with sup-
plemental materials relating to
client/server applications, such as
an exercise building an applica-
tion using an MS SQL server in a
true client/server environment. Syware Announces Dr. DeeBee Tools
UDP will be offering client/server
application development using
Syware Inc., of Cambridge, DeeBee Timer (counts the of their driver, and to run tests
Delphi (5 days) US$1875.00 MA has announced the release ODBC calls an application against the driver. Support
on Aug. 28 - Sept. 1 and
Sept. 11-15. For more
of Dr. DeeBee Tools, a suite of makes and their duration), organizations for ODBC prod-
information and registration utilities for ODBC developers Dr. DeeBee Test (runs regres- ucts use Dr. DeeBee Tools to
materials, contact:
Christopher Simmons at
and product support organiza- sion tests on ODBC drivers), determine their customers’
(503) 690-6877 or e-mail tions to monitor the operation Dr. DeeBee Spy (a version of ODBC problems and to pin-
[email protected]
of ODBC-enabled applica- Dr. DeeBee Peek for product point whether the problem is
tions and drivers. support organizations that in the application or driver.
Dr. DeeBee Tools provide can be re-distributed), Dr. Dr. DeeBee Tools work with
insight into the performance DeeBee Replay (replays logs all ODBC applications, includ-
and inner workings of generated by Dr. DeeBee ing those created by Microsoft’s
ODBC. It includes a suite of Spy), and Dr. DeeBee Info Access, Visual Basic, and
seven utilities: Dr. DeeBee (displays description and Borland’s Paradox, Delphi, and
Check (semantically checks characteristics of a driver). C/C++. Dr. DeeBee Tools are
ODBC applications at run- ODBC application and dri- compatible with both ODBC
time), Dr. DeeBee Peek ver writers, along with their 1.0 and ODBC 2.0.
(records ODBC calls made customer support organiza-
by an application), Dr. tions, use Dr. DeeBee to mon- Price: US$399 for the Super Bundle
itor, optimize, and test ODBC (all seven tools); or US$199 for the
products and projects. Starter Bundle (Info, Peek, and Timer).
Dr. DeeBee Tools reports on Corporate site license and reseller prices
the ODBC performance of an are available.
application. It helps developers
determine how the application Contact: Syware Inc., P.O. Box 91
is using ODBC, and if the Kendall, Cambridge, MA 02142
application is using ODBC
properly. ODBC driver writers Phone: (617) 497-1376
use Dr. DeeBee Tools to deter-
mine the use and performance Fax: (617) 497-8729

AUGUST 1995 Delphi INFORMANT ▲ 5


Delphi MicroHelp Releases SpellPro 2 & Thesaurus
T O O L S MicroHelp, Inc. of Marietta, ing time, AutoLinkHwnd run-time royalties for distrib-
GA has recently released functionality that allows appli- uted applications.
New Products SpellPro 2 & Thesaurus, an cations to be automatically
and Solutions upgrade to its SpellPro tool linked to the DLL, and multi- Price: US$129
that enables programmers to ple discardable code segments
build spell check functions that reduce the amount of Contact: MicroHelp Inc., 4211 J.V.L.
into visual applications. memory needed. Industrial Park Drive, NE, Marietta, GA
SpellPro 2 & Thesaurus SpellPro 2 & Thesaurus 30066
includes a thesaurus that uses can check 60,000+ words per
a dictionary of more than minute using a Pentium/66 Phone: (800) 922-3383, or
50,000 synonyms. The pack- processor. It also features (404) 516-0899
age contains DLL, VBX, and utilities for building individ-
16/32-bit OLE controls. ual dictionary and thesaurus Fax: (404) 516-1099
SpellPro 2 now supports mul- files, and medical and legal
tiple custom dictionaries while dictionaries. There are no BBS: (404) 516-1497
EMS Professional Shareware has its new dictionary utility gives
released Professional Shareware more than 50 percent compres-
Libraries, adding three new
libraries for Delphi, Clarion, and sion and is three times faster
NT, featuring over 100 tools for when exporting a dictionary to
developers and consultants.
Each library includes a search a text file. The common-word
program allowing users to search cache has been increased from
for a utility by product name,
producer, type, release date, or 25 to 1024 words and includes
with a free text search across all user-definable language settings.
information in the database.
The first library purchased costs Additionally, SpellPro’s preload
US$59.50, and any additional function decreases start-up time.
libraries are US$25. For more
information contact EMS at SpellPro 2 also features built-
(301) 924-3594, or e-mail in dialog boxes to reduce cod-
[email protected].

ProtoView Releases DataTable


ProtoView Development to create powerful database null values, multi-line column
Corp. of Cranbury, NJ has manipulation applications and row labels, automatic
released DataTable version without coding. insertion of empty rows,
2.7 for Delphi. DataTable is DataTable supports over 32 multi-line data entry in a cell,
a Windows grid control that different data types, including and advanced methods and
gives applications the look Microsoft SQL Server, Sybase notifications. With DataTable,
and feel of a professional SQL server and more. The developers can set fonts and
spreadsheet. It provides visu- Delphi developer has com- colors for row and column
al access to database tables, plete control of the DataTable labels, sort with up to three
and allows Delphi developers through design-time Object sort keys, and display cells as
Inspector settings, API, and check, list, or combo boxes.
numerous notification codes.
DataTable features design Price: US$149; source code, US$495.
time visual setting via the Applications created using the DataTable
Delphi Object Inspector, may be distributed royalty free.
Delphi Data Sources support,
cell formatting, editing within Contact: ProtoView Development
individual cells, row and col- Corporation, 2540 Route 130, Cranbury,
umn selection, and horizontal NJ 08512
and vertical grid lines.
It also includes three-dimen- Phone: (800) 231-8588 or
sional row and column styles, (609) 655-5000
column re-sizing, hidden
columns, support for database Fax: (609) 655-5353

AUGUST 1995 Delphi INFORMANT ▲ 6


News Visual Components Made Delphi Ready
Lenexa, KS — Visual
Components, Inc. has
Delphi to add high-quality
spreadsheet, charting, and
Impression, and
VisualSpeller is held in the
L I N E announced the release of spell checking functionality to core DLL. By using the dec-
Delphi-specific declaration Delphi applications. laration files, Delphi devel-
August 1995 fields for Formula One, First According to the company, opers can easily access and
Impression, and VisualSpeller. the declaration files make it use this functionality.
These products are now ship- easier for Delphi developers For more information visit
ping with current builds of to access the core DLL of Visual Components on
each product. each product. This is impor- CompuServe (GO VIS-
The declaration files make it tant because all the function- TOOLS) or contact them at
easier for developers using ality of Formula One, First (913) 599-6500.

Borland Conference Europe 96: A Call for Papers


Portsmouth, UK — Desktop All materials must be submitted (0)1705 822254, fax: +44
Associates Ltd. and Dunstan no later than September 1, 1995. (0)1705 8223999, or e-mail:
Thomas Ltd. are accepting Speakers will be selected [email protected]
Borland International Inc.’s papers for the Borland and required to submit a or 100014,2273.
Sixth Annual Developers Conference Europe 96, sched- written version of each pre- Or write to: Chris Read,
Conference, to be held August
6-9 in San Diego, CA, will focus uled for April 28 - 30, 1996 sentation, code samples, and Dunstan Thomas Ltd., The
on helping developers make a in London. presentation slides. Old Treasury, 1 St. Paul’s
smooth transition to Windows
95. The conference is expected There are three types of pre- For submissions please con- Road, Portsmouth, PO5 4JU,
to attract over a thousand devel- sentations: Pre-Conference tact Chris Read at Dunstan UK. Please mark correspon-
opers from around the world and
will feature over 200 sessions. Tutorials, Technical Thomas Ltd. by phone: +44 dence BCE 96.
Registration for a single attendee Presentations, and Case Studies.
is US$1,195, and US$1,145
The technical sessions are
each for three or more people
from the same company. organized into three major Borland Previews Delphi32
For more information or to
register, call (800) 350-4244 or tracks: Delphi; Paradox and Scotts Valley, CA — Borland ments. Delphi32 will also meet
(805) 495-7800 (international). Visual dBASE; and C++, International will be showing all of Microsoft’s Windows 95
Additional information about
Borland Developers Conference Decision Support Tools, the upcoming 32-bit version logo requirements. For example,
is also available on Borland InterBase, and General of Delphi at the Sixth Annual Delphi32 will be a fully-func-
Online, Borland’s World Wide
Web site at Interest. Each track has a num- Borland Developers tional Windows NT product.
http://www.borland.com. ber of threads, however, they Conference this month. The The back-end of the
do not form the definitive list version has a number of new Delphi32 compiler engine
PC Database Summit, a of topics that may be accepted. features such as forward com- will be shared with the
national conference for man-
agers, system analysts, and
The Delphi track will patibility, and OCX and Windows 95 version of
developers of database applica- include: Solutions, Windows NT support. Borland C++. This enables
tions on PCs, is scheduled for
August 20-22, 1995 in Seattle,
Programming, Tools and With Delphi32, 16-bit users to optionally create C++
WA. The conference will include Techniques, Methodologies, Delphi applications can be .OBJ files instead of Delphi’s
seminars and workshops, two
database competitions, an exhi-
Client Server, and Pre- converted to 32-bit applica- native .DCU files. The com-
bition hall, and a computer lab. Conference Tutorials. tions with a simple recompile. piler will be faster and take
Summit ’95 will be held at the
Sea-Tac Red Lion Hotel near the
All overseas speakers will The only exception would be advantage of the Windows 95
Seattle Airport and costs have their airfare and travel if the 16-bit program uses a 32-bit flat memory model.
US$395. Groups who purchase
three tickets will receive an
paid, and speakers will have Windows API call that has All products bundled with
additional free pass. For more their accommodations been modified between Delphi (Borland Database
information, or to register,
call (800) 497-7060.
arranged and paid. Windows 3.11 and Windows Engine [BDE], Database
To apply as a speaker, send a 95 — an unlikely occurrence. Desktop, and ReportSmith)
personal profile or “bio” for Delphi32 will have complete will also be 32-bit versions.
publishing in conference mate- OCX support, including a new Delphi32 and Delphi32
rials, a session title (under 100 page on the Component Palette Client/Server will begin ship-
characters), a short description with sample OCXes. It will sup- ping within 90 days of
(under 30 words) of your pre- port the entire Windows 95 Windows 95. Due to the
sentation, and an abstract of API (although some Windows uncertainty of Windows 95
you presentation (under 1000 95 API functions will not be acceptance, Borland will con-
words) in Microsoft Word for “wrapped”), and encapsulate all tinue to ship the 16-bit version
Windows or ASCII format. Windows 95 user-interface ele- of Delphi.

AUGUST 1995 Delphi INFORMANT ▲ 7


News Delphi Seminars Now Available Worldwide
Scotts Valley, CA — Borland
International Inc.’s Delphi for
offer worldwide seminar series
for Delphi developers.
tions to full 32-bit performance.
Beginning this summer,
L I N E Windows and Delphi According to Borland, the Softbite International, DSW
Client/Server application devel- Delphi series will put developers Group, and Zachary Software
August 1995 opment tools are rapidly gaining on the fast track for building the will collectively reach more
worldwide attention following next generation of Windows than 50 cities worldwide to
numerous awards from industry and client/server applications. offer developers training on
publications. The mounting With the forthcoming using Delphi to build stand-
interest in Delphi has led Windows 95 version of Delphi, alone, LAN, and client/server
Softbite International, DSW attendees will learn how they applications. Each company
Group, and Zachary Software to can easily upgrade their applica- will provide one- and two-day
seminars beginning in July and
Informant Forum Opens on CompuServe running throughout the year.
For information on seminar
Elk Grove, CA — Informant other general company infor- locations and dates, log on to
Communications Group, Inc. mation, simply post a message Borland’s Internet World Wide
ICG CompuServe Forum (ICG) launched its Informant in the customer service area. Web site at htpp://www.bor-
Structure Forum on CompuServe in late For technical information, land.com. Or contact Softbite
June. The forum was created areas have been designated for International (708) 833-0006;
to foster the exchange of tech- various topics. Informant DSW Group (800) OK-DEL-
Message Sections: nical information among authors, as well as other PHI; or Zachary Software
# Title Description
developers using industry experts, will be surf- (800) GO-DELPHI.
1 Customer Service Customer service questions
Borland’s Paradox and ing Informant Forum to lend
Delphi, and to give their expertise.
2 Pdox DOS (ALL) Paradox for DOS discussions
Informant readers an Library 19 is dedicated to
ICG Publishes New
3 Pdox Win Form/Rpts PW form or report discussions
4 Pdox Win Queries PW query discussions easy way to reach ICG. Peter F. MacGruder fans. Delphi Power Tools
5 Pdox Win ObjectPAL PW ObjectPAL discussions “Our forum has Upload your most Mac-worthy Catalog; Readies
already proven to be a news, and if he uses your
6 Pdox Win Network PW networks discussions
7 Pdox Win Wish List PW wish list discussions great way to reach our material in a column, you’ll
Paradox and C++
8 Delphi Database Delphi database discussions readers,” said Mark receive an Informant T-shirt or Elk Grove, CA — Informant
9 Delphi Win API Delphi Windows API discussions Wiseman, Operations baseball cap. Communications Group, Inc.
10 Delphi Components Delphi components discussions Manager for ICG. Informant Forum also has (ICG) has released a new
11 Delphi Obj Pascal Delphi Object Pascal discussions “We’re able to respond several libraries for Paradox Delphi Power Tools catalog.
12 Delphi Wish List Delphi wish list discussions to readers’ questions and Delphi downloadables. In addition, ICG is accepting
22 Jobs/Help Wanted Help wanted/job opportunities within minutes.” If you View the Delphi custom advertising for the upcoming
23 Database Industry Database industry discussions have a question about components, utilities, and Paradox and C++ Power Tools
your subscription, would other files available. For catalogs. Each catalog features
Library Sections: like to subscribe, or need prospective writers, the third-party add-in products
# Title Description Paradox Informant and and services that complement
1 General - Cust Srv Subscription information Delphi Informant Writer’s Delphi, Paradox for Windows
2 New Paradox Uploads New Paradox Informant code samples Style Guides and Editorial (PW), or C++, respectively.
3 New Delphi Uploads New Delphi Informant code samples, etc. Calendars are available for These catalogs are indepen-
5 Pdox DOS 4.x Paradox for DOS magazine code samples download in Library 21 dently produced by ICG and
6 Pdox DOS Demo/Share Paradox for DOS demo/shareware programs (Editorial Information). inserted into each copy of
8 Pdox Win 4.x PW 4.x magazine code samples To visit the Informant Delphi, PW, or C++.
9 Pdox Win 5.x PW 5.x magazine code samples Forum type “GO ICGFO- The next edition of Delphi
11 Pdox Win Demo/Share PW tools/demo/shareware programs RUM” at any CompuServe Power Tools is already under-
12 Delphi 1.x Delphi Informant code samples
GO prompt. If you want to way. For advertising informa-
14 Delphi Demo/Share Delphi tools/demo/shareware programs
join CompuServe, you can tion, phone Lynn Beaudoin at
17 General Windows General Windows utility files
19 Ltr to Ed/MacGruder Upload private files to Editorial Dept./MacGruder
obtain a CompuServe starter (916) 686-6610, ext. 17 (e-
20 Back Issues Info Back Issue catalog file kit including a US$15 usage mail: 74764,1205) or Sheri
21 Editorial Info Editorial information downloads, including writer style guides credit by calling toll-free in Birkmaier at (916) 686-6610,
and editorial calendars the United States (800) 524- ext. 21 (e-mail:
22 Jobs/Help Wanted Employment opportunities 3388 and asking for REP 76072,1720).
23 ICG News Informant Communications Group news number 547.

AUGUST 1995 Delphi INFORMANT ▲ 8


On the Cover
Delphi / Object Pascal

By Jonathan Matcho

Creating MDI Apps


Multi-Form Delphi Applications: Part I

hile a form alone can certainly be considered an application, appli-

W cations typically consist of several forms. When developing a multi-


form Windows application, you can choose from two major ways of
presenting the overall application interface: the Multiple Document Interface
(MDI), or Single Document Interface (SDI).

Each style presents an application to the user in a different way. MDI applications have been
thought of as “proper” Windows style. However, SDI applications are becoming more popular —
Delphi is an excellent example.

In this first part of a two-part series, we’ll focus on MDI application design. Specifically, we’ll discuss:
learning the basics of setting up an MDI application, designing code to control MDI applications,
learning about MDI-related properties and methods, and developing an example MDI application.

Creating MDI Applications


Delphi allows you to create Windows applications that support the
MDI standard. Examples of MDI applications are Windows Program
Manager, File Manager, Microsoft Word, and most Windows text
editors that support loading multiple files simultaneously.

MDI-compliant applications have an MDI parent window with a


client area that displays one or more MDI child windows (or chil-
dren). MDI child windows are confined to the client area, meaning
that child windows can’t extend outside the parent window’s border.

MDI child windows can be minimized, maximized, or sized to fit


anywhere within the client area. Typical MDI capabilities include
tiling and cascading MDI child windows, as well as arranging the
icons of minimized child windows. The MDI parent window con-
tains the application’s master menu, used to manipulate the MDI
child windows. The child windows do not have menus.

Setting Up MDI Parent and Child Forms


MDI applications consist of two or more forms. A single-form MDI
application is contradictory and should be developed as an SDI appli-
cation. All MDI applications must have a parent window with at least
a single MDI child window. To implement this relationship in
Delphi, you need to manage at least two form files in your project.

AUGUST 1995 Delphi INFORMANT ▲ 9


On The Cover

The easiest way to create an MDI application is to use Delphi’s


own MDI Application project template. To better understand the
process, however, we’ll go through the steps of building an MDI
project from the ground up. A project is a collection of related
forms and units that work together to make up an application.

Start with a new project by selecting File | New Project from the
menu. If you have the Gallery option on for new projects, you’re
prompted with the Browse Gallery dialog box shown in Figure 1.
If the Browse Gallery dialog box appears, select the Blank project
template and press the OK button.

Make the default form an MDI parent form by setting its


FormStyle property to fsMDIForm. (We’ll discuss this more
Figure 1: The Browse Gallery dialog box for projects is displayed when
below.) Name the MDI parent form frmMDIParent. the Gallery: Use on New Project option has been selected at the
Environment Options dialog box. The MDI Application template sup-
Add another form to the project (it will be used for MDI chil- plied with Delphi will get you off to a great start.
dren) by selecting File | New Form. This causes a new form and
unit to be added to your project. If you have the Gallery option
Figure 2: The
on for new forms, you are again prompted with the Browse Delphi Project
Gallery dialog box — this time for form templates. Select the Manager. A project
Blank form template and click the OK button. can contain many
forms, but only two
types are needed
Using the Object Inspector, set its FormStyle property to
for an MDI
fsMDIChild, name it frmMDIChild and give it a caption, such as application.
“Child”. The name is used as the basis for the form’s class name, and
the caption is the text that’s placed in the title bar. (Tip: Giving your
form objects, and unit and project files meaningful names makes
them easier to work with and document.) Window option on the Window menu is necessary so he can
calculate his bonus multiple times, receiving a bonus check for
Once this is done, a new unit appears in the Project Manager. Bring each additional window he creates. After failing to persuade Bob
the Project Manager on-screen by selecting View | Project that this is not the most ethical way to increase one’s compensa-
Manager. Figure 2 shows the Project Manager window with two tion, you reluctantly agree to implement Bob’s new feature.
form types defined. Note the term form types. In MDI terms, a
form’s type indicates whether it is an MDI parent — fsMDIParent, You determine that you’ll simply add a new menu choice to the
or child — fsMDIChild. system, enabling the creation of a new MDI child window by
creating another instance (instantiation) of the child window
At run-time, multiple instances of these new form classes can form. You can create this menu by dropping a menu component
be created and are limited only by system resources. The term on the Parent form. Then right-click on the component, select
classes is used here, since when adding a new form to a project, Menu Designer, and define the menu (see Figure 3).
we are essentially sub-classing the basic form class, TForm.
This is shown by this code from a unit’s type declaration: To complete the task, modify the OnClick procedure for the
Window | New Window menu choice (by double-clicking on
type
TfrmChild = class(TForm) OnClick on the Events page of the Object Inspector, as shown in
... Figure 4). Here’s the modified procedure:
procedure TfrmMDIParent.menuNewClick(Sender: TObject);
Referencing MDI Child Windows var
There are many properties and methods that enable you to control frmChildTemp: TfrmMDIChild;
MDI child windows within your application. The following exam- begin
{ Create a new instance of the MDI child window form }
ple of an imaginary company illustrates several techniques for con- frmChildTemp := TfrmMDIChild.Create(Self);
trolling MDI child windows. end;

Suppose you have a user request from Bob, the head of the In this procedure, the var statement declares a form object
human resource department at a company called XYZ. Bob has named frmChildTemp that is of the TfrmMDIChild class (the
just requested that a function be added to XYZ’s Bonus class created when the MDI child form was added to our pro-
Calculation system to enable creation of additional bonus calcu- ject). This is also the same syntax by which new variables are
lation windows within the application. Bob explains that a New defined. The object type TfrmMDIChild is available from the

AUGUST 1995 Delphi INFORMANT ▲ 10


On The Cover

Figure 5: The results of the first try at creating child windows.

time. This is because these properties aren’t applicable during


form design. The read- and run-time properties are:
• MDIChildCount: An integer value containing the number of
currently open MDI child windows.
• ActiveMDIChild: A value of TForm type that can be used as a
handle to manipulate the active MDI child window.
• MDIChildren: An integer-indexed array of TForm containing
MDI child window handles in the order the child windows
were created.

As discussed earlier, two types of forms are required in MDI


applications — one for the parent form and another for the child
form. We have already discussed how to set a form to become an
MDI parent window. Likewise, MDI child windows must have
their FormStyle property set to fsMDIChild.
Figure 3 (Top): Creating the menu for our example application.
Figure 4 (Bottom): Modifying the OnClick procedure for the Window All MDI applications consist of a parent form having a
| New Window menu item. FormStyle property value of fsMDIForm that identifies the
parent MDI form. The parent MDI form must also be refer-
MDI child unit that you added to the project earlier. Attached to enced in the application’s CreateForm method, which Delphi
the child unit is a form named frmMDIChild, containing the handles automatically. The FormStyle property is set at design-
definition for the TfrmMDIChild class. time in most cases, but it can also be set at run-time.

Now Bob can create new child windows at will (see Figure 5). Changing a child window’s FormStyle property from
This example highlights how child windows (which are essential- fsMDIChild to fsNormal enables that window to be brought
ly objects) are created by using a handle of the same object type outside the parent MDI window, as it’s no longer a child win-
as that of the actual window’s class. Additional properties and dow. This can also be done at design- or run-time.
methods can be used to control MDI applications. We’ll discuss
these properties as well as creating new MDI child windows. The Visible property determines whether a visual object is
shown or hidden at run-time. Typically, MDI parent forms
Useful Properties for MDI Window Management are not hidden. It’s also somewhat odd to consider hiding
The highest window class, TForm, includes a number of proper- child forms, and probably the reason this is simply not
ties that support MDI parent and child windows. You can use allowed in a Delphi MDI application.
these properties to affect the behavior of all child forms in your
MDI application. Since forms are used as the basis of the user Incorporating MDI Window Methods
interface, changing overall form-handling properties often has a Now we’ll turn our attention to the additional methods of the
major effect on interface functionality. TForm class that work with MDI windows. Along with the
Create method used in our previous example, there are a
A number of MDI parent window properties that are read- and number of other methods that are useful when assembling
run-time only are not available in the Object Inspector at design MDI applications. MDI methods are recognized only by

AUGUST 1995 Delphi INFORMANT ▲ 11


On The Cover

MDI parent windows (those with a FormStyle property value


of fsMDIForm).

To implement Bob’s outlandish request, we had to dynamically


create MDI child windows at run-time whenever the Window |
New Window menu choice is selected. The following procedure
is identical except that the MDIChildCount property is being
used to increment the child windows’ captions:

procedure TfrmMDIParent.menuNewClick(Sender: TObject);


var
frmChildTemp: TfrmMDIChild;
begin
frmChildTemp := TfrmMDIChild.Create(Self);
frmChildTemp.Caption := IntToStr(MDIChildCount);
end;

Figure 6 shows an MDI parent form after Window | New


Window has been selected four times. Note that the child win-
dows now have different captions.

Arranging Icons
The ArrangeIcons method organizes the icons of minimized MDI
child windows so they’re evenly spaced along the bottom of the
parent MDI window. The ArrangeIcons method must be sent
only to MDI parent windows (again, those having a FormStyle
property value of fsMDIForm).

The ArrangeIcons method is typically linked to your MDI applica-


tion’s Arrange Icons command on the Window menu (if you have
one, otherwise you’re probably not implementing a true MDI-com-
pliant application). Here is an example of the ArrangeIcons method: Figure 6 (Top): Now the child windows have unique titles based on
the MDIChildCount property. Figure 7 (Bottom): The result of the
procedure TfrmMDIParent.menuArrangeIconsClick(
ArrangeIcons method.
Sender: TObject);
begin totypes that can contain code that you can reuse. After reading
TfrmMDIParent.ArrangeIcons;
end;
this article, you will be able to modify and tailor an MDI appli-
cation template to your specific needs.
Alternatively, you can abbreviate the ArrangeIcons statement by
using a more object-oriented syntax: Cascading MDI Windows
The Cascade method arranges the child windows so they overlap
procedure TfrmMDIParent.menuArrangeIconsClick( each other. A cascaded set of windows shows title bars of as
Sender: TObject);
begin
many windows that fit on-screen, allowing the user to easily
ArrangeIcons; choose an available MDI child window.
end;
Here’s an example of how the Cascade method is used:
Abbreviations of this type apply to all MDI methods as well as
for all properties belonging to the procedure class. procedure TfrmMDIParent.menuCascadeClick(Sender: TObject);
begin
Cascade;
Add this code to your form and then create and minimize some end;
MDI child windows. Then, shuffle their arrangement on the MDI
parent window. Selecting Window | Arrange Icons causes the When MDI child windows are first created (e.g. using Window
MDI child window icons to be arranged as shown in Figure 7. | New Window), they are placed in a cascaded arrangement
within the parent (refer to Figures 5 and 6).
You may wonder why you have to bother issuing an ArrangeIcons
method, since virtually all MDI applications provide support for Closing the Current Child Window
arranging icons, tiling, and cascading their child windows. There Most of the work required to close child windows has been
is indeed an easier way that involves using an application done for you by Delphi. There’s only one modification you
template. Delphi’s application templates are simply prebuilt pro- need to make to have the MDI children close as you would

AUGUST 1995 Delphi INFORMANT ▲ 12


On The Cover

expect them to when C4 is pressed. You need to modify


the child form’s OnClose method so that it responds appropri-
ately to the Close event:

procedure TMDIChild.FormClose(Sender: TObject;


var Action: TCloseAction);
begin
Action := caFree;
end;

As you can see, the OnClose procedure takes a parameter


named Action. The value of Action determines how the proce-
dure will respond to the Close event. We want the window to
close, so we assign the caFree constant to Action. (For more
information, see “caFree” or “TCloseEvent Type” in Delphi
on-line help.)
Figure 8: The result of the Tile method.
You can also add an explicit menu choice to close child win-
dows (that is, a File | Close menu option) using the Close procedure TfrmMDIParent.TileMenuClick(Sender: TObject);
begin
method. To do so, you need to add a menu item and then mod- Tile;
ify its OnClick procedure: end;

procedure TfrmMDIParent.menuFileCloseClick(Sender:
TObject); Conclusion
begin Of course, now that you have all this information, you have all the
if ActiveMDIChild <> nil then
license needed to create interesting and unique Delphi applications
ActiveMDIChild.Close;
end; — right? Not entirely. Keep in mind that your Windows users will
expect consistency between applications. And with the impending
This code checks the ActiveMDIChild property to make sure release of Windows 95, there will be a greater call to provide the
that there is a child window to close. If there isn’t, issuing the user with uniform application interfaces. This does not mean that
Close method will cause a General Protection Fault. an MDI-compliant application will always be best. Perhaps an SDI
implementation would be better suited to your user’s needs.
Next and Previous
The Next method makes the next MDI child window in the Fortunately, Delphi makes it simple to create and maintain
MDI parent window sequence the active MDI child form. The either interface. The freedom you have to use built-in templates
Next method treats the MDI child windows as a circular list. or create custom templates is provided by Delphi. All you have
For example, if you send the Next method to the MDI parent to do is concentrate on the user and the application-specific
window and the currently selected MDI child window is the logic. (In fact, it’s important to note that an excellent model for
last MDI child window out of at least two, the Next method a robust MDI application is available in the form of the MDI
causes the first MDI child window in the list to be made active. Application project template provided with Delphi. You should
definitely study it before creating your own MDI applications.)
The following illustrates use of the Next method:
Next month we’ll discuss an interface style that is growing in
procedure TfrmMDIParent.menuNextClick(Sender: TObject); popularity, the Single Document Interface (SDI). We'll compare
begin
SDI and MDI and build a simple SDI application.
Next;
end;
This article was adapted from material for Using Delphi: Special
The Previous method behaves similarly to the Next method. Edition (Que, 1995) by Jon Matcho, David Faulkner, et al. ∆
However, Previous selects child windows in the opposite direc-
tion. Like the Next method, the Previous method also treats the The demonstration project referenced in this article is available
list of MDI child windows as a circular list. If the Previous on the 1995 Delphi Informant Works CD located in
method is issued when the first MDI child is active, the last INFORM\95\AUG\JM9508.
MDI child becomes active.
Jon Matcho has been building business systems since 1987. Since
Tiling MDI Children then, Jon founded Brickhouse Data Systems, Inc., an East Coast con-
The Tile method sizes the MDI child windows so they don’t over- sulting firm specializing in software development. In 1993 he joined
lap each other. The client area of the MDI parent window is Professional Computer Solutions, Inc. to assist in the delivery of mis-
divided into different regions, each with an MDI child window sion-critical database solutions. You can reach Jon at (908) 704-
7300, or on CompuServe at 71760,2720.
contained (see Figure 8). This code example uses the Tile method:

AUGUST 1995 Delphi INFORMANT ▲ 13


On the Cover
Delphi / Object Pascal / Windows Help

By Robert Palomo

A Topical Search
Integrating On-Line Help in Delphi Applications

or many people, their first encounter with the term hypertext conjures up

F images of something out of Star Trek. As often happens however, reality


is rather mundane as we’ll see when we take a peek inside the technolo-
gy behind hypertext. Ordinary or not, a well-designed hypertext-based help sys-
tem can be a highly utilitarian, even “sexy” component of an application that
adds a great deal of value to your software.

Software companies are now supplying more of their product’s documentation in an electronic for-
mat. They do this because the cost of printing and shipping books takes a bite out of their bottom
line. On the other hand, software users are often unwilling to relinquish the comforting security of
a hefty volume or two (or six). Indeed, sometimes a printed manual is vital. For example, if your
system has just crashed, an on-line system administrator’s guide would be pretty useless.

The popularity of CD-ROM based multimedia titles — such as Microsoft’s Encarta encyclopedia
— is doing much to encourage acceptance of the computer screen as a preferred medium for read-
ing and gleaning information. CD-ROM enables software companies to distribute the entire con-
tents of their printed manual sets on disk, as Borland does with Delphi.

On-line documentation solutions range from entire printed manuals “dumped” into a format for
“viewer” software (that displays text in a linear fashion similar to a book), to custom-designed hyper-
text help systems. This article focuses on the latter, since Delphi provides devel-
opers with some nicely encapsulated means of integrating this type of help in
their applications.

Authoring vs. Integration


Developing on-line help for Windows applications involves two fundamental
processes: creating, or authoring the help file, and integrating help with com-
ponents of the application. Authoring on-line help files provides the subject
matter for entire articles, books, and seminars. We’ll look at the process only
as it relates to integrating help into a Delphi application.

Authoring on-line help essentially involves writing text, dividing it into discrete
topics, formatting it to create hypertext links, creating graphics, and configuring
display elements such as secondary windows and menus. A help file is a self-con-
tained Windows application that users can run from Windows independently of
any other application. (For example, you can double-click on a .HLP file in the
Windows File Manager to run it.) However, that’s not always enough to meet
the needs of end-users, as we’ll see later.

AUGUST 1995 Delphi INFORMANT ▲ 14


On The Cover

Let’s begin by taking a quick look at


some of the basic things you, as an Menu bar
Button bar
application developer, should under-
stand about Windows on-line help. Nonscrolling
region
We’ll then examine how Delphi
makes it easy to integrate help into
your applications.

What’s So Hyper about


Hypertext? Hypertext
At the risk of over-simplifying, a jumps
hypertext system is essentially just a Scrolling
region
database application. The data are
“chunks” of text and/or graphics Hypergraphics
called topics. Each topic is identified
by a unique alphanumeric key called
a context string. The Windows help Figure 1: The
Delphi Help
compiler creates a B-tree type index Contents
of these context strings, enabling the page has
WinHelp engine (WINHELP.EXE) several hyper-
to rapidly locate and display any text jumps.
topic in the compiled help file.
expecting to see help for the active user interface (UI) element or
A hypertext system is really no different from a typical customer process that has proved baffling. If nothing happens, or if the
database where the customer file is indexed on a CustNo field user is simply booted into the help file’s Contents topic, your
containing a unique value identifying one customer record. For client will definitely be disappointed. Even though your on-line
example, searching the index for “ABCCORP” accesses the help system is fully hypertext-based, it’s not context-sensitive.
record for the customer “ABC Corporation”. Similarly, you could
have a topic titled “Using the Widget Control” in a compiled Briefly, context-sensitivity is an application’s ability to display a
help file. When the topic was created in the help source file, let’s specific topic from a Windows help file at a given point during
assume it was assigned the context string UsingWidget. When the run-time. We’ll focus on the mechanisms that Delphi provides to
help compiler compiles the source files (text and graphics) into enable you to “hook” the various components in a Delphi appli-
binary format, it creates an index of the context strings defined cation to specific topics in a Windows help file.
in the source file(s). Within the help source files, the help author
creates and formats text strings that point to a particular context Before discussing the specific techniques, however, there’s one
string. When the user clicks on that text in the compiled help technical pitfall inherent to the current state of Windows help
file, the help Engine (WINHELP.EXE) looks up the Context ID development that you must understand so you can avoid it.
value in the index and “jumps” to the topic identified by this
“key field” value — the context string. Understanding the Data Type Trap
The Windows application programming interface (API) provides
What Is Context-Sensitivity? developers with the means to integrate context-sensitive help in
The typical help file has a Contents topic similar to a book’s table Windows applications. To accomplish this, the programmer pro-
of contents. This screen summarizes the main subject areas in the vides a “hook” in the code that equates to the context string of a
help file and provides jumps to the principal topic screen (see specific topic in a help file when that code executes.
Figure 1). These topic screens may in turn contain jumps to other
related topics. (Note that topics can be formatted to display in the It’s a simple concept, but not so simple in practice. You go
main help window as a secondary help or a popup window.) through a lot of gyrations to get values into the right variables of
the correct data type: issue a call to the Windows API, start up
If your users will be content to begin with the Contents screen WinHelp, pass it the ID for the topic, and finally access and dis-
and muddle around in the help file from there, your life as a play the topic specified by the hook in the source code.
developer is easy. You simply develop your application, author a
help file, and provide an icon to run the help file from the That’s the bad news. The good news is that Delphi makes this
Windows Program Manager. process easy by providing components, properties, and methods
that encapsulate this otherwise aggravating bit of coding.
Chances are that will not be the case. At some point a user won’t
understand what is happening, and your job will become more If you have experience with WinHelp and the Windows API,
interesting. Experienced Windows users tend to press 1 you’re probably familiar with an interesting little glitch in the

AUGUST 1995 Delphi INFORMANT ▲ 15


On The Cover

communication between these entities. Delphi requires you


to specify the help “hook” as an integer value in the
HelpContext property of visual components. That’s because
the Windows API requires numeric values for the help
Context IDs in a Windows application. Delphi dutifully
delivers these values as required.

Now here’s a good one: the WinHelp engine requires alphanu-


meric context strings to locate the topics in a help file’s Topic
index. In other words, you can’t just pass the Context ID from
your application through the Windows API to WinHelp. (I
know what you’re thinking, and yes, the same company did
develop both systems. Go figure.)

This means if you have a context string UsingWidget in the help


file, there’s no direct way to call it from a Windows application.
For example, if you specify 110 as the help Context ID in the
HelpContext property for your Form1.Widget1 component, that
value is delivered to the API as a numeric data type.

However, if you specify “110” as the context string for the


“Using the Widget Control” topic in the help source file, it will
be delivered to WinHelp as a character value. Delphi provides a
handy way around this little problem with the HelpJump and
HelpContext methods (which we’ll look at a bit later). These
methods are fine for use in event handlers, but to provide con-
text-sensitive access to help topics using 1 you need to coordi-
nate your Context IDs in the help project file.

The Help Project File


The WinHelp compiler begins its work with the help project
(.HPJ) file. This is basically just an .INI file. It has different sec- Figure 2 (Top): A sample .HPJ file. Figure 3 (Bottom): Using an
tions, each identified by bracketed keywords (e.g. [CONFIG]). included .TXT file to integrate Context IDs with the .HPJ file.
Figure 2 shows an example of a simple .HPJ file. The [MAP] sec-
tion of the .HPJ file is where the numeric help Context IDs and the user presses 1, nothing happens. This is great, because
from your Delphi application are equated to their alphanumeric if there are components that you don’t want or need to provide
context strings in the help file. context-sensitive help, you don’t have to do anything. Just leave
the default zero value in the HelpContext property.
If your only connection with the help authoring process is to
supply the numeric Context ID values from your application By entering a positive, non-zero value in the HelpContext proper-
components to a help author, you have a cushy job and should ty, you set up the means for accessing a topic in the help file
try to hang onto it. You only need to coordinate with the help (which for now, we’ll assume already exists). The value need not
author (who handles the production of the help file) to get the be unique within your application. For example, the OK buttons
two sets of IDs in sync in the [MAP] section of the help project in five different dialog boxes might all have the same value in the
(.HPJ) file. You don’t even need to touch the .HPJ file. (In fact, HelpContext property because you want the same help topic to
some help authors would do you grievous bodily harm for even display for all the buttons.
thinking about it.) Instead, you can create a separate text file
containing the [MAP] section that the help author can reference It’s important to understand that specifying a Context ID in the
with an include statement in the .HPJ file (see Figure 3). HelpContext property is only one step in the process of imple-
menting context-sensitivity. You must still coordinate these IDs
Hooking Delphi Components to Help Topics with the help authoring process as discussed earlier.
Let’s turn our attention to integrating context-sensitivity in a
Delphi application. Delphi’s architects have thoughtfully provid- Planning a HelpContext ID Scheme
ed the HelpContext property for every visual component that can You will probably want to devise some logical scheme for the
receive focus, specifically for integrating context-sensitive help. values of the HelpContext property for your application’s compo-
The default value for this property is zero. At run-time, if a com- nents. The organization is up to you, but it should be part of
ponent has a zero value in the HelpContext property, has focus, your application design.

AUGUST 1995 Delphi INFORMANT ▲ 16


On The Cover

Depending on the scope of your application, you might TApplication has three methods that pertain to the display of on-
define different ranges of values and the parts of the applica- line help: HelpCommand, HelpContext, and HelpJump. If you
tion. For example, one range might be reserved for an entire have experience in other environments working with WinHelp,
module, and sub-ranges defined for component windows of then you may prefer the HelpCommand method for invoking and
those modules. Or, in a small application, you might have controlling help from a Delphi application. This method provides
one range for each form or dialog box, or one reserved only a quick hook-up from the Delphi environment to any of the
for menus, and so forth. WinHelp command macros.

As you plan the ranges, make them large enough so that during Besides accessing topics in context, you can control properties of
initial development each component’s HelpContext ID incre- the help window — such as size, color, or position — and dis-
ments by five. For example, for three button components on a play topics in secondary windows. HelpCommand is well docu-
form, you would set the HelpContext properties as 100, 105, and mented in the Delphi on-line help system, and you should be
110 respectively (instead of 100, 101, and 102). This leaves able to learn and use it quickly.
room in the range for additional components without having to
make major modifications to the [MAP] section of the .HPJ file. If you want to access a specific help topic with code, then you’ll
appreciate the simplicity of the HelpContext and HelpJump meth-
Properties and Methods for Accessing Windows Help ods. These provide the same result: the display of a specific topic
Delphi provides properties and methods that enable you to in the help file. The difference is in how you specify the Context
access specific topics in a help file, or in different help files. In ID for the help topic you want to access.
this section, we’ll summarize these and take a look at some cre-
ative ways you might use them. An application developer will tend to approach context-sensitivity
from the standpoint of the application user-interface. You know
Delphi’s TApplication component encapsulates the functionality what components are in a specific dialog box or window, and you
needed to access WinHelp via the Windows API. The WinProcs know (or can easily look up) the numeric Context ID in the Object
unit contains methods for accessing specific help topics in a Inspector. Therefore, you would know the Widget component in
given help file. the Foo dialog box has a Context ID of 110 in its HelpContext
property. You may not know (nor care) that the help file topic asso-
Before your application can display help, you must specify a help ciated with it is “Using the Widget Component” with a context
file for it. The HelpFile property of TApplication specifies the string of UsingWidget. You simply want to display whatever topic is
name of the help file that the various help access methods will in the help file for the Widget component when it has the focus and
look at. You normally specify the name of this file by selecting the user presses 1.
Options | Project and choosing the Application page of the
Project Options dialog box (see Figure 4). If you want to display this topic in response to another event,
simply call the HelpContext method in your event handler:
You can also set or change the designated help file at run-time
with an assignment: Application.HelpContext(110);

Application.HelpFile := 'helpfile.hlp'; Help authors tend to approach context-sensitivity from the


standpoint of the help source file. They may not even know how
If you don’t specify a help file either at design time in Project to run Delphi, much less deal with the values of the HelpContext
Options or at run-time in code, the application will not display property of components. They may know only that the topic
help at run-time. Without a help file specified, it doesn’t matter “Using the Widget Control” has a context string UsingWidget in
that you may have assigned Context IDs in the HelpContext the help source document, and this is the value they can supply
property of components, or that a .HLP file exists. to you, the application developer. Not a problem — you can
display the same help topic with a call to HelpJump:
Application.HelpJump('UsingWidget');

Remember, you need to use these methods only if you want to


Figure 4: invoke a specific help topic in response to some event other than
The the user pressing 1. 1 context-sensitivity is already built into
Application all components having a HelpContext property. You need only
page of the specify a non-zero Context ID value in that property, and map the
Project
value appropriately in the help project file as we discussed earlier.
Options
dialog box.
Some Practical Techniques
Let’s look at a practical application you might develop using these
methods. This is a module for a Human Resources system that

AUGUST 1995 Delphi INFORMANT ▲ 17


On The Cover

• BENEFITS.HLP — Information on all other employee benefits.


• POLICIES.HLP — Information on general employment poli-
More Information about cies and regulations.
Help Authoring • HRINFO.HLP — Help file for the information application
itself.
To create a Windows help file, you need: a word processor
capable of saving files as Rich Text Format (.RTF) files; a You could certainly combine the source documents for these files
Windows help compiler (HCP.EXE); a hotspot editor for and compile a single Windows help file for the module.
creating hypergraphics (SHED.EXE); and a paint program However, let’s assume there’s a reason to keep them separate to
that can create .BMP files. The help compiler and Hotspot illustrate some techniques you can use in Delphi to change the
Editor both ship with both versions of Delphi. Also avail- TApplication component’s HelpFile property. You also want to
able with Delphi is CWH.HLP, an on-line help-authoring keep them separate to address specific topics in the various .HLP
guide. This file resides in the \DELPHI\BIN directory in a files at different times, depending upon what’s happening in the
default Delphi installation. Another good resource is the
application UI.
Microsoft Help Authors Forum on CompuServe.

I can also recommend Developing On-Line Help for At design time, we’ll specify HRINFO.HLP as the application
Windows by Scott Boggan, David Farkas, and Joe Welinske help file. We’ll create a UI that will switch the help file as need-
(SAMS). This book will take you from neophyte to consul- ed. Then, we’ll create a main form for the application called
tant-level expertise in Windows help development. It’s well- MAINFRM.PAS, as shown in Figure 5.
organized and indexed, very readable, and covers all the
issues. It includes a disk containing Word templates and
macros optimized for creating Windows help source files,
example help projects, help project file templates, and
bitmap graphics you can use in your own projects. It also
presents a comprehensive review and comparison of several
third-party help authoring tools.

Third-Party Tools
Windows Help Authoring Utility
(on the Microsoft Developer Network CD)
Microsoft Corp.
1 Microsoft Way
Redmond, WA 98052
(206) 882-8080 Figure 5: The Human Resources sample application.

RoboHelp
Blue Sky Software Corp. This form has five BitBtn components labeled Insurance,
7486 La Jolla Boulevard, Suite 3 Benefits, Policies, Help, and Close. The event code behind the
La Jolla, CA 92037
(619) 459-6365
first four buttons hides the main window, displays a button bar,
and executes the OnClick event of the appropriate Speedbutton
Doc-To-Help component on the button bar:
WexTech Systems, Inc.
310 Madison Avenue, Suite 905 procedure TMainWin.BBtnInsuranceClick(Sender: TObject);
New York, NY 10017 begin
(212) 949-9595 MainWin.Hide;
BtnBarWin.Show;
Help Magician BtnBarWin.SBInsuranceClick(Sender);
Software Interphase, Inc. end;
82 Cucumber Hill Road
Foster, RI 02825-1212
(800) 542-2742
Each of the BitBtn components has a similar OnClick event handler.
(401) 397-2340
On the button bar, each Speedbutton sets the current help file
and displays its Contents screen:
procedure TBtnBarWin.SBInsuranceClick(Sender: TObject);
provides information and answers to employee questions on-line. { User has selected Insurance button in main screen }
The information is contained in several Windows help files. The begin
{ Display Speedbutton in down state }
text of these files are maintained by different people in the HR SBInsurance.Down := True;
department. There is also a help file for the module itself. { Set current Help file }
Application.HelpFile := 'INSURE.HLP';
{ Access Help file Contents }
The help files are as follows: Application.HelpCommand(HELP_CONTENTS, 0);
• INSURE.HLP — Information on medical, dental, and life PnlInsurance.visible := True;{ Display button panel }
insurance plans. end;

AUGUST 1995 Delphi INFORMANT ▲ 18


On The Cover

The Windows Help button on the main form switches the active
help file back to the design time default, HRINFO.HLP:

procedure TMainWin.BBtnMainHelpClick(Sender: TObject);


begin
Application.HelpFile := 'HRINFO.HLP';
Application.HelpCommand(HELP_CONTENTS,0);
end;

The main three BitBtn components are context-sensitive.


Pressing 1 while any of them have focus invokes a specific
topic in the application’s help file. This file (HRINFO.HLP)
is set as the active help file whenever the main form’s
Figure 6: OnActivate event occurs.
The example
help system Conclusion
in action.
Developing a well-planned on-line help system with context-
sensitivity can provide an extra measure of value to the soft-
ware you develop with Delphi. Delphi provides you with
Each Speedbutton event handler specifies a different help file. The some handy short-cuts that reduce the somewhat convoluted
help window is sized in the .HPJ file’s [WINDOWS] section to allow integration process for context-sensitivity to a simple property
the button bar to display beside it (see Figure 6). setting. And as we saw in the example application, Delphi
enables developers to experiment with Windows help in some
The Insurance button displays a panel on the button bar with interesting and out-of-the-ordinary ways. ∆
several speedbuttons that access a specific topic in the help file
using the HelpJump method. For example, the Med button code
looks like this: The demonstration application referenced in this article is available
procedure TBtnBarWin.SBMedInsClick(Sender: TObject); on the 1995 Delphi Informant Works CD located in
begin INFORM\95\AUG\RP9508.
Application.HelpJump('MEDICALPLAN');
end;

The Insurance, Benefits, and Policy buttons on the button bar have Robert Palomo has been a technical writer in the software industry in Seattle, WA and
their GroupIndex property set to a value of 1, and the AllowAllUp Silicon Valley, CA for the past five years. His most recent job was as a member of the
property set to False. This eliminates the need to test for the value of Delphi documentation group at Borland International. The extensive staffing cutbacks
the button’s Down property. You simply set the Down property of at Borland gave him enough free time after Delphi shipped to set up shop part-time as
the selected button to True, and the others with the same a consultant specializing in integrating context-sensitive help in Delphi and other
Windows applications. Robert also does Delphi application development work. You can
GroupIndex property display in the “up” state. (You could achieve contact him on CompuServe at 76201,3177 or on the Internet at
the same effect with a RadioButton group, but this technique [email protected].
enables you to use glyphs on the buttons for a more elegant UI.)

AUGUST 1995 Delphi INFORMANT ▲ 19


On the Cover
Delphi / Object Pascal

By Douglas Horn

Initialization Rites
Using Windows .INI Files in Delphi

early every commercial Windows application employs an .INI file. Even

N a glance at the \Windows directory of most PC’s will show how widely
they’re used — and some programs use several.

Unfortunately, .INI files are underutilized by most application developers. This is despite the fact
that they’re extremely useful for storing information that must be saved between program sessions.

Delphi makes it particularly easy to implement an .INI file with an application. This article will
introduce .INI files and explain their use with Delphi.

What Are .INI Files?


INI files are named for their common three-letter file extension, an abbreviation for initialization.
They’re used to store configuration parameters, user preferences, program status, and other infor-
mation that should persist from one execution of an application to the next.

Two of the best-known .INI files are WIN.INI and SYSTEM.INI. Both of these files are used to
store important parameters for the Windows operating system. While most Windows applications
use an .INI file named for the executable (e.g. DELPHI.INI), many use the WIN.INI file instead
of, or in addition to, their own file.

.INI files are simple text files (see Figure 1). Each .INI file is divided into
sections, easily recognizable by a section title enclosed in brackets (e.g.
[Boot]). Within each section are a number of statements. Each statement
begins with a variable or identifier, followed by its value (e.g.
spooler=True). .INI files are not case-sensitive.

How Delphi Handles .INI Files


Delphi interacts with .INI files using its TIniFile object. The TIniFile object
has 16 methods, about half of which programmers will use regularly in
implementing .INI files (see Figure 2). The first task when using .INI files
in Delphi applications is to add the IniFiles statement to the uses clause of
the program unit that will call the .INI file:

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

AUGUST 1995 Delphi INFORMANT ▲ 20


On The Cover

When it’s no longer necessary to access the .INI file, the Free
method is used to release the .INI file, destroy the TIniFiles
object, and free the resources reserved for the object:

...
AppIni.Free;
end;

These minor preliminaries are necessary whenever TIniFiles are


used. Between the Create and Free methods, however, lie a large
number of possibilities.

Reading, Writing, and ’Rithmetic


The real workhorses of the TIniFile methods are the “reads” and
the “writes”. The three write methods are WriteBool, WriteInteger,
and WriteString. These methods are similar; the only factor that
differentiates them is the type of value each handles.

Each write method requires three parameters: the section, identi-


fier (or variable), and value. For example, the following state-
Method Description ment would write the string value RIVETS.BMP to the
WallPaper identifier in WIN.INI’s [Desktop] section (assum-
EraseSection Erases a section of an .INI file.
ing a link to WIN.INI was already created). Note that the brack-
FileName The name of the .INI file the TIniFile ets are not used when specifying the section:
object encapsulates.

ReadBool Retrieves a Boolean value from an .INI file. WinIni.WriteString('Desktop','WallPaper','RIVETS.BMP');

ReadInteger Retrieves an Integer value from an .INI file.


Of course the value may be literal, as above, or can be derived
ReadSection Reads all variables of a section into a from a property just as any other value in Delphi. The following
string.
line would then set an .INI file property to the corresponding
ReadSectionValues Reads all variables and their values of a program property’s current state:
section into a string.

ReadString Retrieves a string value from an .INI file. AppIni.WriteBool('Settings','ShowButton',Button1.Visible);

WriteBool Writes a Boolean value to an .INI file.


The read methods are ReadBool, ReadInteger, and ReadString
WriteInteger Writes an integer value to an .INI file.
— each corresponding to a write method shown above. The
WriteString Writes a string to an .INI file. syntax is also quite similar between corresponding read and
write methods.
Figure 1 (Top): A section of a typical Windows .INI file.
Figure 2 (Bottom): Key methods of the TIniFile object.
Conversely, while a write method specifies a value, a read method
Once IniFiles is added to the uses clause, the .INI file need only uses a default value that is used in case the target .INI file state-
be declared as a variable and then created. ment is blank (or non-existent). The following two read methods
correspond directly to the write methods previously shown:
The following illustrates the beginning of a typical procedure
Canvas.TextOut(10,10,'Wallpaper Image = ' +
that accesses an .INI file: WinIni.ReadString('Desktop','WallPaper','none'));

procedure TForm1... Button1.Visible :=


var AppIni.ReadBool('Settings','ShowButton',True);
AppIni: TIniFile;
begin
AppIni := TIniFile.Create('APP.INI'); There are two more read methods: ReadSection and
... ReadSectionValues. These methods function somewhat differently
than those already described. Instead of reading a single specified
After the TIniFile handle (AppIni) is declared, the .INI file is value, ReadSection and ReadSectionValues read an entire .INI file
opened using the TIniFile.Create method, where APP.INI is the section into a TStrings object.
name of the file to be read from or written to. The Create
method opens an existing .INI file if the one specified exists, or The difference between the two methods is demonstrated in
creates a new one if it doesn’t. (Unless a specific path is supplied, Figure 3, where the ListBox component on the left uses the
Delphi will search for APP.INI in the \Windows directory.) ReadSection method, while the one on the right uses

AUGUST 1995 Delphi INFORMANT ▲ 21


On The Cover

(TFormSA.FormCreate) allocates memory to create a TIniFile


object, and passes it the file name of an .INI file. Also upon
opening, the application accesses the SAMPLEAP.INI file and
uses parameters that .INI file contains to reset itself.

The application’s main function is to read all the entries of the


[Desktop] section of the WIN.INI file into a ListBox compo-
nent. Then, the user can select a variable to inspect. If the user
resizes the window at any time, the user-interface objects repo-
sition themselves relative to the application’s new dimensions.

This sample application relies heavily on the most useful form of


.INI file manipulation — simple, single-statement read and
write method calls. While the ReadSection and ReadSectionValues
methods have their merits, they are less useful than the more
straightforward methods. This application uses ReadSection to fill
the ListBox component with the variables in WIN.INI’s
[Desktop] section. However, these methods are rarely useful for
Figure 3: A simple pair of ListBox components illustrates the differ-
ences between the ReadSection and ReadSectionValues methods.
manipulating .INI files. (Again, the EraseSection method is used
even less and should be implemented with caution.)
ReadSectionValues. ReadSection displays only the variables in the
section, and displays them regardless of whether they have val- To view the code section by section, the initial lines of code con-
ues, or are preceded by the REM keyword. On the other hand, sist of the necessary preliminaries. Note the IniFiles reference in
the ReadSectionValues method displays the variable and its value the uses clause. This statement must be added whenever TIniFile
(the complete statement), and ignores blank variables or “REM- methods will be used.
ed out” statements.
The first procedure, FormClose, records all the desired informa-
This Object Pascal code produces the list box contents shown in tion to the SAMPLEAP.INI file. First it declares TheIni as a
Figure 3: TIniFile object, and then creates the link to the application’s
own .INI file, SAMPLEAP.INI. Next, the procedure writes
procedure TForm1.FormActivate(Sender: TObject); information consisting of the form’s size and coordinates, stored
var as integers, and the value of the current variables list (ListBox1)
AppIni: TIniFile;
begin
setting, stored as a string.
AppIni:= TIniFile.Create('WIN.INI');
AppIni.ReadSection('Ports',Listbox1.Items); Note that the information could more easily be stored as an inte-
AppIni.ReadSectionValues('Ports',Listbox2.Items);
AppIni.Free;
ger, using the ItemIndex property. However, using this property,
end; this would only store a position on the list, not an actual vari-
able. In case WIN.INI is changed, the variable setting might not
The final TIniFile method of note is EraseSection. It’s not useful remain the same.
under most circumstances, and in fact, could do a lot of damage
to a system if used improperly. The next procedure, FormCreate, not only accesses
SAMPLEAP.INI but WIN.INI as well, using the same TheIni
Sample Application object. The first operation is to create a link to WIN.INI, and
The sample application that then read the contents of the [Desktop] section into the
accompanies this article (see TStrings object, ListBox1.Items. After this is accomplished, the
Figure 4) shows how to link to WIN.INI is destroyed and TheIni object is linked to the
implement an .INI file that sample application’s own .INI file.
stores a number of program
parameters when it closes. Next, the sample application reads the values stored during
The complete unit file FormClose (using the ReadInteger method), and uses them to set
(INI_APP.PAS) is shown in the form to the size and position it held when it was last closed.
Listing One beginning on Using the similar ReadString method, the procedure resets the
page 24. Let’s take a look at ListBox selection to that recorded in the .INI file.
the code.
Figure 4: The sample application The FormResize procedure is then called to establish the proper size
When the application opens, illustrates a variety of practical and position of the user-interface objects, based on the form dimen-
the Create method ways to use .INI files. sions stored in the .INI file. Because the Object Pascal code exists in

AUGUST 1995 Delphi INFORMANT ▲ 22


On The Cover

the FormCreate procedure (rather than FormActivate), these changes


occur before the form is drawn, and remain invisible to the user.

Button1Click is the last procedure to employ .INI file operations.


When called (when the user clicks the Inspect button) the pro-
cedure creates a link to WIN.INI as above, finds the value of the
entry selected in the list of variables (ListBox1), and displays
the value in the edit box (Edit1).

The two final procedures provide simple housekeeping. FormResize is


called by FormCreate. It’s also called whenever the user changes the
form’s dimensions. This procedure simply resizes and repositions
user-interface objects relative to the form’s size. This is done to give
users a logical reason to resize the form (i.e. to resize the ListBox
depending on the length and number of the [Desktop] variables) so
that new coordinates and dimensions can be stored in the .INI file.

The last procedure, BitBtn1Click, simply closes the sample


application.

Conclusion
I hope this article has helped to demystify Windows .INI files.
These files can be easily implemented, and add an extra level of
user-friendliness and sophistication to any Delphi application.
Although for clarity’s sake, the sample application stores only
simple coordinates and settings, .INI files can be used to store
almost any type of program information.

Next month, we’ll extend the .INI file concept further by com-
bining it with MDI (multiple-document interface) applications
and menus to create a list of most-recently used files (or MRU).
This is an advanced feature that enables users to quickly and eas-
ily pick up where they left off. ∆

The demonstration project referenced in this article is available on


the 1995 Delphi Informant Works CD located in
INFORM\95\AUG\DH9508.

Douglas Horn is a freelance writer and computer consultant in Seattle, WA. He special-
izes in multilingual applications, particularly those using Japanese and other Asian
languages. He can be reached via CompuServe at 71242,2371.

AUGUST 1995 Delphi INFORMANT ▲ 23


On The Cover

Begin Listing One — INI_APP.PAS TheIni := TIniFile.Create('SAMPLEAP.INI');


unit Ini_app; FormSA.Top := TheIni.ReadInteger('Settings',
'Top',0);
interface FormSA.Left := TheIni.ReadInteger('Settings',
'Left',0);
uses FormSA.Height := TheIni.ReadInteger('Settings',
IniFiles, SysUtils, WinTypes, WinProcs, Messages, 'Height',100);
Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, FormSA.Width := TheIni.ReadInteger('Settings',
StdCtrls, Menus, Buttons; 'Width',100);
ListBox1.ItemIndex := ListBox1.Items.IndexOf(
type TheIni.ReadString('Settings','Variable',''));
TFormSA = class(TForm) TheIni.Free;
ListBox1: TListBox;
Label1: TLabel; FormSA.FormResize(FormSA);
Button1: TButton; end;
Edit1: TEdit;
BitBtn1: TBitBtn; procedure TFormSA.Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var
var Action: TCloseAction); TheIni: TIniFile;
procedure FormCreate(Sender: TObject); begin
procedure Button1Click(Sender: TObject); if ListBox1.ItemIndex > -1 then
procedure BitBtn1Click(Sender: TObject); begin
procedure FormResize(Sender: TObject); TheIni := TIniFile.Create('WIN.INI');
Edit1.Text := TheIni.ReadString('Desktop',
private ListBox1.Items[ListBox1.ItemIndex],'');
{ Private declarations } TheIni.Free;
public end;
{ Public declarations } end;
end;
procedure TFormSA.FormResize(Sender: TObject);
var begin
FormSA: TFormSA; if FormSA.Width < 250 then
FormSA.Width := 250;
implementation
if FormSA.Height < 300 then
{ $R *.DFM } FormSA.Height := 300;

procedure TFormSA.FormClose(Sender: TObject; ListBox1.Height := FormSA.ClientHeight - 179;


var Action: TCloseAction); ListBox1.Width := FormSA.ClientWidth - 32;
var Button1.Top := FormSA.ClientHeight - 122;
TheIni: TIniFile; Button1.Left := FormSA.ClientWidth div 2 —
begin Button1.Width div 2;
TheIni := TIniFile.Create('SAMPLEAP.INI'); Edit1.Top := FormSA.ClientHeight - 81;
TheIni.WriteInteger('Settings','Top',FormSA.Top); Edit1.Width := FormSA.ClientWidth - 32;
TheIni.WriteInteger('Settings','Left',FormSA.Left); BitBtn1.Top := FormSA.ClientHeight - 40;
TheIni.WriteInteger('Settings','Height',FormSA.Height); BitBtn1.Left := (FormSA.ClientWidth div 2) —
TheIni.WriteInteger('Settings','Width',FormSA.Width); (BitBtn1.Width div 2);
WriteString('Settings','Variable', end;
ListBox1.Items[ListBox1.ItemIndex]);
TheIni.Free; procedure TFormSA.BitBtn1Click(Sender: TObject);
end; begin
Close;
procedure TFormSA.FormCreate(Sender: TObject); end;
var
TheIni: TIniFile; end.
begin
TheIni := TIniFile.Create('WIN.INI');
TheIni.ReadSection('Desktop',ListBox1.Items);
TheIni.Free; End Listing One

AUGUST 1995 Delphi INFORMANT ▲ 24


OP Basics
Delphi / Object Pascal

By Charles Calvert

Strings: Part I
An Introduction to Object Pascal Strings

trings. You work with them in virtually every application you develop, yet

S there are probably a number of features associated with strings that you
haven’t had a chance to explore.

This first installment of a three-part series on strings will demonstrate that strings are really a
form of array. However, a number of interesting rules specific to strings do not apply to arrays,
and we’ll investigate most of these in detail. In particular, you’ll learn how to search for a sub-
string in a string, and how to parse a lengthy string.

A String Is Just a Form of Array


A string is very similar to, but not identical to, an array of characters. Consider the following
Object Pascal declarations:

type
TNearString = array[0..255] of Char;

var
NearString: TNearString;
MyString: string;

Based on this code fragment, MyString has all the traits of TNearString, plus a few special
qualities. In other words, a Delphi string is a superset of an array of Char that is 256 charac-
ters long. Let’s examine the differences.

All characters in an array of Char are equal; no one character has any special properties. In a
string however, the first character is called a length byte. It designates how many characters
exist in the string. Because the first character has this special task, the first letter in the string is
always at offset one.

It’s important to remember that most Chars can be represented in two ways. For instance, the letter
“A” can be printed verbatim, or it can be represented by the 65th member in certain character sets.
If you want to refer to the letter “A” by its place in a character set, you can enter #65. The # in this
example designates the item in question is a Char and not a simple numerical value. Therefore, the
number five is represented as 5, but the fifth character in a character set is represented by #5.

For example, consider a string containing the word “Hello”. This string is five characters
long, so the first byte in a string containing this word would be set to the fifth character
in a table of characters:

AUGUST 1995 Delphi INFORMANT ▲ 25


OP Basics

NearString[0] := #5;
procedure TForm1.Button1Click(Sender: TObject);
var
The next character in the array would be an “H”: S: string;
begin
NearString[1] := 'H'; { H = #72 } S[0] := #5;
S[1] := 'H';
S[2] := 'e';
The rest of the letters would immediately follow: S[3] := 'l';
S[4] := 'l';
NearString[2] := 'e'; S[5] := 'o';
NearString[3] := 'l'; Edit1.Text := S;
NearString[4] := 'l'; end;
NearString[5] := 'o';
Figure 1: Assuming an Edit component (named Edit1) and Button
The result is an array of six characters that looks like: component (named Button1) exist on a form, this Object Pascal code
compiles and displays Hello in the Edit box.
#5,'H','e','l','l','o'
Clearly, this fragment is easier to write. However, the fact
If you took the whole process to an imaginary “memory that you can write code like this is a special feature of the
theater”, you would see six seats aligned one behind the compiler. What the compiler actually does is shown in
other. The person in the first seat would be told to remem- Figure 1. However, it’s laborious to write all that code each
ber the total number of letters in the word(s) that are part time you want to assign a value to a string. Therefore, the
of the string. The person in the second seat would remem- compiler allows you to write code like the above example.
ber the first letter of the string (in this case it’s an “H”).
The person in the next seat would remember the letter A brief sample program, named EASYSTR.DPR, demon-
“E”, and so on. strates these ideas. Specifically, EASYSTR shows what hap-
pens if you don’t treat a string’s length byte carefully. The
So far so good. But what about the remaining 250 characters form for the EASYSTR program includes two buttons and an
in the string? It doesn’t matter what information is stored in Edit component (see Figure 2). The code for the EASYSTR
those bytes. They can be zeroed out, or hold nothing but program is shown in Listing Two on page 28.
garbage. It doesn’t matter what those bytes hold provided the
first byte is correctly set to the total number of valid charac- The EASYSTR program enables you to display a valid or invalid
ters in the string. string inside an Edit component. The invalid string is flawed
because it has an incorrect length byte. Specifically, it sets the
Let’s say the length byte in the above example was accidental- length byte to 150, although the string you want to print is only
ly set to #6 instead of #5. five characters long.

Then, the letter the person in seat seven is supposed to This simple mistake would cause trouble in your program.
remember would become part of the string — usually with However, so you can clearly see what is going wrong, anoth-
disastrous results. For instance, the string Hello may suddenly er ScrambleString procedure was added to the program.
become any of the following:
• Hello1
• Hellob
• Hello#
• Hello+

In short, the behavior is unpredictable in such situations.

The code in Figure 1 will compile and run without error. It


prints the word Hello inside an Edit component. You can
view this code fragment as the anatomy of a string. It explic-
itly shows the elements that comprise a string. The follow-
ing code behaves identically to the code in Figure 1:

var
S: string;
begin
S := ‘Hello’;
Edit1.Text := S;
end; Figure 2: To create the form for the EASYSTR program, simply drop
two buttons, a panel, and a label onto a form.

AUGUST 1995 Delphi INFORMANT ▲ 26


OP Basics

This ensures all the characters in a string are set to random


values:
procedure ScrambleString(var S: string);
var
i: Integer;
begin
for i := 0 to 255 do
S[i] := Chr(Random(255));
end;

This function sets all the characters in a string to various val-


ues between zero and 255 by using the Random function.
Random returns a number between zero and the value passed
in its sole parameter. However, in this case the goal is not to
produce a random number, but a random character. To
achieve this result, the Chr function is used. Chr is used to
convert a numerical value into a character. Figure 3 (Top): If the length byte of a string is set to the wrong
value, the results can be chaotic. Figure 4 (Bottom): No matter how
Note that there is no significant difference between using the you scramble the extra characters in a string, the result shown to the
Chr function and simply typecasting the value returned from screen is fine provided the length byte is assigned a valid value.
the Random function. For example, this code produces the
same result as using the Chr function: This code prints the word Hello in an orderly fashion. To
do this, it sets the first character of a null-terminated string
S[i] := Char(Random(255));
to the letter “H” and sets the sixth character to the value of
the first member of the currently selected character set.
Figure 3 depicts what may happen if you try writing a string
to an Edit component when the length byte is set to an arbi-
It’s important to remember that you don’t end null-terminat-
trarily large value. Clearly the result is less than optimal.
ed strings with the number zero — use #0. The number zero
Characters are scattered across the component like some kind
is usually the 48th member of a standard character set. It is
of hieroglyphic, and the word Hello is discernible only after
entirely distinct from the first member of that character set.
you closely study the output.
Null-terminated strings are frequently referred to as
You can compare the fiasco in Figure 3 with the orderly
PChars. PChars are pointers to arrays of Char. As a result
results in Figure 4. In this second case, the compiler is passed
you must allocate memory for them before you try to use
a valid length byte and the results are precisely defined and
them. For instance, the following code explicitly allocates
readily understandable.
26 bytes of memory for a PChar before filling it with char-
Null-terminated Strings acters and displaying it on the screen.
Before talking about strings in more depth, we’ll discuss
PChars, null-terminated strings, and the correct way to use an The memory is then deallocated:
array of Char as a string.
procedure TForm1.BCharsClick(Sender: TObject);
var
A null-terminated string has no length byte. Instead, the compil- S: PChar;
er searches for a #0 character and assumes that it marks the end begin
GetMem(S,26);
of a string. StrCopy(S,'Hello');
Edit1.Text := StrPas(S);
Specifically, if you return to the examples shown earlier, FreeMem(S,26);
end;
you can easily modify the functions so they will print a
properly formatted null-terminated string:
When you allocate memory for a pointer, it’s similar to a per-
procedure TForm1.BCharsClick(Sender: TObject); son entering the “memory theater” and telling a specific num-
var ber of people they are part of a string. In this example, for
S: array[0..25] of Char;
begin instance, 26 members of the audience are grouped under the
S[0] := 'H'; aegis of a single PChar.
S[1] := 'e';
S[2] := 'l';
S[3] := 'l'; Devotees of C/C++ will notice Delphi has a function
S[4] := 'o'; called StrCopy that mirrors the job performed by strcpy in
S[5] := #0; the land created by AT&T. That is, StrCopy copies one
Edit1.Text := S;
end; string into another. There are also functions called StrCat,

AUGUST 1995 Delphi INFORMANT ▲ 27


OP Basics

StrPos, StrCmp, and so on, if you need them. The StrPas


Begin Listing Two — EASYSTR function converts a PChar into a string. PChars become
particularly important when you start working with
unit Main;
Windows API functions.
interface
Conclusion
uses
SysUtils, WinTypes, WinProcs, Messages, Classes,
Next month’s article will discuss how to store strings in text
Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; files and retrieve them from text files. The third article will
explore parsing the contents of a text file, and converting the
type
TEasyString = class(TForm)
data into fundamental Delphi types.
Panel1: TPanel;
Label1: TLabel; Next month we’ll also explore some real-world examples of
Valid: TButton;
Bad: TButton;
challenges you might face when working with strings. For
procedure BValidClick(Sender: TObject); example, one classic problem we’ll tackle is the need to strip
procedure BBadClick(Sender: TObject); blanks from the end of a string. See you then. ∆
private
{ Private declarations }
public
{ Public declarations } This article was adapted from material for Charles Calvert’s
end;
book, Delphi Unleashed, published in 1995 by SAMS publishing.
var
EasyString: TEasyString;

implementation
The demonstration program referenced in this article is avail-
able on the 1995 Delphi Informant Works CD located in
{$R *.DFM} INFORM\95\AUG\CC9508.
procedure ScrambleString(var S: String);
var
i: Integer;
begin
for i := 0 to 255 do Charlie Calvert works at Borland International as a Developer Relations Manager for
S[i] := Chr(Random(255));
end; Languages. He is the author of Delphi Programming Unleashed, Teach Yourself
Windows Programming in 21 Days, and Turbo Pascal Programming 101. He lives
procedure TEasyString.BValidClick(Sender: TObject); with his wife, Marjorie Calvert, in Santa Cruz, California.
var
S: string;
begin
ScrambleString(S);
S[0] := #5;
S[1] := 'H';
S[2] := 'e';
S[3] := 'l';
S[4] := 'l';
S[5] := 'o';
Label1.Caption := S;
end;

procedure TEasyString.BBadClick(Sender: TObject);


var
S: string;
begin
ScrambleString(S);
S[0] := #150;
S[1] := 'H';
S[2] := 'e';
S[3] := 'l';
S[4] := 'l';
S[5] := 'o';
Label1.Caption := S;
end;

end.

End Listing Two

AUGUST 1995 Delphi INFORMANT ▲ 28


DBNavigator
Delphi / Object Pascal

By Cary Jensen, Ph.D.

Data Validation: Part I


Validating Your Data in Delphi

very database application needs the ability to validate data. This can be

E as simple as ensuring that the user enters data in all upper-case letters,
or as complex as verifying that an entered value is consistent with data
stored in another table.

This month’s DBNavigator is the first of a two-part series on data validation. Part I introduces
the basic concepts of data validation, and describes how to apply field-level validation to stan-
dard components (i.e. components from the Standard page of the Component Palette not
associated with database tables). In Part II, we’ll look at applying both record-level and field-
level validation to data-aware components (i.e. components from the Data Controls page of
the Component Palette).

Introduction to Data Validation


Record-level validation refers to the application of data-validity rules when a record is being posted
(written) to a table. When the user has finished editing a record, record-level validation code veri-
fies the data is accurate. If the code determines the record is not acceptable, the record should not
be posted to the table.

Field-level validation refers to the validation that takes place when a user enters data into a sin-
gle field. (The term “field” is used here in its database sense. In Delphi a “field” usually takes
the form of an Edit or DBEdit component.) In most cases, the validation process occurs when
the user has completed editing the field, although it can also be applied after each keystroke. If
the data in the field is determined to be unacceptable, the user is informed and won’t be per-
mitted to leave the field.

From the user’s standpoint, record-level validation is more convenient than field-level. Specifically,
when record-level validation is employed, the user can move freely among the records, leaving some
fields only partially complete to move onto other fields. As long as the user completes these partial
fields before attempting to post the data (and has also completed the record correctly), record-level
validation code will accept the record. This process mimics the way a user interacts with a paper form.

On the other hand, field-level validation can be intrusive. A user attempting to leave a field — or
perform another task that will result in the field being posted (such as inserting a new record) —
when the field is not complete is interrupted by the validation code. This interruption may be as
minor as the display of an error message in a status bar, or as significant as the display of a message
in a modal dialog box requiring acknowledgment.

AUGUST 1995 Delphi INFORMANT ▲ 29


DBNavigator

Field Validation with Standard Controls ComboBox component is the one that requires the most adjust-
In Delphi, you will quickly learn that sometimes less program- ment, this example will make use of that component.
ming is better. Specifically, if you can achieve a particular result
using either properties or code, use properties. Sometimes this Begin by creating a new project. (It’s always a good idea to
also means selecting the right component for the job. These rules first create a directory to save the project in.) On your new
certainly apply when it comes to field-level validation. form place a Label and a ComboBox component from the
Standard page of the Component Palette (see Figure 1).
In addition, how you perform field-level validation depends in Change the Label’s Caption property to &Day of Week:, and
part on the type of component you are validating. The compo- its FocusControl property to ComboBox1. (A Label component
nents (or controls) that you place on a form are available in cannot have focus, so the FocusControl property determines
two basic “flavors”: data-aware (i.e. associated with a field in a which component focus will shift to when you press the
table), or not. A data-aware edit component (i.e. a DBEdit Label’s short-cut key, “D” in this case.)
component) has different events than one that is not (i.e. an
Edit component), and consequently, requires distinct tech-
niques for field-level validation.

Let’s start by considering standard controls — components that


are not linked to a table. There are six of them on the Standard
page of the Component Palette:
• Edit
• Memo
• CheckBox
• RadioButton
• ListBox
• ComboBox

Of these six components, field-level validation is easiest with the


last five. A Memo component typically contains simple text (in
its Lines property) that is rarely evaluated programmatically.
Figure 1: Building the example form.
The remaining four components can be set so the user cannot
enter invalid data. For example, a CheckBox can have only two Next, select the ComboBox. Begin by changing its Style property
states; its Checked property can be True or False. There is no way to csDropDownList. This style requires the user to select from the
for the user to place this component in an invalid state. Likewise, dropdown list. By comparison, when a ComboBox uses the
RadioButton and ListBox components display only those values csDropDown style, a user can either select from the dropdown list
available to a user. Even a ComboBox can be configured to per- or enter text. Importantly, this entered text doesn’t have to corre-
mit only the selection of valid data. spond to one of the dropdown list items, so you must validate
csDropDown style ComboBox components using the same tech-
This leaves the Edit component. Field-level validation is most niques as those used for Edit components.
difficult with Edit components. This is because the user is
free to enter almost any value. However, your code may be You are now ready to define the contents of the ComboBox’s
expecting a value that conforms to a particular data type, such dropdown list. Select the ComboBox’s Items property in the
as a number, date, or time. Validation of Edit components Object Inspector and then click on the ellipsis that appears.
often requires validation code (an example of which is provid- Delphi displays the String list editor. Now enter the days of the
ed later in this article). week, one on each line, beginning with Sunday (see Figure 2).
Click the OK button to save the list.
Note: There is a component similar to Edit that is somewhat
easier to validate without requiring code. This is the EditMask Press 9 to compile and run the program. The running form
component, and it appears on the Additional Component (see Figure 3) permits you to select any item from the dropdown
Palette page. This component includes an EditMask property list. Importantly, it does not permit you to enter a value that is
which can be used to limit which characters the user can enter not a day of the week. This is an ideal way of ensuring that your
into the control. Using the EditMask property is described in data is valid, without having to write code.
Part II of this series.)
You may notice the running form doesn’t have a default value in
An Example of Code-Free Validation the ComboBox when the form first opens. When a ComboBox’s
The following example demonstrates how to create a standard Style is set to csDropDown, you can use the Text property to
control that does not require field-level validation code. Since the define the default value. But when Style is set to csDropDownList,

AUGUST 1995 Delphi INFORMANT ▲ 30


DBNavigator

The Text property permits you to define the default value that
will appear in the component. At a minimum, this property
should be set to a blank string. It looks strange to the user if the
component name (e.g. Edit1) appears by default.

However, these properties provide only limited validation of


data. In most cases, the issue reduces to one of data type.
Specifically, data entered into an Edit component is necessarily
text. However, you will often use an Edit component to permit
the user to enter a value of a particular data type, such as a num-
ber, an integer, a date, or a time. When the data you want the
user to enter into a field is more restrictive than text, it’s up to
you to verify that the entered data conforms to the desired type.

There are a number of events to which you can attach your Edit
component validation code. Some of these require more work
Figure 2 (Top): The String list than others. For instance, if you add your validation code to
editor dialog box. Figure 3
either the OnKeyDown or OnKeyUp event handlers, you must
(Left): The demonstration form
at run-time. The user can only evaluate the entered data after each keystroke. In many cases, this
enter values from the is a lot of work. For example, if the Edit component is used to
ComboBox’s dropdown list. get a date from a user, your code must account for the fact that
the value will not conform to a date value until the user enters
the last character.
the Text property is blank. If you need to define a default value
for your DropDownList ComboBox, add the following line to the I have found it easier to validate data when the user attempts to
form’s OnCreate event: leave the field, or before the value in the Edit component is used
by another part of the program. For example, if a button contains
ComboBox1.ItemIndex := 0; code in its OnClick event handler that will generate a query based
on a value in an Edit component, the OnClick code should first
This Object Pascal statement sets the ComboBox’s default to the validate the Edit component’s data. Likewise, if the validation
first string stored in the List property (i.e. Sunday). needs to be performed before a form is closed, the validation code
can be called from the form’s OnCloseQuery event handler (and its
Validating Standard Controls Using Code CanClose parameter can be set to False if invalid code is found).
Edit components are more complex to validate. On one hand,
they possess properties you can use to ensure the user enters The specific technique you employ to validate the Edit compo-
appropriate data. On the other hand, there are many situations nent depends on the type of validation required. Since most of
where you must add code to ensure validity. the time the validation relates to the data type of the entered
text, a try...except statement is the most useful. In the try block
Important properties that you should consider using with you attempt to cast the Text property of the field to the particu-
Edit components include CharCase, MaxLength, ReadOnly, lar data type.
and Text. You can use CharCase if you want to control the
case of data entered into an Edit component. For example, If the value cannot be cast to the specified value, Delphi will
setting CharCase to ecUpperCase will convert all letters generate an exception. You trap this exception in the except
entered into that field to upper-case, while ecLowerCase will block, and respond accordingly by displaying a message in a sta-
convert them to lower-case. tus bar (usually a Panel component), or by raising a custom
exception (displaying an error message you’ve defined).
The MaxLength property enables you to define the maximum
number of characters the user can enter into a field. If the Even if the Text property of the Edit object can be successfully cast
user attempts to enter one character more than the defined to a date type, it is still possible that the value is not valid based on
MaxLength value, the form beeps and the character is rejected. business rules. For example, you may not want to permit the user
When MaxLength is set to zero, no limit is enforced. to enter a date later than today’s date. When an unacceptable date
is detected by your code, you can explicitly raise an exception.
You use the ReadOnly property to prevent the user from changing This can permit the rule violation to be handled by the same
a value in an Edit component. Obviously, if an Edit component is exception handler that processes the illegal assignment exception.
read-only, the user cannot change the value. Often, you modify
the ReadOnly property at run-time, changing the Edit component The following example demonstrates how to validate a field.
from editable to non-editable, based on events on the form. Because this type of validation is often called from more than

AUGUST 1995 Delphi INFORMANT ▲ 31


DBNavigator

one event, this code will be nent to validate. If the date in that Edit component is found
placed in a function. This to be invalid, an error message is displayed and ValidateDate
allows it to be called from returns the value False. Otherwise, the function returns the
any event handler that must value True.
validate the field. (The
specifics of creating a new As an additional demonstration, this code also sets the value
function are not discussed of the Day of Week ComboBox after a valid date has been
here. Likewise, exception entered. This is done by modifying the ComboBox’s
handling and exception cre- ItemIndex property. However, notice it’s necessary to subtract
ation is demonstrated without Figure 4: Adding an Edit compo- one from the DayOfWeek function. This is because List com-
going into detail. If you need nent to the example form. ponents have a zero-based index, while the DayOfWeek func-
additional information about tion returns a value from one to seven. If you want to use the
these topics, please refer to the Delphi User’s Guide.) ValidateDate function as a generic date validation function,
Begin by adding a Label component and an Edit component to you would remove the following statement:
your form. Change the Caption property of the Label component
ComboBox1.ItemIndex := DayOfWeek(newValue)-1;
to D&ate:, set the FocusControl property to Edit1, and delete Edit1
from the Text property (see Figure 4).
We’re not finished implementing the ValidateDate function. It’s
still necessary to declare the function in the interface part of the
Next, select the Edit component and set its MaxLength property
unit. Add the header of the function (without the TForm1 com-
to 10 (10 characters is sufficient to permit the entry of a date).
ponent name) to the type declaration.
Next, press @ to display the unit. Move your cursor to the
line just above the final statement in the unit (end.), and enter
It is also necessary to declare the exception EEarlyDate. This
the ValidateDate function shown in Figure 5.
must be done before the form declaration. When you are
through the type declaration should look like this:
The ValidateDate function takes a single parameter — an Edit
component. This permits you to call this validation code from type
various routines, passing the name of a specific Edit compo- EEarlyDate = class(Exception);
TForm1 = class(TForm)
Label1: TLabel;
ComboBox1: TComboBox;
function TForm1.ValidateDate(TheField: TEdit): Boolean; Edit1: TEdit;
var Label2: TLabel;
NewValue: TDateTime; function ValidateDate(TheField: TEdit): Boolean;
begin private
{ Initialize the return value. } { Private declarations }
Result := True ; public
{ Do not evaluate if the field is blank. } { Public declarations }
if TheField.Text = '' then end;
Exit;
try All you need to do now is call this function from the OnExit
{ Cast the field’s text to a date. } event handler for the Edit component. Return to the form,
NewValue := StrToDate(TheField.Text);
{ The value is a date. Perform any additional tests. } select the Edit component, and double-click OnExit on the
if NewValue < StrToDate('1/1/95') then Events page of the Object Inspector. Modify the Edit1Exit
raise EEarlyDate.Create('Date cannot be before 1995') event handler to look like this:
else
{ Valid date. Modify the value of ComboBox1.}
ComboBox1.ItemIndex := DayOfWeek(newValue)-1; procedure TForm1.Edit1Exit(Sender: TObject);
except begin
on EEarlyDate do ValidateDate(Edit1);
begin end;
Result := False;
raise; Compile the project, save it as VALIDATE.DPR, and exit Delphi.
end;
else Then select File | Run from Windows Program Manager and
begin enter the name of the executable project (include the path and the
Result := False; name VALIDATE). Once the form is running, move to the Date
raise Exception.Create('Invalid date');
end; field and enter an invalid date. Then press F to exit the field.
end; This will produce an exception resembling that in Figure 6. Move
back to the Date field and enter a valid date. This time, the value
end;
displayed in the Day of Week field will be updated.

Figure 5: This custom ValidateDate function uses a try...except block Note: To see how the exception appears to the user, it is best
to validate a date value.
to run this program from the Program Manager, rather than

AUGUST 1995 Delphi INFORMANT ▲ 32


DBNavigator

from the Delphi IDE. If you


run the program from the
Delphi IDE, and if Break on
Exception is enabled on the
Preferences page of the
Environment Options dialog
box (the default setting), each
exception puts the program
into the Debugger. To see the
exception the user sees, you Figure 6: The code in Figure 5
must “step over” the excep- produces this exception.
tions created by Delphi as
well as those you raise.

Conclusion
It is often necessary to ensure that data entered by users con-
forms to certain parameters. Here we have considered how to
perform this task with fields not associated with table data.
While some of these components required no code to ensure
valid data, Edit components do.

In the next installment, we’ll look at techniques for performing


field-level and record-level validation with data-aware controls. ∆

The demonstration project referenced in this article is available on the


1995 Delphi Informant Works CD located in
INFORM\95\AUG\CJ9508.

Cary Jensen is President of Jensen Data Systems, Inc., a Houston-based database


development company. He is a developer, trainer, author of numerous books on data-
base software, and Contributing Editor of Delphi Informant. You can reach Jensen Data
Systems at (713) 359-3311, or through CompuServe at 76307,1533.

AUGUST 1995 Delphi INFORMANT ▲ 33


Sights and Sounds
Delphi / Object Pascal

By David Faulkner

Show Your Colors


Creating Visual Effects with Delphi’s Canvas Property

ne of the many nice things about programming in Windows is its

O device independence. When you write information to the screen or


printer, your program does not need to worry about loading, linking,
or calling device drivers that may differ from machine to machine.

The program in this article demonstrates device independence by creating the color triangle shown
in Figure 1. Try this program with different video drivers, resolutions, and number of colors. By
varying some of the calculations, you can create some spectacular screens.

Writing to a Form’s Canvas


Delphi makes it easy to place text on a form. You just place a Label component on a form and sup-
ply the appropriate caption. Because this is so easy, you may not be aware that you can program-
matically place text on a form without using a Label component. For example, create a new form
and place a Button component on it. In the button’s OnClick method, write the following code:

Form1.Canvas.TextOut(10,10,'Hi Mom');

Now run the form and click the button. Assuming your button isn’t in the wrong place, “Hi
Mom” should appear in the screen’s upper-left corner.

Each form you create has a Canvas property of type TCanvas. With
the form’s canvas you can easily draw lines, circles, boxes, and text.
The Canvas property encapsulates the Windows device context. If you
are not already convinced that Delphi is the “cat’s meow”, the Canvas
property should convince you. If you had to write the “Hi Mom”
code above using just the Windows API, you would need to do quite
a bit of work creating and destroying pens and brushes.

The form’s canvas also gives you access to the individual pixels on a
form. This is done through the Pixels property:

property Pixels[X, Y: Longint]: TColor;

X and Y represent the horizontal and vertical canvas coordinates of a


pixel and TColor represents the pixel’s color. This property is both
read and written at run-time so you can either set or determine the
Figure 1: The color triangle program in action.
pixel’s color.

AUGUST 1995 Delphi INFORMANT ▲ 34


Sights and Sounds

For a quick example of the Pixels property, create a form and By substituting this equation into the above Pythagorean equa-
enter the following code into the form’s OnClick method: tion, and doing some algebra we have:
procedure TForm1.FormClick(Sender: TObject);
var h 2 = ( 1 2 h) 2 + y 2
x,y : integer;
begin
for x:=0 to Form1.ClientWidth do 1
for y:=0 to Form1.ClientHeight do h2 = h2 + y2
Form1.Canvas.Pixels[x,y] := 4
$02000000 + Trunc($ffffff * Random);
end; 3 2
h = y2
4
Run the form and click on it. The form should fill from left to
right with random colors (not exactly exciting, but it gets better). 4 2
h2 = y
3
The TColor value of the Pixels property determines the color
of a pixel. Its type is Longint so it is four bytes long. The first 2
h= y
byte determines how the color is rendered on a palette. The 3
next three bytes represent blue, green, and red, respectively. A
value of zero for any of these colors means that color is not
In Object Pascal code this becomes:
displayed at all, while a value of $FF (that’s Delphi’s hex
notation for 255) means full intensity of that color. For
const
example $02FF0000 is blue, $0200FF00 is green,
Sqrt3=1.732; { The square root of 3. }
$020000FF is red, $02000000 is black, and $02FFFFFF
(all colors) is white.
begin
with Form1 do
The Color Triangle
begin
To create the color triangle, create a new form and call the
intTriangleHeight := ClientHeight-2;
DrawTriangle method (shown in Listing Three on page 38) from
IntTriangleWidth := Trunc(2*intTriangleHeight/Sqrt3);
either a button or menu choice. Note that this code is more
complicated than it needs to be just to draw a triangle. The
Note here that the square root of three is declared as a constant
complexity is there so the user can configure the application to
named Sqrt3. This is because the square root of three is used in
create those cool screens (which we’ll see a bit later).
a number of places in the program including once in a loop.
There is no need to slow down the program by making the com-
First, the code in DrawTriangle determines the coordinates of
puter do a calculation each time Sqrt3 is needed.
the triangle’s three points. The triangle’s height is set to the
form’s height minus two pixels to give a one pixel border at
With the height and width of the triangle determined, it’s a sim-
the top and bottom of the form. The width is a bit more
ple matter to calculate the coordinates of the triangle’s three ver-
complicated to calculate, and you might need to brush up on
tices. A pair of nested for loops is used to visit every pixel in the
your trigonometry and algebra skills to see where the formula
triangle as follows (this code is a simplified version):
comes from.
for y:= intTopY to intTriangleHeight do
The Pythagorean theorem states the square of the hypotenuse begin
of a right triangle is equal to the sum of the squares of the for x:=intTopX-Trunc(y/Sqrt3) to intTopX+Trunc(y/Sqrt3) do
begin
other two sides: { Statements to enter color screen pixels }
end;
end;
h2 = x2 + y2
The intTopY and intTopX variables represent the x and y coordi-
Here h is the length of the hypotenuse, and y is the height of nates of the triangle’s top vertex. Notice the use of the Sqrt3
the triangle, and we are looking for x, the width of the trian- constant again. This time the reader must perform the necessary
gle. Since the color triangle is an equilateral triangle (all its algebra to calculate the start and end of the x loop.
sides are of equal length), we will work with the right triangle
created by the line y. Since the line y bisects the bottom of Within the nested loop, the objective is to vary the intensity of each
the triangle, we know that: color in proportion to the distance from that color’s vertex. The dis-
tance between two points on a plane is calculated with this formula:
1
x= h 2 2
2 d= x 2 − x1 − y 2 − y1

AUGUST 1995 Delphi INFORMANT ▲ 35


Sights and Sounds

In code this becomes:


longBlueDistance := Trunc(Sqrt(Sqr(intTopX-x) +
Sqr(intTopY-y)))

Since the blue vertex is the top vertex, the intTopX and
intTopY variables are used in this calculation. The Sqrt func-
tion returns a real number, so the Trunc function is used to
convert the real number into an integer that can be assigned
to the longBlueDistance variable. Similar calculations are done
for each color.

With the distance known, the amount of blue is proportioned Figure 2: The configuration dialog box.
with the following code:

realBluePart := ((intTriangleWidth-longBlueDistance) / ables that are meant to be accessed by any other program using
intTriangleWidth); a unit should be declared in the interface section of the unit:
longBlue := Trunc($ff*realBluePart)*$ff*$ff;
interface
The realBluePart variable is assigned a fraction between zero and
uses
one since the minimum BlueDistance is zero and the maximum type
BlueDistance is equal to the length of any side of the triangle.
This fraction is then multiplied by 255 to obtain the actual blue var
Form1 : TForm1;
intensity that will be used to color a pixel. Since the blue part of byteBlueOption : byte;
the TColor type is the second byte, the number is multiplied by byteRedOption : byte;
255 * 255 to shift it into its proper position. byteGreenOption : byte;
boolFullScreen : Boolean;
boolColorLimit : Boolean;
Actually, the code would be faster and more accurate if it read: boolPaletteCheck : Boolean;

longBlue := Trunc($ff*realBluePart) shl 16 implementation

The shift left operator, shl, shifts the value 16-bits (two bytes) Before any of these variables can be used, they must be initial-
to the left to move it into the proper position. The problem ized. Since there is no guarantee the user is going to configure
with this method is that it removes some of the cross color the program before they initiate the drawing process, it’s a good
interference resulting in the various screens you’ll create at the idea to initialize the variables in the form’s Create method:
end of the article.
procedure TForm1.FormCreate(Sender: TObject);
begin
After each color is calculated, it can be used to assign a color to a byteBlueOption := 0;
screen pixel as follows: byteGreenOption := 0;
byteRedOption := 0;
boolFullScreen := False;
Canvas.Pixels[x,y] := longBlue + longGreen + longRed;
boolColorLimit := True;
boolPaletteCheck := True;
That’s it for creating the color triangle. Download the code or end;
type it in (it’s not that long) and try it.
To give the user access to the configuration dialog box, either a
Configuring the Color Triangle menu choice or a button can call this code:
While writing the original color triangle code, I made a number
procedure TForm1.Config1Click(Sender: TObject);
of coding mistakes that yielded some wild results. The results
begin
were odd enough that I decided to make the program user-con- ConfigDialog.ShowModal;
figurable so the user could recreate the same effects. I did this by end;
creating the dialog box shown in Figure 2.
Note the unit that creates the configuration dialog box must be
Adding a configuration dialog box to this or any other pro- included in the main form’s uses clause for the above code to
gram is relatively easy, but there are a few things you must compile. The ShowModal function shows the passed form and
know. The configuration dialog box must communicate with insists the user close that form before continuing.
the main form.
Getting Around a Circular Reference
One way of doing this is with global variables that both the The first problem the configuration dialog box faces is gaining
main form and configuration dialog box can access. Global vari- access to the main form’s global variables. It seems logical to accom-

AUGUST 1995 Delphi INFORMANT ▲ 36


Sights and Sounds

plish this by placing the main form’s unit in the dialog box’s uses
clause. If you try this, Delphi will respond with the “Error 68:
Circular Unit Reference” when you compile. This happens because
the main form uses the dialog box’s unit, which in turn uses the
main form’s unit, which in turn uses the dialog box’s unit, etc.

To work around this, the main form’s unit should be added to


the implementation part of the dialog box’s unit. Declarations
made in the implementation part of a unit are private and there-
fore cannot be seen by other units.

With the main form’s unit (Coloru.PAS in this example) available


to the dialog box, access to the main form’s global variables is easy:

FullScreenButton.Checked := Coloru.boolFullScreen;
TriangleButton.Checked := not Coloru.boolFullScreen;
ColorLimitButton.Checked := Coloru.boolColorLimit;
PaletteCheckButton.Checked := Coloru.boolPaletteCheck;

This code is used to initialize the values of the various components


in the configuration dialog box. When the dialog box is closed, simi-
lar code is used to set the values of the main form’s global variables.

Compiler Directives
You may have noticed the following two lines of code at the
beginning of the Coloru unit:

{$R-}
{$Q-}

Although these look like comments, they do a lot more. Any com-
ment beginning with a dollar sign ( $ ) tells Delphi to do something
special at compile time. The {$R-} compiler directive tells Delphi to
turn off range checking. This quickens the compile and allows the
math in the DrawTriangle method to go out of range without caus-
ing a run-time exception. The {$Q-} compiler directive tells Delphi
to turn off overflow checking in integer math. Again, this speeds
compilation and allows the integer math in the DrawTriangle
method to overflow during run-time without causing exceptions.

These two options can be set interactively on the Compiler


page of the Project Options dialog box (see Figure 3), but it’s
better to embed the compiler directives in source code. This
allows the code to be compiled on other machines without
having to check the compiler settings.

One other compiler directive you might want to play with is {$N-}.
This tells Delphi to do real number math in software instead of
using the floating point coprocessor on your machine. If you use
this directive, you will notice a big slowdown in the program (unless Figure 3 (Top): The Compiler page of the Delphi Project Options dia-
of course, your machine doesn’t have a math coprocessor). log box. Figure 4 (Middle): Fun with colors. Use these settings to
create the color triangle as shown. Figure 5 (Bottom): To generate
this “field of circles”, set the Red, Green, and Blue radio buttons
Conclusion to: S. Root, S. Root, and Nothing (respectively). Deselect Color
So have some fun. Use the configuration dialog box to produce Limit, check Palette Check, and select Full Screen.
the special effects shown in Figures 4, 5, 6, and 7.
colors, and fonts. This may seem like a frivolous exercise, but
Delphi gives the programmer quick and easy access to the form’s when it comes time to write your components you’ll use the
canvas and you can experiment with various lines, boxes, pixels, skills learned here to write custom OnPaint code. ∆

AUGUST 1995 Delphi INFORMANT ▲ 37


Sights and Sounds

Begin Listing Three — Coloru.PAS

{$R-}
{$Q-}

unit Coloru;

interface

uses
SysUtils, WinTypes, WinProcs, Messages, Classes,
Graphics, Controls, Forms, Menus, Config;

type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
Config1: TMenuItem;
Draw1: TMenuItem;
procedure Config1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure DrawTriangle;
procedure Draw1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
byteBlueOption: Byte;
byteRedOption: Byte;
byteGreenOption: Byte;
boolFullScreen: Boolean;
boolColorLimit: Boolean;
boolPaletteCheck: Boolean;

implementation

{$R *.DFM}

Figure 6 (Top): This “super nova” is created by setting Red to procedure TForm1.DrawTriangle;
Square, and Green and Blue to S. Root. Color Limit and Palette var
Check are not checked. Figure 7 (Bottom): To get this “cosmic { Coordinates of top and bottom left of triangle }
intTopX,intTopY,intLeftX,intLefty,
egg” set Red and Green to Nothing and Blue to S. Root. Deselect
{ Coordinates of bottom right of triangle }
Color Limit and Palette Check.
intRightX,intRightY: Integer;
{ Height and width of triangle }
intTriangleHeight,intTriangleWidth: Integer;
{ Distance current position to triangle point }
The demonstration project referenced in this article is available on longBlueDistance,
the 1995 Delphi Informant Works CD located in longGreenDistance,longRedDistance: Longint;
{ Fraction of ColorDistance to MaxDistance }
INFORM\95\AUG\DF9508. realBluePart,realGreenPart,realRedPart: Real;
{ Color of pixel to be placed on screen }
longNewColor: TColor;
{ Amount of RGB for each color }
longRed,longGreen,longBlue: Integer;
{ First in last pixel in row of triangle }
David Faulkner is a developer with Silver Software in Kula, Hawaii. He is also intXBegin,intXLimit,
Contributing Editor to Paradox Informant, and co-author of Using Delphi: Special { First and last pixel in col of triangle }
Edition (Que, 1995). Mr Faulkner can be reached at (808) 878-2714, or on intYBegin,intYLimit: Integer;
CompuServe at 76116,3513. { Loop counters }
x,y: Integer;

const
{ The Square Root of 3 }
Sqrt3=1.732;

begin
with Form1 do
begin
{ One pixel space on top and bottom }
intTriangleHeight := ClientHeight-2;
{ Get out your trig book }

AUGUST 1995 Delphi INFORMANT ▲ 38


Sights and Sounds

intTriangleWidth := Trunc(2*intTriangleHeight/Sqrt3);
{ Top is half way across screen } realGreenPart := ((intTriangleWidthlongGreenDistance)/
intTopX := ClientWidth div 2; intTriangleWidth);
{ and one pixel down } longGreen := Trunc($ff*realGreenPart)*$ff;
intTopY := 1;
if boolColorLimit then
intLeftX := (ClientWidth - intTriangleWidth) div 2; longGreen := longGreen and $0000ff00;
intLefty := intTopY+intTriangleHeight;
intRightX := (ClientWidth + intTriangleWidth) div 2; case byteRedOption of
intRightY := intTopY+intTriangleHeight; 0: longRedDistance := Trunc(Sqrt(Sqr(intRightX-x) +
Sqr(intRightY-y)));
if boolFullScreen then 1: longRedDistance := Sqr(Sqr(intRightX-x) +
begin Sqr(intRightY-y));
intYLimit := ClientHeight; 2: longRedDistance := Abs(Sqr(intRightX-x) +
intYBegin := 0; Sqr(intRightY-y));
end end;
else
begin realRedPart := ((intTriangleWidthlongRedDistance)/
intYLimit := intTriangleHeight; intTriangleWidth);
intYBegin := intTopY; longRed := Trunc($ff*realRedPart);
end;
if boolColorLimit then
for y:=intYBegin to intYLimit do longRed := longRed and $000000ff;
begin
if boolFullScreen then longNewColor := longBlue+longGreen+longRed;
begin
intXLimit := ClientWidth; if boolPaletteCheck then
intXBegin := 0; longNewColor := longNewColor and $02ffffff;
end Canvas.Pixels[x,y] := longNewColor;
else { End of for x loop }
begin end;
{ Get out that trig book again } { End of for y loop }
intXBegin := intTopX-Trunc(y/Sqrt3); end;
intXLimit := intTopX+Trunc(y/Sqrt3);
end; { End of 'with Form1 do begin' }
end;
{ For each pixel in this row } {End of procedure}
for x:=intXBegin to intXLimit do end;
begin
case byteBlueOption of procedure TForm1.Config1Click(Sender: TObject);
0: longBlueDistance := Trunc(Sqrt(Sqr(intTopX-x) + begin
Sqr(intTopY-y))); ConfigDialog.ShowModal;
1: longBlueDistance := Sqr(Sqr(intTopX-x) + end;
Sqr(intTopY-y));
2: longBlueDistance:= Abs(Sqr(intTopX-x) + procedure TForm1.FormCreate(Sender: TObject);
Sqr(intTopY-y)); begin
end; byteBlueOption := 0;
byteGreenOption := 0;
realBluePart := ((intTriangleWidth-longBlueDistance) / byteRedOption := 0;
intTriangleWidth); boolFullScreen := False;
longBlue := Trunc($ff*realBluePart)*$ff*$ff; boolColorLimit := True;
boolPaletteCheck := True;
if boolColorLimit then end;
longBlue := longBlue and $00ff0000;
case byteGreenOption of procedure TForm1.Draw1Click(Sender: TObject);
0: longGreenDistance := Trunc(Sqrt(Sqr(intLeftX-x) + begin
Sqr(intLefty-y))); DrawTriangle;
1: longGreenDistance := Sqr(Sqr(intLeftX-x) + end;
Sqr(intLefty-y));
2: longGreenDistance := Abs(Sqr(intLeftX-x) + end.
Sqr(intLefty-y));
end;
End Listing Three

AUGUST 1995 Delphi INFORMANT ▲ 39


On-Line
Delphi / World-Wide Web / HTML

By Rand McKinney

Delphi on the Web


A Guide to Delphi Resources on the World-Wide Web

nless you’ve been under a rock for the last year, you’ve at least heard

U of the world-wide web (WWW), a graphical, hypertext-based interface


to the Internet. If you have a “browser” tool such as Netscape or
Mosaic (both are available free), and a proper connection to the Internet, you
can access a virtually limitless array of information provided on web sites or
“pages” by universities, corporations, and individuals.

In recent months, a number of Delphi-centric web pages have appeared. Created by Delphi pro-
grammers, consultants, and writers, these web pages provide a wealth of useful information that’s
just a few mouse clicks away. Many sites have Delphi demonstration applications and components
available for download for free, or as shareware. Some provide forums for questions and answers on
Delphi programming, and others are simply marketing vehicles for Delphi application developers.
These web sites literally span the globe: there are Delphi web pages on servers in Australia, Sweden,
Poland, Germany, and across the United States.

Web Pages
The following is an incomplete list of some of the best web pages devoted to Delphi. Each
page has a URL (Uniform Resource Locator) that is essentially the WWW address of the page.
You can type them or use the HTML file provided with this article (see end of article for
details). As of this writing, these URLs are accurate. However, the web is dynamic by nature
so some may have changed.

Official Web Pages


The following are the only official Borland web pages.

The Official Borland Delphi Web Page


http://www.borland.com/Product/Lang/Delphi/Delphi.html
This page includes a Delphi fact sheet, news, and press releases from Borland, downloadable documen-
tation in Adobe Acrobat format, lists of Delphi educational resources, and other Borland information.

Borland FTP Server on the Web


ftp://ftp.borland.com/pub/ftpmenu.htm
The Borland FTP (File Transfer Protocol) server, presented in living HTML for your browsing
pleasure. This is the official place to download a variety of Delphi-related files and other
Borland products. If you don’t have a web browser, you can access the same files at ftp.bor-
land.com.

AUGUST 1995 Delphi INFORMANT ▲ 40


On-Line

Delphi Technical Support Home Page Delphi Bug-List Web Page


http://loki.borland.com:8080/ http://www.cybernetics.net/users/bstowers/delphi-bugs.html
The Delphi technical support web page, including Delphi questions Unofficial list of known bugs and work-arounds in Delphi,
and answers, links to the Borland Database Engine (BDE), maintained by a Delphi programmer in North Carolina.
ReportSmith, SQL Links web pages, and other relevant information.
Delphi Hacker’s Corner
Commercial Sites http://tmpwww.electrum.kth.se/~ao/DHC/
The following web pages are maintained by companies or indi- An excellent web page maintained by Anders Ohlsson in
viduals for commercial reasons. Some require payment for their Sweden. It includes tips and tricks, demonstrations, a list of
components, books, or applications, but many have freeware and major Delphi users’ groups, and European mirror sites for
shareware available for download. Delphi FTP resources.

InfoPower Component Library The Delphi Station


http://www.webcom.com/~wol2wol/infopowr.html http://www.teleport.com/~cwhite/wilddelphi.html
InfoPower, from Woll2Woll Software, is a library of Delphi data- With dozens of shareware and freeware Delphi components,
aware components that are automatically installed into Delphi’s there’s an incredible amount of useful information, examples,
Component Palette. [InfoPower is reviewed on page 45.] and other Delphi-related stuff on this page.

The Coriolis Group’s Delphi Explorer Dave’s Delphi Destination


http://www.coriolis.com/coriolis/whatsnew/delphi.htm http://vislab-www.nps.navy.mil/~drmcderm/delphi.html
Excerpts from the book Delphi Programming Explorer, Delphi arti- Numerous valuable resources, including The Unofficial Delphi User’s
cles, commercial and shareware Delphi software, etc. are available. Newsletter (in Windows on-line help format), calendar components,
and the famous TSmiley component, are available on this page.
Delphi RADical Application Development
http://super.sonic.net/ann/delphi/ Michael’s Delphi Home Page
This page of components enables you to use Delphi for web http://linux.rz.fh-hannover.de/~holthoefer/delphi.html
server CGI programming. It includes descriptions, demonstra- Lots of components, demonstrations, and other good stuff.
tions, and downloadable components. There’s also a link to 32
downloadable freeware components created by Michael Ax. The Delphi Super Page
http://sunsite.icm.edu.pl/archive/delphi/
Delphi TAutoButton Component Straight from Poland: Warsaw University’s Sunsite has a
http://www.widewest.com.au/delphi/ Delphi page loaded with demos, tips and tricks, shareware and
A Delphi component built by a Delphi programmer with freeware components.
AeroSoft in Australia.
Annotated Bibliography of Delphi Articles and Books
The City Zoo http://www.iscinc.com/dugbib.html
http://www.mindspring.com/~cityzoo/cityzoo.html A list similar to this one, but for printed materials on Delphi.
Tips and tricks, Delphi announcements, components, etc., from
a Delphi consultant in Florida. General Pascal Pages
Turbo Pascal Programmer’s Guide
CIUPKC Software http://www.cs.vu.nl/~jprins/tp.html
http://www.webcom.com/~kilgalen/welcome.html A comprehensive list of web sites and resources related to the Pascal
CIUPKC Software (pronounced “soo-pack”) is a small software language, maintained by a Pascal programmer in The Netherlands.
development company specializing in software built with Delphi.
Their page has a few shareware components, and lots of links to The Perkins Pascal Page
other sites and software. http://www.iii.net/users/rexkp.html
This page provides current information on BugSlay, the Pascal
Non-commercial Sites Postmortem Debugger, as well as links to other Pascal related
The following web pages are maintained by individuals for their information.
own reasons — primarily out of sheer love for Delphi and its
capabilities. These are always informative, sometimes amusing, User Group Sites
and occasionally quirky. There are many Delphi user groups around the world. Anders
Ohlsson in Sweden maintains a comprehensive list of them at
Delphi FAQ the following URL:
http://www.mhn.org/delphi.faq
Comprehensive, but unofficial, Delphi Frequently Asked http://tmpwww.electrum.kth.se/~ao/DHC/dug.html
Questions list. Some of the user groups even have their own web pages.

AUGUST 1995 Delphi INFORMANT ▲ 41


On-Line

New York Delphi Users’ Group


http://www.iscinc.com/nydug.html

North Bay Delphi Special Interest Group


http://Super.Sonic.Net/delphisig/index.html

Salt Lake City Delphi Users’ Group


http://www.xmission.com/~uldata/delphi.html

Discussion Forums and Newsgroups


Delphi WWW Forum
http://www.pennant.com/delphi/hn/dconn.html
A newsgroup-like forum in HTML format for Delphi users.

comp.lang.pascal
The Usenet newsgroup for discussion of Pascal-related topics,
including Delphi.

alt.comp.lang.borland-delphi

Alternative-hierarchy Usenet newsgroup for discussion of Delphi. ∆

The HTML referenced in this article is available on the 1995 Delphi


Informant Works CD located in INFORM\95\AUG\RM9508.

C. Rand McKinney is a Senior Technical Writer for the Delphi team at Borland
International. Previously, he helped to document the InterBase 4.0 Workgroup Server
and client tools. He has also worked as an AI researcher and a space systems analyst.
He can be reached at [email protected].

AUGUST 1995 Delphi INFORMANT ▲ 42


At Your Fingertips
B Y D A V I D R I P P Y
Delphi / Object Pascal

F or the things we have to learn before doing them, we learn by doing them.

— Aristotle, 384-322 BC

How can I create “hot regions” on my form?


A common way of presenting options to a multimedia applica-
tion user is to display an attractive bitmap in place of the usual
Windows menus and buttons. For example, the menu screen Figure 1:
This “menu
shown in Figure 1 consists of a single Image object created in screen” was
CorelDRAW! that displays three pictures representing different created in
areas of the system the user can access. Corel
DRAW!
The problem is, we need to be able to detect when the user
clicks within the areas of the three pictures. For example, we
must load the Recreation form when the user clicks on the
man playing golf. To do this, we can use the TShape compo-
nent and define an invisible “hot region” around the golfer.
This will enable us to detect when the user clicks within that
area. In essence, these hot regions become our “buttons” and
can respond to mouse events such as OnMouseDown and Figure 2:
OnMouseUp. Stretch the
Shape
As demonstrated in Figure 2, create a shape object on your objects to
cover the
form and stretch it until it covers the region that you want to area that
trap for mouse events. You can change the Shape property of you need to
the shape object to better fit this region. (Note that the icon trap for
representing the Shape component is a bit misleading; you can’t mouse
create a triangle.) Finally, change the BrushStyle property to events.
bsClear and the PenStyle to psClear. This will cause our shape to
be invisible at run-time. Create as many hot regions as needed
for your screen.
here’s a quick and dirty way to give your users the information
As mentioned earlier, the all-important benefit of creating these they need with a minimum of code.
regions is they provide you with several events you can trap for
in your program including the MouseDown event. Also, it’s likely Figure 3 shows a form with a TMemo component containing
you’ll attach code for loading additional forms, displaying infor- text that explains some highly technical information. To see the
mation, playing a sound bite, etc. — D.R. definition of a word within the memo field, the user simply
highlights the word and clicks on the Definition button. A dia-
How can I create a simple glossary system for a memo field? log box with the definition of the selected word will be dis-
For applications that rely heavily on terminology that may be played. For example, in Figure 4 the user is unsure of the mean-
unfamiliar to the user, it’s often a good idea to include a glossary ing of “life”. However, by clicking the Definition button, the
system to provide definitions. If you’re on a shoestring budget, meaning of life is made perfectly clear.

AUGUST 1995 Delphi INFORMANT ▲ 43


At Your Fingertips

Figure 3: You
Figure 7: This
can highlight
code is attached
a word in
to the OnClick
Windows by
event of the
double-click-
Definition
ing on it.
button.

How can I easily copy a record from one table to another?


Here’s a simple way to copy a single record from one table to anoth-
er, with only a few lines of code. Figure 8 shows a form containing
Figure 4: two table objects, named Table1 and Table2, and their correspond-
Pressing the ing DataSource and DBGrid components. This example will copy
Definition
button will
the current record from Table1 into Table2. Further, we will instant-
display the ly see the new record
word’s appear in the DBGrid of
definition. Table2 when the Copy
Record button is pressed.

All the code for copying a


record into a destination
The first step in implementing the glossary system is to create table with an identical
a table called GLOSSARY.DB with the structure shown in record structure is con-
Figure 5. In this table, you’ll store all the words and their tained in the OnClick event
Figure 8: This form copies a record from
meanings for the application. As shown in Figure 6, the sam- of the Copy Record button Table1 into Table2.
ple table contains the definitions for several words including as shown in Figure 9. Most
“LIFE”. It’s important to capitalize each letter of the word in of the important code is contained within the for loop. Basically, it
the WORD field for the IndexFields command to work prop- steps through each field in the current record of Table1 and assigns
erly. If you’re using a Paradox table, you can automate this their values to the same set of fields in Table2. Just make sure your
task by creating a picture of *& for the WORD field (see tables are open, either interactively or programmatically, before
Figure 5 again). attempting to copy.
Figure 5: Table
Field Name Type Size Key structure for the Figure 9: This
Word A 20 * GLOSSARY table. code is attached
to the OnClick
Definition A 60
event of the
Copy Record
button.
Figure 6: Define as
many words as needed
for your application.
Note: For simplicity, there is no exception handling for duplicate
records — you must only copy one record at a time. In a real
application, you would want to handle key violations more
All the code necessary for the glossary system is located in the gracefully. — D.R. ∆
OnClick event of Button1 as displayed in Figure 7. When the
user clicks on the Definition button, the table object TGlossary The demonstration forms referenced in this article are available on
is immediately placed in a kind of “search mode” by calling the the 1995 Delphi Informant Works CD located in
EditKey method. The word selected by the user is then convert- INFORM\95\AUG\DR9508.
ed to upper-case and used to specify the value we want to
locate in the WORD column via the FieldByName command.
Finally, the GoToKey method will attempt to locate the selected David Rippy is a Senior Consultant with Ensemble Corporation,
word. If it is found, the definition of the word is displayed in a specializing in the design and deployment of client/server database
dialog box. If the selected word is not contained in the GLOS- applications. He has contributed to several books published by Que,
and is a contributing writer to Paradox Informant. David can be
SARY table, a dialog box informs the user that no definition is reached on CompuServe at 74444,415.
available for the highlighted word. — D.R.

AUGUST 1995 Delphi INFORMANT ▲ 44


New & Used
by joseph c. fung

InfoPower
Woll2Woll’s VCL Components for Database Developers

After you are finished installing InfoPower, you can immediately

I
f you’ve been waiting for a third-party vendor to
supply an alternative to Delphi’s built-in data begin using its components to build a database application.
access components, your wait is over. Woll2Woll
Enhanced DataSet and DataSource Controls
Software has released InfoPower, a comprehensive At the core of InfoPower are three new data access components:
collection of native VCL components for database TwwDataSource, TwwTable, and TwwQuery. (There are actually
developers. InfoPower consists of 15 data-aware four if you include a new TwwQBE component, but we’ll ignore
components that add powerful new capabilities to it for now.) These new components are enhanced versions of the
Delphi, including a sophisticated data grid, built-in TDataSource, TTable, and TQuery components. They
build upon the basic VCL versions by adding new properties
enhanced DataSet and DataSource components, fil-
and methods. Many of InfoPower’s visual and non-visual com-
tering capabilities, incremental searching, expanding ponents rely on the extended functionality provided by these
memos, editable lookup combo-boxes, and a set of new components to work. The TwwDataSource, TwwTable, and
standard and user-defined search dialog boxes. TwwQuery components are derived directly from their Delphi
counterparts and are 100% backward compatible. Because of
Users familiar with the capabilities of Paradox for Windows’ fil- this, you can substitute the InfoPower versions directly into your
ters and TableFrame object will appreciate this software because it existing forms, including the ones created by the Form Expert.
brings similar capabilities to Delphi. InfoPower’s components are
also optimized to account for client/server operations so you can While TwwDataSource and TwwQuery serve mainly to interface
access remote data with minimal overhead. In addition, applica- with other InfoPower components, TwwTable adds important
tions you create with InfoPower can be distributed royalty-free. new functionality. A new Filter property has been added to sup-
port the ability to filter tables (explained below). A new
Installing InfoPower wwFindKey method has also been added to permit optimal
Installing InfoPower on your system is easy if you follow the searching against SQL tables. This new method replaces Delphi’s
instructions in the user manual. InfoPower comes with the typical FindKey method that is slow when used against large remote
Windows-hosted installation program that copies the necessary files data sets. Finally a new Pack method lets you remove dead space
to your hard disk. Once installed, you’re instructed to complete a from Paradox and dBASE tables.
series of manual steps to create an alias for the optional demonstra-
tion programs, install the components into Delphi’s component Access to BDE Filters
palette, and merge the InfoPower on-line help into Delphi. By default, Delphi lets you use ranges and queries to select a sub-
set of a table. The Borland Database Engine (BDE) also supports
For those tempted to skip the user manual and dive right into the concept of filters. Unlike ranges, filters are not restricted to
the sample applications, be sure to follow these steps or you indexed fields. A filter offers the flexibility of a query because a
might have trouble running the demonstration files. These files filter lets you use an expression to specify a criteria for any or all
require you to create an alias called InfoDemo that points to the the fields in a table. A filter also provides you with an editable
directory containing the sample tables. result set, which may not always be possible with a query.

AUGUST 1995 Delphi INFORMANT ▲ 45


New and Used

Delphi lets you use filters, but only if you are willing to do some Sophisticated Database Grid
engine-level programming. To implement filters in Delphi, you The centerpiece of InfoPower’s enhanced data controls collection
must program complex data structures and make BDE calls. If the is the TwwDBGrid component. This component extends upon
idea of using pointers scares you, you’re better off using the filter- Delphi’s built-in TDBGrid by adding significant new functionali-
ing capability in InfoPower. InfoPower makes using filters a breeze. ty, such as the ability to attach combo-boxes, checkboxes, and
memos to the grid. Fields from multiple tables in a one-to-one
To create a filter, simply use the TwwTable component’s Filter prop- relationship can be displayed on the same row without coding. In
erty and FilterActivate method. The Filter property is a TStringList addition, you can define fixed, non-scrollable columns in the grid
so use the Add method to assign criteria to the filter. Valid criteria so they always appear as the user pans through the fields. You can
statements can contain relational operators (< , > , <= , >= , = ,<>) also alter the default appearance of the grid, including word-wrap-
and the AND/OR logical operators. After specifying the filter, call ping the titles and changing individual cell colors. Another impor-
FilterActivate to apply the criteria against your table. The following tant, but subtle, improvement is the accurate display of the vertical
Object Pascal code illustrates how to create a filter that shows scrollbar’s thumb when scrolling through Paradox or dBASE
orders that have amounts exceeding 100 dollars: tables. Delphi’s TDBGrid leaves the thumb position “stuck” in the
center of the scrollbar. Many of InfoPower’s customers will be pur-
procedure TForm1.Button1Click(Sender: TObject);
begin
chasing the software just to obtain this component.
with TwwOrdersTable1 do
begin
Filter.Clear;
Filter.Add('Amount > 100');
FilterActivate;
end;
end;

The source table doesn’t need to be indexed to use a filter. If an


index does exist, however, you can select it for any purpose, such
as to change the display order of the records. The availability of
an index in the result set is one of the key advantages that filters
have over queries.

Filters also have some disadvantages. They tend to be slower than A TwwDBGrid component with customized titles and a combo box.
ranges because each record is evaluated as it is seen. Also, when you
apply a filter on a table, the RecordCount property reflects the total TwwDBGrid inherits from TDBGrid, so it works just like the
number of records in the table, not the number of records matching built-in grid. To use it, you assign a TwwDataSource to the grid’s
the filter. To obtain an accurate record count, you can use Object DataSource property. In turn, the TwwDataSource component’s
Pascal to iterate through the result set and count the records. DataSet property must refer to a TwwTable, TwwQuery, or
TwwQBE. The grid has several properties and events that you
New QBE Component program to alter its behavior and appearance.
Besides TwwTable and TwwQuery, InfoPower offers a third
data access component: TwwQBE. This useful component Enhanced CheckBoxes, Combo-boxes, etc.
enables you to use Paradox-style query-by-example (QBE) InfoPower makes it convenient to display a field in the grid as a
statements to query tables. This is a welcome addition to checkbox, combo-box, or lookup combo. Each field in a
Paradox for Windows developers who are familiar with QBE TwwDBGrid has a Control Type setting. You can access this set-
and want to make the transition to Delphi. Not only does ting from the Select Fields dialog box. This dialog box appears
TwwQBE let you run existing QBE statements unmodified, it when you click on the grid’s Selected property or the DataSet’s
also permits the creation of some queries not possible when ControlType property. The field’s control type determines the
you use SQL syntax against local tables (i.e. the dreaded appearance of its cell. This can be the default edit box, a checkbox,
“Capability Not Supported” message). or one of InfoPower’s several combo-box or lookup components.
If what you want is an edit box or checkbox, you set the control
To use the TwwQBE component, Woll2Woll recommends type to Field or CheckBox, respectively, and you’re finished.
you create the QBE statement from the Database Desktop or
Paradox for Windows, then load it into the QBE property of To display a combo-box or lookup, you must first bind one of
the component. You can also use the Add method to build InfoPower’s combo-box or lookup components to the field, then
the QBE statement at run-time since the QBE property is a leave it on the form with its Visible property set to False. Next
TStringList. Finally, the AnswerTable and AuxiliaryTables you use the Select Fields dialog box to set the field’s ControlType
properties are available so you can define the result set and property to Combo or LookupCombo, depending on the compo-
any auxiliary tables arising from INSERT, DELETE, or nent type you want to use. After you do this, a second drop-
CHANGETO operations. down list appears showing the names of all the components that

AUGUST 1995 Delphi INFORMANT ▲ 46


New and Used

you choose the table used in the one-to-one relationship, the


names of the joined fields, the index used, and the field that is
displayed. When you run the form, any linked fields are auto-
matically shown as read-only fields.

Controlling the Grid’s Appearance


TwwDBGrid offers much more control over the appearance of
the grid than Delphi’s TDBGrid. The FixedCols property lets you
define non-scrollable columns on the grid’s left side. The Ctrl3D
property gives the whole grid a 3-D look instead of only the
titles as TDBGrid permits. The TitleAlignment, TitleColor, and
TitleLines properties let you control the alignment, color, and
number of lines occupied by the titles. When you use the latter
property to create multi-line titles, you embed “~” symbols in
your titles to force the text onto the next line.

TwwDBGrid adds the OnCalcCellColors event to let you set the


appearance of individual cells in the grid. You can use this event
to highlight important fields or to convey status to the end-user.
Setting up a linked field. The following code sample turns the text color of the OnHand
field to clRed if its value falls below 30 items:
can be attached to the cell. When you choose one, the grid will
display it each time the cell has focus. procedure TForm1.OnCalcCellColors(Field:TField;
State:TGridDrawState; Highlight:Boolean;
AFont:TFont; ABrush:TBrush);
Two InfoPower components you can use with the grid are begin
TwwDBCombobox and TwwDBLookupCombo. TwwDBCombobox if Field.FieldName = 'OnHand' then
if Field.Value < 30 then
replaces Delphi’s built-in TDBCombobox component. Like the AFont.Color := clRed;
TwwDBLookupCombo, this control can be used inside the grid or end;
by itself. Woll2Woll found keystrokes — such as F, J, e,
and SF — didn’t function as expected when using the Searching, Sorting, and Locating
regular TDBCombobox with the InfoPower grid. You should use InfoPower contains two controls, TwwKeyCombo and
this replacement component with TwwDBGrid in place of TwwIncrementalSearch, that let you give the end-user the ability
TDBCombobox whenever you need to use a combo-box with a to “sort” a table and incrementally search for values. The
fixed list of choices. Aside from this adjustment, nothing else is TwwKeyCombo doesn’t actually sort a table, but lets you change
new about TDBCombobox. its display order. This component is a drop-down list that is
populated with the names of all the indexes for a table. When a
TwwDBLookupCombo is an enhanced TDBLookupCombo that selection is made, the table is ordered by the fields in the index.
adds several new features. TwwDBLookupCombo lets you select This mimics the capability of Paradox for Windows’ Table |
any number of fields from the lookup table to display. In addi- Filter | Order By menu command.
tion, you can control their display width and title descriptions.
When the drop-down list is displayed, the user can incremental- The TwwIncrementalSearch component lets the user incremental-
ly search the list by typing into the edit box. It also lets you ly search for values in a table. As the user enters a value in the
determine the alignment of the drop-down list relative to the control’s visible edit box, the
component’s edge. Finally, you do not have to fill in the selection is narrowed to the clos-
DataField and DataSource properties to bind the field. The est record. Internally,
component can be used without editing an underlying table, so TwwIncrementalSearch searches
it is useful in situations other than in the grid. the first field in the table’s active
index. This control is best used in
Creating Linked Fields conjunction with TwwKeyCombo
TwwGrid lets you display a linked field from another table by set- and a data grid to allow the user
ting properties. To do this with the built-in grid, you would have to select the index and view the
to write code in the OnCalcField event to reference the appropri- results of the search.
ate value from a lookup table, then display it in a calculated field.
InfoPower simplifies this by removing the need to write code. InfoPower provides two compo-
The Locate Field Value dialog
nents, TwwSearchDialog and box enables you to search
To display a linked field, you use the Edit Linked Field dialog TwwLocateDialog, that prompt the the fields of a table for a
box of the TwwTable to select a display field. This dialog box lets user when searching for a record. specific topic.

AUGUST 1995 Delphi INFORMANT ▲ 47


New and Used

TwwSearchDialog combines the features of TwwIncrementalSearch table is displayed and what


and TwwKeyCombo in a dialog box so that users can incrementally to do with the selected value.
search for a record. The dialog box also contains up to two user-
definable buttons that you can program responses to. Deployment,
TwwLocateDialog displays a dialog box that lets the user search for a Documentation, and
record by entering a value and a field to match it against. The dialog Sample Code
box contains options to allow case-sensitive, and exact or partial Registered users are given a
matches. This component also contains two methods, FindFirst and royalty-free license to dis-
FindNext, that let you perform a behind-the-scenes search without tribute executable applica-
displaying the dialog box at all. Both TwwSearchDialog and tions they build using the
TwwLocateDialog are used by calling their Execute methods. InfoPower components.
Since InfoPower is a VCL
The wwDBLookupComboDlg
User Defined Combo-boxes component enables you to search library, there is no need to
TwwDBComboDlg is one of the more versatile visible components in for a record. distribute additional files
the InfoPower collection. This visible control is bound to a field and with your application. If you
works very much like a combo-box, except that you control what buy the source code, you can modify it and/or derive your
happens when the user clicks the component’s ellipsis (...) button. own components from InfoPower’s basic set. You can then use
InfoPower ships with an example that uses a TwwDBComboDlg these customized components in applications provided you do
component with a date field. When you click on the ellipsis button, not distribute them outside your company.
a calendar is displayed that lets you pick a date and fill in the field.
Woll2Woll’s documentation for InfoPower consists of 115
To program the ellipsis button, you add code to respond to the pages. This user’s manual contains instructions on how to
TwwDBComboDlg component’s OnCustomDlg event. The fol- install the software, descriptions of each component, and use-
lowing Object Pascal code fragment displays a calendar in ful examples of how to use each one. Since many of the
response to this event: InfoPower components are inherited from VCL components,
it is important to understand where and why the newer com-
procedure TForm1.wwDBComboDlg1CustomDlg(Sender: TObject); ponent diverges from the pre-defined behavior of its ancestor.
begin
wwCalendarComboDlg(Sender as TwwDBComboDlg); To this end, the section for each component lists any new,
end; modified, or obsolete properties.

Additional Lookup Dialogs Also in the documentation is a tips and techniques section
To round off its collection of that describes how to achieve common functionality. This
lookup components, information is also available in the on-line help system. Since
InfoPower includes the on-line help is integrated into Delphi’s IDE, the reference
TwwDBLookupComboDlg and is always conveniently available. A
TwwLookupDialog. These two final valuable reference is
components offer functional- InfoPower’s source code that is
ity similar to This wwDBLookupComboDlg com- available as a separate purchase. If
TwwDBLookupCombo ponent displays a calendar. you are interested in learning about
InfoPower is a collection of data-aware
because they let you display how InfoPower works, or how to components that enhance Delphi’s exist-
choices from a lookup table. What’s different is they let you make direct BDE calls, you should ing VCL components, including an
enhanced data grid, database filtering,
present the lookup table as a searchable grid in a dialog box buy this option. lookup combo-boxes, expanding memo
dialogs, and incremental search compo-
instead of a drop-down list. The dialog box can contain an nents. The package has a well-written
index selection combo-box and up to two optional command InfoPower ships with a series of user manual and a comprehensive collec-
tion of sample code. Source code is avail-
buttons that you can program responses to when they are small Delphi sample programs that able separately.
pressed. TwwDBLookupComboDlg is bound to a data field, just illustrate the features of each com- Woll2Woll Software
as TwwDBLookupCombo is. When the user clicks on the ellip- 1032 Summerplace Drive
ponent. Although installation of the San Jose, CA 95122
sis button, the dialog box containing the grid appears. sample programs is optional, I rec- Phone: (800) WOL2WOL, or
(408) 293-9369
ommend running through each one
TwwDBLookupDialog displays a similar dialog box, but is not Price: Introductory price US$149 expires
to get a quick overview of August 31, 1995; source code US$79;
bound to a data field. It’s a non-visual component just as InfoPower’s capabilities. By study- after August 31, US$199, with source
code at US$99 (30-day money-back
Delphi’s common dialog components, so you control it using ing each example, you can learn guarantee).
code. To display the dialog box, you call the component’s how to use InfoPower most effec- Free technical support is provided
Execute method. When the user is finished with the dialog tively in your application. In fact, via:
CompuServe: 76207,2541
box, you can query the component’s LookupTable property to prospective customers can obtain a Internet: [email protected]
Fax: (408) 287-9374
determine what record was selected. TwwDBLookupDialog is demonstration version, Voice: (408) 293-9369
very flexible because you can control exactly when the lookup InfoDemo.ZIP, from CompuServe

AUGUST 1995 Delphi INFORMANT ▲ 48


New and Used

(Informant Forum, Library 14) or at Woll2Woll’s World-


Wide Web address (http://www.webcom.com/~wol2wol/).
This demonstration version contains the same examples that
ship with InfoPower.

Conclusion
InfoPower provides capabilities essential to every professional
database developer. The components are complete and well
thought out, significantly enhancing the development process.
The documentation, help system, and sample code serve as a
very good tutorial in helping new users master the product.

Developers who want to build full-featured front-ends for


their database applications should take a serious look at this
product. The quality of the total package rivals or exceeds
many of the more established same-niche VBX products that
I’ve used to develop Visual Basic database applications.
Woll2Woll plans for future versions include many grid
enhancements, such as multi-selection rows, editable fixed
columns and linked fields, and spin edit support. ∆

Joseph C. Fung is a principal of Farpoint Systems Corporation, a NY/NJ-based con-


sulting firm specializing in developing traditional and client/server database appli-
cations with Delphi, ObjectPAL, and Visual Basic. He writes for Paradox Informant,
and is the author of Paradox for Windows Essential Power Programming. Mr
Fung is also the architect of ScriptView and AppExpert, two award-winning devel-
opment tools for Paradox. Currently, Mr Fung chairs an advisory board for the
Borland Developer Conference ’95. He can be reached at (201) 656-6561, on
CompuServe at 71121,2331, or via Internet at [email protected].

AUGUST 1995 Delphi INFORMANT ▲ 49


Te xt F i l e

Delphi Unleashed: Worth the Wait


The first books to appear after topics. The remainder of experience with Borland Pascal
the release of a new software Unleashed covers a wide variety will appreciate the comparisons
product typically whet readers’ of topics including OOP to Delphi, including how their
appetites, but leave them (object-oriented programming), object models differ. Those who
wanting more. Only later do component creation, exception rely heavily on Windows API
the major reference works handling, and a short primer on calls will learn how to easily
begin to appear. From Sams good programming techniques. include them in their Delphi
Publishing, Charles Calvert’s In general, there are many applications. And those fairly
Delphi Unleased is in this sec- things to like about this book. new to programming will bene-
ond category, and well worth Calvert does an excellent job of fit from the detailed explana- great addition to any pro-
the wait. Unleashed is a large, explaining the sometimes com- tions of control structures and grammer’s library.
satisfying “must read” for plex issues, making extensive use type declarations. — Cary Jensen, Ph.D.
Delphi developers. It is well- of analogies to assist the reader. Another plus for Unleashed is
written, detailed, and contains Calvert also shows consideration its many code examples includ- Delphi Unleashed by Charles
insights into Delphi that you for the more advanced reader, ed on the CD-ROM accompa- Calvert, Sams Publishing
will find nowhere else. suggesting which parts of the nying the book. (Macmilian Publishing) 201
While Unleased has some- book may be skipped, skimmed, In short, Delphi Unleashed West 103rd Street, Indianapolis,
thing for nearly everybody, or reviewed based on the read- is an important new resource IN 46290; (317) 581-3500
Parts II and III of this book er’s experience level. for Delphi developers. It cov-
will be particularly welcome The topics covered in ers a wide variety of topics, ISBN: 0-672-30449-6
for those new to the Pascal Unleashed are as varied as the and contains valuable insights, Price: US$45.00
language, or returning to it book is long. Programmers with hints, and tips that make it a 930 pages, CD-ROM
after a long absence. Unleashed
spends more than a third of its
900 pages covering the basics Putting it Together with Nuts & Bolts
of Object Pascal. These sec- matics professor, teams up with backgrounds. Unfortunately, I
tions begin with a discussion Strain, a former testing manag- found the typographic presenta-
of variables and types, contin- er for Visual Basic (VB) at tion of the tips interrupted the
ue into control structures, and Microsoft. They assume the flow of text. Each tip is preced-
end with a detailed look at reader has a working knowledge ed by a column-wide dotted
pointers, PChars, and linked of programming (in any lan- rule and followed by a page-
lists. The information con- guage) that enables them to wide solid rule. The rules create
tained here will be especially skip such topics as how to use too much visual separation
appreciated by anyone who loops and other common con- between the main-body para-
has tried to read the practically structs. They still cover the syn- graphs that precede and follow
indecipherable Object Pascal tax and the unexpected idiosyn- the tip. After reading a tip, I
Language Reference. crasies, but they don’t waste consistently was surprised to
Part IV of Unleashed contains Experienced programmers look- pages dwelling on material pro- return to the original subject
a serviceable introduction to ing for a quick jump start into grammers already know. rather than a whole new topic.
using Delphi for database appli- Delphi will welcome Delphi The book offers numerous The book begins with the
cations. Here readers learn the Nuts & Bolts for Experienced short tips. Icons in the margins expected basics: the Delphi
relationship between Programmers by Gary Cornell classify the tips as being of gen- environment, form design,
DataSource and DataSet com- and Troy Strain (Osborne eral interest, for VB, or Pascal components, menus, etc. By
ponents, and how to use these McGraw-Hill). I looked for- programmers. Pointing out how concentrating on the big pic-
to create forms that provide ward to seeing this title, having Delphi differs from VB and ture, on easily missed features of
access to databases. Included in often recommended Cornell’s Pascal is especially valuable for Delphi, and on unexpected
this section is a nice, but limit- earlier books on Visual Basic. In the many programmers coming “gotchas”, the early chapters
ed introduction to client/server Nuts & Bolts, Cornell, a mathe- to Delphi from one of those “Nuts & Bolts” , continued on page 51

AUGUST 1995 Delphi INFORMANT ▲ 50


TextFile

A Delphi Adventure in Three Easy Parts


Delphi Programming EXplorer several simple databases. This a great way to start your
by Jeff Duntemann, Jim section has a few editing errors, adventures in Delphi. Sign up
Mischel, and Don Taylor is a and some printed listings have for the trip. And be prepared
great way to learn Delphi pro- bugs that have been corrected for a good time!
gramming. At the same time, on the diskette, but they are — Tim Feldman
it’s a lot of fun to read. Jeff minor problems. By the end of
Duntemann is an excellent the section you’re ready to start Delphi Programming EXplorer
author, unsurpassed at explain- working on significant projects. by Jeff Duntemann, Jim
ing programming subjects in Part 3 of EXplorer is where Mischel, and Don Taylor,
an easy-to-follow manner. His the fun really starts. In “Ace Coriolis Group Books, 7339
editorials are the first thing I Breakpoint’s Database East Acoma Drive, Suite 7, ISBN: 1-883577-25-X
read each month when PC Adventure” Don Taylor pre- Scottsdale, AZ 85260; (800) Price: US$39.99
Techniques magazine arrives. sents a database design study. 410-0192, or (602) 483-0192. 627 pages, diskette
Mischel and Taylor also write In the form of a hard-boiled
for PC Techniques. When I detective novel! Ace is an ex- “Nuts & Bolts” (cont. from page 50)
learned they had teamed up to private investigator turned provide a wealth of information interface features” (toolbars, sta-
write EXplorer, I ordered a programmer, learning Delphi very quickly. The authors tus bars, common dialog boxes,
copy, sight unseen. I wasn’t dis- while trying to become sensi- devote little space to examples, MDI forms, drag-and-drop
appointed — it’s a winner. tive and politically correct (a but refer readers to Delphi’s operations, and help systems). I
EXplorer is written in three sort of Sam Spade for the sample programs. Similarly, suspect that many readers could
parts, and includes a diskette of 90s). As you follow Ace in his they urge readers to consult benefit from more depth on
source code and utilities. In Part struggles to deliver a demo to Delphi’s Help files for details of these topics.
1, Duntemann and Mischel an important customer, defeat less important component The biggest disappointment
alternate writing chapters. They his scornful competitor, and properties. was the final chapter “A Survey
use a “hands-on” approach that regain his lost love, you’ll The middle chapters cover of Database Features,” that runs
produces results quickly. actually learn important steps basic and advanced aspects of just eight pages. The authors
Chapters by Mischel guide you in the Rapid Application the Delphi language. I was acknowledge the brevity, but
through the mechanics of using Design (RAD) process. You’ll pleased by the emphasis on data plead that it would take a book
Delphi to create simple, inter- write a sophisticated applica- structures, including arrays, twice the size of Nuts & Bolts to
esting applications. In alternat- tion using Delphi database string lists, records, pointers, explain “any substantial part” of
ing chapters, Duntemann components. You’ll also learn etc. Objects are covered in a Delphi’s database programming
reviews the theory behind the how to add help to a project separate chapter, although per- power. Perhaps so, but such an
code. Both authors use personal using the supplied HelpGen haps more briefly than object- important topic surely deserves
anecdotes to tie the code and utility, and find out what hap- oriented programming (OOP) more than eight pages.
discussions to the real world. pens in Ace’s love life. newcomers may wish. If you already know how to
After several chapters, you’ll The book includes an The final portion of the program and want to learn
have enough experience and appendix on Delphi for book skims over a variety of what’s new in Delphi, Nuts &
confidence to experiment with Visual Basic users. It contains topics. Most of the material is Bolts will take you farther, faster
Delphi on your own. a brief review of the differ- helpful, and provides a good than most other books. This is
Duntemann and Mischel ences between Delphi and starting point for personal especially true if your back-
continue their team approach Visual Basic, instructions for exploration. However, these ground is in VB or Pascal. The
in Part 2. They don’t hold your installing and using an evalu- chapters seemed less complete quality of what’s provided is
hand as much, and the pace ation version of EarthTrek’s than the earlier sections. It excellent, but the brevity leaves
quickens. The theory and prac- Delphi Conversion Assistant, appeared as if the authors were you wishing for even more.
tice start to mix together, and and a short example of the working under a page-count — Larry Clark
there are some examples that conversion process. limit or a severe time deadline.
are not part of complete pro- With Delphi Programming The too-brief chapters include Delphi Nuts & Bolts for
jects. The subject matter is EXplorer, Duntemann, discussions of error and excep- Experienced Programmers by
more advanced: objects, files, Mischel, and Taylor have cre- tion handling (nine pages), test- Gary Cornell and Troy Strain,
printing, graphics, and the ated a rare combination of ing and debugging (11), and Osborne McGraw-Hill, 2600
beginnings of database pro- valuable content and refresh- working with files (18). Other Tenth Street, Berkeley, CA
gramming. The examples ing presentation. Palatable for short chapters deal with inter- 94710; (800) 227-0900.
include a file viewing utility, a experienced developers as well application communication ISBN: 0-07-882136-3
mortgage calculator, a graphics as newcomers — amusing (Clipboard, DDE, and OLE), Price: US$24.95,
toy like the “Spirograph”, and without being frivolous — it’s graphics, and “advanced user- 307 pages

AUGUST 1995 Delphi INFORMANT ▲ 51

You might also like