Delphi Users Guide For Windows
Delphi Users Guide For Windows
Delphi represents a brand new way to develop applications for Windows. It combines
the speed and ease of use of a visual development environment with the power,
flexibility, and reusability of a fully object-oriented language, the world’s fastest
compiler, and leading-edge database technology.
As a result, Delphi lets you build sophisticated client/server applications in record time.
Delphi includes support for creating stand-alone executable (.EXE) and dynamic-link
library (.DLL) files and local or networked database applications, as well as client/
server applications.
Installing Delphi
Delphi and its installation program are both Windows applications, so you must
already have Windows running to install Delphi. The installation program creates
directories as needed and copies files from the distribution disk to your hard drive.
The installation program is largely self-explanatory. The following steps tell you all you
need to know to install Delphi.
■ To install Delphi,
1 Start Windows if it is not already running on your computer.
2 Insert the Delphi CD into your CD-ROM drive.
3 Use Program Manager’s File|Run menu command or File Manager to run
\INSTALL\SETUP.EXE from the Delphi CD.
4 Follow the instructions presented by the installation program.
When the installation program finishes its work, it offers you the option of reading the
README.TXT file, which contains important last-minute information about Delphi. It’s
a good idea to read README.TXT before running Delphi for the first time.
Introduction 1
Documentation overview
Delphi includes complete documentation to help you learn to use the product quickly
and effectively.
The Delphi documentation consists of three parts:
• Printed manuals
• Online Help
• Interactive Tutors
Using Help
Delphi’s online Help provides a superset of the information presented in the printed
manuals. Use online Help to find
• Specific procedural information regarding programming tasks in Delphi
• The language definition of Object Pascal
• Reference material for the Visual Component Library and the Run-Time Library
Manual conventions
The printed manuals for Delphi use the typefaces and symbols described in Table
Intro.1 to indicate special text.
Table Intro.1 Typefaces and symbols in these manuals
Typeface or symbol Meaning
Monospace type Monospaced text represents text as it appears onscreen or in
Object Pascal code. It also represents anything you must type.
[] Square brackets in text or syntax listings enclose optional items.
Text of this sort should not be typed verbatim.
Boldface Boldfaced words in text or code listings represent Object Pascal
reserved words or compiler options.
Italics Italicized words in text represent Object Pascal identifiers, such
as variable or type names. Italics are also used to emphasize
certain words, such as new terms.
Keycaps This typeface indicates a key on your keyboard. For example,
“Press Esc to exit a menu.”
■ This symbol indicates the beginning of a procedure. The text
that follows describes a set of general steps for performing a
specified kind of task.
➤ This symbol indicates a specific action you should take, such as
a step in an example.
Contacting Borland
The Borland Assist program offers a range of technical support plans to fit the different
needs of individuals, consultants, large corporations, and developers. To receive help
with this product send in the registration card and select the Borland Assist plan that
best suits your needs. North American customers can register by phone 24 hours a day
by calling 1-800-845-0147. For additional details on these and other Borland services, see
the Borland Assist Support and Services Guide included with this product.
Introduction 3
4 Delphi User’s Guide
Part
I
Getting started with Delphi
Part I
The single chapter making up this part, “Introducing Delphi,” introduces the Delphi
integrated development environment (IDE), and discusses basic concepts and
techniques for creating Delphi applications.
Introducing Delphi
Chapter 1
1
Delphi is a component-based application development environment supporting rapid
development of highly efficient Microsoft Windows-based applications with a
minimum of coding. Many of the traditional requirements of programming for
Windows are handled for you within the Delphi class library, shielding you from
complicated, or merely repetitive programming tasks.
Delphi provides design tools such as application and form templates, so you can quickly
create and test your application prototype. Then, by using Delphi’s rich component set
and intuitive code generation, you can turn your prototypes into robust applications
that fit your business needs.
Delphi’s database tools enable you to develop powerful desktop database and client/
server applications and reports. You can view “live” data at design time, so you know
immediately whether your query results are what you want.
This chapter introduces the following topics:
• The Delphi programming environment
• Elements of the Delphi interface
• The Delphi development model
• Overview of Delphi projects
• Setting environment preferences
Starting Delphi
You can start Delphi the same way you start any Windows-based application:
• Double-click the Program Item for DELPHI.EXE that was created by the Install
program.
• Use File Manager to locate and double-click the DELPHI.EXE file (if you performed a
default installation, this file is located in your DELPHI\BIN directory).
• Choose Run from the Program Manager File menu, and specify the path to
DELPHI.EXE.
• Start Delphi from the command line: WIN DELPHI (assuming Windows is in your
path statement).
Figure 1.1 The Delphi programming environment
Component palette (Standard page shown; additional
SpeedBar component pages available by selecting page tabs)
Object
Inspector
Code Editor
Object
selector
Form
Forms are the focal point of nearly every application you develop in Delphi. You use the
form like a canvas, placing and arranging components on it to design the parts of your
user interface. Components are the building blocks of Delphi applications. They appear
on the Component palette, displayed in the top right-hand part of the screen (see
Figure 1.1).
You can think of a form as a component that can contain other components. Your
application’s main form and its components interact with other forms and their
components to create your application interface. The main form is your application’s
main interface; other forms can include dialog boxes, data entry screens, and so on.
You can resize the form and move it anywhere on your screen. A form includes
standard features such as
• Control menu
• Minimize and maximize buttons
• Title bar
• Resizeable borders
You can change these features, as well as other properties of the form by using the Object
Inspector to edit the form during design time—the time during which you are designing,
rather than running, your form. Properties define a component’s appearance and
behavior.
Form tools
Forms created in Delphi can be reused among Delphi projects, and can also be saved as
dynamic-link libraries (DLLs) so you can load them into projects built with other
applications such as C++, Paradox, dBASE, Visual Basic, and PowerBuilder.
Delphi provides several development tools that make generating productive forms and
reports easier than ever:
Component palette
Components (Standard-page components shown; Placeholders for additional
Left scroll arrow additional components available by clicking the page tabs) components
Components are the elements you use to build your Delphi applications. They include
all the visible parts of an application, such as dialog boxes and buttons, as well as those
that aren’t visible while the application is running, such as system timers or Dynamic
Data Exchange (DDE) servers.
Delphi components are grouped functionally on the different pages of the Component
palette. For example, components that represent the Windows common dialog boxes
are grouped on the Dialogs page of the palette.
You can create your own custom components and install them onto the Component
palette, making the Delphi environment fully extensible. There is no difference in
usability between the components you create yourself and those that ship with Delphi.
You can also install Visual Basic (VBX) controls and third-party components. And the
Component palette itself is configurable and scrollable, so you can select how you want
components to be displayed in the palette.
The specific components provided with Delphi are discussed in Chapter 2 and in online
Help under the search word “Component Palette.” For information about how to
configure the palette, see Chapter 2.
Properties
page
Events page
The Delphi Object Inspector enables you to easily customize the way a component
appears and behaves in your application. The properties and events of the component
that is selected in the form are displayed in the Object Inspector.
You use the Properties page of the Object Inspector to customize components you’ve
placed on a form (or the form itself), and the Events page to generate and navigate
among certain parts of program code, called event handlers. Event handlers are
specialized procedures.
■ To keep the Object Inspector visible at all times, right-click it and choose Stay On Top
from the SpeedMenu.
Object selector
The Object selector (the drop-down list at the top of the Object Inspector) displays the
name and type of every component in the current form, including the form itself. You
can use the Object selector to easily switch among components in the form, or to switch
back to the form.
Code Editor
Page tab
The Delphi Code Editor is a full-featured editor that provides access to all the code in a
given application project. The Code Editor includes many powerful features such as
Brief-style editing, color syntax highlighting, and virtually unlimited Undo. For
information about using the editor, refer to the online Help topic Code Editor.
SpeedBar
Select unit
from list Select form
Add file from list
Save project to project Run
Project Manager
Remove file
from project View unit View form
Add file to
project
Update
Project
status line
The Delphi Project Manager lists the files that make up your application, and enables
you to easily navigate among them. You can use buttons on the Project Manager
SpeedBar to generate new forms and units, to view files in the current project, and to
Menu Designer
Menu item
(Menu commands appear
below menu items)
The Delphi Menu Designer enables you to easily add menus to your forms. You open
the Menu Designer by double-clicking on a MainMenu or PopupMenu component
(found on the Standard page of the Component palette) after placing the component on
a form. Once the Menu Designer is opened, you can create your own custom menus, or
use the predefined menu templates provided with Delphi to insert ready-made menus
into your application.
The Menu Designer is discussed in more detail in Chapter 3.
Integrated debugger
Delphi provides a fully integrated debugger so you can debug your source code
without exiting the development environment. Your debugging sessions take place in
the same visual environment that Delphi provides. The debugger includes many
advanced features, including syntactic awareness, expression evaluators, watches,
conditional breakpoints, and the ability to view the call stack.
The integrated debugger is discussed in detail in Chapter 8.
ObjectBrowser
Browsing status line Back Show browsing history
Details
pane
The Delphi ObjectBrowser enables you to visually examine object hierarchies, units, and
global symbols your program uses. You need to compile your application with Symbol
Image editor
SpeedBar
Resource selector
window (Page tabs
provide selection
among bitmaps, Color palette
icons, and cursors)
Tool palette
The Delphi Image editor is a design tool that you can use to create and edit bitmaps,
icons, and cursors for display in your application. You can use any Windows-
compatible bitmap, icon, or cursor—those in the Image Library shipped with Delphi,
those you create in the Image editor, or third-party images you import for use in Delphi.
Note For more information about the Delphi Image Library, search online Help under Image
Library.
■ To view the Image editor, choose Tools|Image Editor.
Designing a form
Designing forms is as simple as arranging objects in a window. If you’re familiar with a
graphical user interface (GUI) environment such as Windows, then you already know
how to use the mouse to manipulate objects by selecting, moving, sizing, and so forth.
(If you are not familiar with these techniques, consult your Microsoft Windows
documentation.) In Delphi, the objects you manipulate are components, and the
window is the Delphi form.
This section demonstrates the following concepts:
• Creating a new form
• Adding components to the form
• Setting component properties
• Running the program
Page tabs
If you wanted the Caption property to change as the application runs, you would type
the appropriate code in the Code Editor. This is explained more fully under “Handling
events” on page 18, and in Chapter 2.
■ To modify a property at design time,
1 In the form, select the component whose property you want to change.
The Component List displays the name of the selected component.
2 From the Properties page of the Object Inspector, select the property that you want to
change.
3 Modify the property by entering a new value.
Most property changes you make at design time are reflected immediately in the form.
For more information about setting properties, refer to the online Help topic Setting
Properties.
➤ Change the Caption property for Form1 to 'My Demo'. Then change the Caption property
for Button1 to 'Color'. Notice that as you type, the Caption property for Form1 and
Button1 display their changing value in the title bar of the form and on the button.
Notice that the components in the compiled program behave as you would expect them
to. The button appears to “push in” when you click it, and you can resize and move the
form. Such behaviors are native to each component; you don’t have to program them.
Of course, nothing useful happens when you click the button in this form. That’s where
your code comes in.
In Delphi, you write code that specifies what your program should do when it detects
user interactions such as a button click, or a drag and drop. In programming terms, such
user interactions are called events.
➤ Close the running application by double-clicking the Control-menu box.
You can use the Object Inspector to generate an event handler for the form, or any
component you have on the form. When you do so, Delphi generates and maintains
parts of the code for you. For example, the following code is the initial “framework”
event handler that Delphi generates for the OnClick event of Button1 (the event that
occurs when the button is clicked) on Form1:
procedure TForm1.Button1Click(Sender: TObject);
begin
end;
The first line of the event handler names the procedure (TForm1.Button1Click) and
specifies the parameters it uses (this procedure uses only one: Sender of type TObject).
The code you insert between the begin..end block is executed whenever the OnClick
event occurs.
For this sample application, you’ll handle a button click.
■ To generate an event handler,
1 Select a component, then click the Events tab at the bottom of the Object Inspector.
2 Select an event, and double-click in the right (Value) column.
When you double-click the Value column for an event, Delphi generates an event
handler in the Code Editor, and places your cursor inside the begin..end block.
3 Inside the begin..end block, type the code that you want Delphi to execute when the
component receives the event.
ListBox1
Note The ampersand (&) character is used in button captions and menu items to provide
quick keyboard access to the button or menu item (by means of accelerator keys). This
technique is explained in more detail in Chapter 3.
Form
A blank Delphi project initially contains one unit (.PAS) file and one associated form
(.DFM) file. The .PAS file contains the Object Pascal source code for the form, and the
.DFM file contains binary code that stores the “image” of the form. Together these two
files make up the form. For every additional form in a project, there will be a .PAS and
.DFM file.
Project name
Uses clause
Form identifiers
Compiler directive
As you add new forms or units to your project, Delphi automatically adds the
appropriate code to the .DPR file.
Delphi added the identifier for the new unit, Unit2, its file name, UNIT2.PAS, and the
identifier for its associated form, Form2.
Unit identifier
Begins interface part of code
Uses clause
Form variable
declaration
Begins implementation
part of code
3 Add a button component to the form, while watching what happens to the type
declaration.
Figure 1.10 Modified type declaration
If you delete Button1 from Form1, Delphi deletes the button’s instance variable, but not
any associated methods. For more information, see Chapter 2.
Note No code is generated when you change a component’s design-time properties, because
those values are stored in the .DFM file. The only exception to this is the Name property,
as discussed previously. When you use the Object Inspector to change a component’s
Name property, Delphi changes its variable declaration for you to reflect the new name
in the underlying code. This is discussed in more detail in Chapter 5.
Gallery options
The check boxes in the Gallery group that appear at the bottom of the Environment
Options dialog box are some of the most important options because they control what
you see when you open a new form or a new project.
Note The exercises in this and subsequent chapters assume that the Forms Gallery option is
enabled, as it is by default when you install Delphi. However, if you share your
installation of Delphi, this option might have been disabled by another user. See
“Enabling the Gallery options” later in this section.
The Gallery is a collection of Form and Project Templates and Experts supplied with
Delphi. (Some versions of Delphi contain more Form Templates and Project Templates
than are illustrated in the following figures.) You can develop your own forms and
projects to serve as templates for your applications and add them to the Gallery, making
it easy to reuse forms, or even entire projects, in new applications. For information on
creating form and project templates see Chapter 3 and Chapter 4.
The Use On New Form and Use On New Project check boxes in the Gallery group box
control whether the Browse Gallery window is displayed when you create a new form
or project in the current or future Delphi work sessions.
Desktop Only
Choosing this option saves directory information, open files in the Code Editor, and
open windows.
Autosave Options
These options enable you to specify what files and options are automatically saved
when you test run your program from within Delphi, and when you exit Delphi.
Editor Files
Choosing this option saves all modified files in the Code Editor. The advantage of this
option is that changes to your code are saved whenever you test run your program.
Desktop
Choosing this option saves the arrangement of your desktop. Subsequent Delphi work
sessions display the same desktop as the current session.
Integrated Debugging
Enables the Delphi integrated debugger in the environment. Check this option unless
working exclusively with programs that have already been debugged.
Break On Exception
Choosing this option causes a running application to stop if an exception occurs and
displays the exception class, message, and location. This provides a means for you to
step through the exception handlers as if going through the code sequentially.
Minimize On Run
Choosing this option minimizes the Delphi IDE whenever you run an application from
within Delphi. The IDE returns to a normal state when the running application
terminates.
Compiling option
Delphi can display a dialog box showing the progress of the compiler as it compiles
your program. To enable this display, check the Show Compiler Progress check box in
the Environment Options dialog box. Enabling this option makes the Cancel button in
the Compiling dialog box available so you can cancel a compilation in progress.
Figure 1.14 The Compiling dialog box
Summary
This overview introduced the following concepts:
• Elements of the Delphi programming environment interface
• Overview of the Delphi development model, including
• Setting a component’s design time properties by using the Object Inspector
II
Fundamental skills
Part II
The chapters in this part present concepts and skills fundamental to creating Delphi
applications. These concepts and techniques are illustrated by simple but functional
examples that you can create.
The three chapters making up this part are
• “Using components and code”
This chapter explains the nature of Delphi components, where to find them on the
Component palette, how to place them on forms to create user interfaces, and how to
attach code to events associated with those components. Additional topics include
how to use the Component Expert to create custom components, how to add VBX
components to the Delphi Component palette, and how to customize the Delphi
Visual Class Library (VCL).
• “Building form and menus”
This chapter explains how to design and create forms for maximum reusability, both
within the same project and across multiple projects. Additional topics include how
to use the Delphi Menu designer to create and modify Form menus for both Single-
Document Interface (SDI) and Multiple-Document Interface (MDI) applications.
• “Managing projects, files, and directories”
This chapter explains how to use the Delphi Project Manager to view and administer
the files making up your Delphi project. Additional topics include how to set project
and programming environment options, and how to streamline your programming
tasks by using Delphi templates.
Delphi components
The pages of the Component palette display the components Delphi provides to enable
you to quickly develop powerful and diverse applications. A large part of interface
design consists of using these components to customize the forms that make up your
application.
Delphi components include both visual and nonvisual types. Visual components appear
essentially the same in your form at design time as they do at run time. Nonvisual
components, on the other hand, are not visible on the form at run time. The MainMenu
and Timer components are two examples of nonvisual components. The MainMenu
component appears as an icon in your form at design time to give you access to the
Menu Designer; but at run time, only the menu you’ve designed is visible, not the
Y FileListBox Provide a list box that displays the files in the current
directory, and enable users to scroll among them at run
time.
Y DirectoryListBox Provide a list box that displays the directories on the
current drive, and enable the user to switch among them
at run time.
Y DriveComboBox Provide a combo box that displays the current drive, and
enable the user to choose a different drive from the drop-
down list at run time.
Y FilterComboBox Provide a combo box that displays the current file filter
(for example, *.*), and enable the user to select from a list
of available filters at run time.
Y MediaPlayer Display a VCR-style control panel for playing and
recording multimedia video and sound files.
Y OLEContainer Create an Object Linking and Embedding (OLE) client
area in the form.
N DDEClientConv Establish a client connection to a Dynamic Data Exchange
(DDE) server application.
N DDEClientItem Specify the (client) data that will be transferred during a
DDE conversation.
N DDEServerConv Establish a server connection to the DDE client
application.
N DDEServerItem Specify the server data that will be transferred during a
DDE conversation.
Note The components on the VBX and Samples page are not included in the Delphi Visual
Component Library (VCL). They are provided as examples only, and are not formally
documented as part of the core product. All components in the VCL are fully
documented in online Help. For more information, press F1 with a component selected
in the form.
Property Value
Name AboutBox
Caption About
BorderStyle bsDialog
Position poScreenCenter
Changing BorderStyle to bsDialog removes the form’s Minimize and Maximize buttons
and makes its borders non-resizable. Changing Position to poScreenCenter ensures that
the dialog box appears in the center of the screen. Note that these changes become
visible at run time, not design time.
■ To resize a single component, select the component on the form, and drag a sizing
handle until you are satisfied with the component’s size.
When you release the mouse button, the component is redrawn in the new size.
■ To resize multiple components,
1 Select the components you want to resize as a group.
2 Choose Edit|Size to display the Size dialog box.
3 Select appropriate sizing options, then choose OK.
Grouping components
Besides the form itself, Delphi provides several components—the GroupBox, Panel,
Notebook, TabbedNotebook, and ScrollBox—that can contain other components. These
are often referred to as container components. You can use these container components to
group other components so that they behave as a unit at design time. For instance, you
might group components, such as speed buttons and check boxes, that provide related
options to the user. You often use container components such as the Panel component to
create customized tool bars, backdrops, status lines, and so on.
For more information about creating tool bars and status lines, see Chapter 12, or search
online Help under “tool bars” or “status lines.”
Aligning components
You can align components relative to each other, or relative to the form. Once you select
the component(s) you want to align, you can use the Alignment palette or the
Alignment dialog box to set the alignment. When aligning a group of components, the
first component you select is used as a guide to which the other components are aligned.
■ To align components by using the Alignment palette,
1 Select the component(s).
2 Choose View|Alignment Palette.
The Alignment palette appears.
Form grid
By default, both the grid and its Snap To Grid option, which causes the left and top sides
of each component to always align with the nearest grid markings, are enabled at design
time. You can, however, choose to disable the Snap To Grid option, or disable the grid
altogether.
You can also modify the granularity of the grid—that is, how far apart the grid dots
appear.
■ To set form grid options, choose Options|Environment to display the Preferences page
of the Environment Options dialog box.
The next step in creating the About box involves setting properties for the components
you’ve just arranged.
➤ Change the Name property for all the components in the form, as specified in Table 2.9.
Notice that as you move from component to component, the Name property remains
selected in the Object Inspector.
➤ Set the remaining properties, as noted, for BackgroundPanel, Comments, and OKButton.
You’ll be using Form2 later in this example to open the dialog box at run time.
➤ Change the name for Form2 to MainForm.
Loading an image
You can use the Image component to load a picture into your form at design time.
■ To load a picture into a form,
1 Add an Image component to your form.
2 In the form, double-click the Image component.
5 Choose OK to accept the image you’ve selected and exit the Picture Editor dialog box.
Or, repeat steps 3 through 5 to choose another picture.
Your image appears in the form at design time.
➤ Load an image file from the Delphi Image Library into the Image component in the
About box. (For more information about the Image Library, search online Help under
Image Library.)
Figure 2.14 About box with image
Each file must have a unique prefix, even though their extensions can be different. For
example, if you specify About as the file name for both the form and project file, Delphi
displays the following error message:
The project already contains a module named About.
If you see this error message, Delphi won’t save the project file (or whichever file you
named secondly). Simply rename the file by saving it again with a different name.
6 Click OK.
Clicking OK closes the dialog box automatically because, at design time, you set the
button’s Kind property to bkOK and the border style to bsDialog.
Note The Title property for an application, which is displayed when the application is
minimized as an icon, defaults to the name of the project (.DPJ) file. However, you can
change this property by means of the Application page of the Project Options dialog
box. For more information, see Chapter 4.
It’s a matter of personal preference whether you load the picture, or other values, into
the About box at run time or design time. If you want to share the About box as a
standardized form, you’ll probably want to complete it at design time as nearly as
possible before making it available to other developers or users.
For more information about sharing forms and projects, see Chapter 3 and Chapter 4.
Summary
This chapter has presented the following topics, in the context of developing a reusable
About box:
• The Delphi components and the pages of the Component palette on which they can
be found
• Adding and manipulating components in your forms
• Setting component properties, both at design time and at run time
• Working with code to generate, locate, and modify event handlers
• Customizing the Delphi Visual Component Library by using the Component Expert,
by writing your own customized components, or by adding Visual Basic (VBX)
components
Sharing forms
Before you begin designing and building the forms for your applications, think about
whether these forms will be available to other developers or users. Delphi is designed
around the principle of reusable components, and this encompasses larger elements
such as forms or even entire projects.
The easiest way to share a form is simply to add an existing form to a project. The About
box you created in Chapter 2 is an example of a form that’s broadly reusable. Delphi
provides the About box as a Form Template for just that purpose. Form Templates are
predesigned forms that you can easily reuse in your projects.
When you share forms among projects, there are several considerations to keep in mind:
• As discussed in Chapter 1, to make the forms you add visible to other forms in the
project, you need to add their unit identifier to the uses clause of those other forms.
• When forms reference each other, you need to avoid creating a circular reference.
• When you modify a shared form, the modifications will show up in every project that
uses the form, not just the project where the form was originally created.
These considerations are discussed in more detail in the sections that follow.
2 On the Templates page, use the arrow keys or the mouse to select the template you
want to add, and choose OK.
Delphi adds a copy of the template form and its associated unit file to the project you
have open. You can now use this form the way you would any form in a project. You
2 In the View Form dialog box, select the form to which you want to give focus, then
choose OK.
■ To switch among units in a project,
1 Choose View|Units.
2 In the View Unit dialog box, select the unit you want to view, then choose OK.
You can also use the Delphi Project Manager to navigate among the units and forms in
your project. For more information, see Chapter 4.
Building forms
Delphi provides you with tools for building the forms that will make up your
application’s user interface. By using the Browse Gallery, simple function calls, and
Delphi components, it’s easy to create a wide variety of forms, from the simplest to the
most complex.
One of the most common ways that Windows-based applications interact with users is
through dialog boxes. Dialog boxes supply information about the application, and in
most cases accept input from the user. The About box is an example of the most simple
kind of dialog box. It doesn’t accept any input from the user (other than a button click),
but it does provide useful information. A message box that displays a warning or error
message is also a kind of dialog box.
More intricate dialog boxes require input from the user before the application can
continue. Delphi provides many such fully designed dialog boxes as components, and
you can also develop your own custom dialog boxes by using Delphi components.
ShowMessage procedure
The ShowMessage procedure is the simplest way to display a brief message to the user.
The syntax of the procedure is
ShowMessage(const Msg: string);
This procedure displays a modal dialog box containing the text you specify in the Msg
parameter and an OK button that closes the dialog box.
➤ To display a message box with the ShowMessage procedure, try this:
1 Create a new blank project and place a Button component on Form1.
2 In the button’s OnClick event handler, write the following code:
ShowMessage('Delphi delivers!');
When you run the program and click the button, a modal dialog box appears with the
name of the executable file in the title bar, the text from the Msg parameter, and an OK
button, as shown in the following figure.
Figure 3.2 Example ShowMessage message box
MessageDlg() function
The MessageDlg function displays a message box that contains text you specify, and
optionally, various captions, symbols, and buttons.
Here is the syntax of the function:
function MessageDlg(const Msg: string; AType: TMsgDlgType; AButtons: TMsgDlgButtons;
HelpCtx: LongInt) : Word;
The following table summarizes what each parameter specifies. See online Help for
detailed information regarding each parameter.
Table 3.1 MessageDlg parameters
Parameter name Specifies Comments
Msg Text displayed in the dialog box If you omit this parameter, no text appears
in the dialog box.
AType Caption on title bar, and If you omit this parameter, no caption
accompanying symbol in dialog box appears on the message box title bar.
AButtons Type of button(s) in the dialog box If you omit this parameter, no buttons
appear in the box.
HelpCtx Link to a Help topic Not required.
You need to pass an integer into the HelpCtx parameter even if you don’t have an
application Help file. In this case, pass 0 (zero). If you do have an application Help file,
Note MessageDlg displays the message box in the center of the screen by default. You can use
the MessageDlgPos function to create a message box that appears at a screen location you
specify.
For more information about MessageDlg and MessageDlgPos, look up the references in
online Help and see the Help topic Displaying a Message Box.
Note Changing these settings doesn’t change the design-time appearance of the form; these
property settings become visible at run time.
Note that setting the Kind property also sets the ModalResult property, discussed
previously, in every case except bkCustom, bkHelp and bkClose. In these cases,
ModalResult remains mrNone and choosing the button doesn’t automatically close the
dialog box.
3 In the Controls list, select a component, and press the appropriate arrow button (Up
or Down), or drag the component to its new location in the tab order list.
4 When the components are ordered to your satisfaction, choose OK.
Using the Edit Tab Order dialog box changes the value of the components’ TabOrder
property. You can also do this manually, if you want.
■ To manually change a component’s TabOrder property,
1 Select the component whose position in the tab order you want to change.
2 In the Object Inspector, select the TabOrder property.
3 Change the TabOrder property’s value to reflect the position you want the component
to have in the tab order.
Note The first component in the tab order should have the TabOrder value of 0.
Keep in mind the following points when manually setting your tab order (you needn’t
be concerned with these points if using the Edit Tab Order dialog box):
• Each TabOrder property value must be unique. If you give a component a TabOrder
value that has already been assigned to another component on this form, Delphi
renumbers the TabOrder value for all other components accordingly.
➤ To demonstrate how MDI parent forms contain child forms, try the following.
1 Start a new, blank project and add a new, blank form.
2 Set the FormStyle property for Form1 to fsMDIForm, and for Form2 to fsMDIChild.
3 Add a Panel component to Form1, and change its Alignment property to AlTop.
4 Add a SpeedButton component to the panel, and generate the following OnClick
event handler for it:
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Form2.Show;
end;
5 Add Unit2 to Unit1’s uses clause.
6 Run the program, and click SpeedButton1.
Form2 opens inside Form1.
Figure 3.10 Sample MDI child and parent forms
You can resize and move either form, but the child form always stays within the
borders of the parent.
Here are some rules about MDI parent and child forms:
• The MDI parent form must always be the application’s main form.
If the MDI parent form isn’t specified as the application’s main form, the application
won’t be correctly compiled.
Accelerator key
Separator bar
Keyboard shortcut
A MainMenu component creates a menu that’s attached to the form’s title bar. A
PopupMenu component creates a menu that appears when the user right-clicks in the
form. Pop-up menus do not have a menu bar.
■ To open the Menu Designer, select a menu component on the form, and then choose
from one of the following methods:
• Double-click the menu component.
• From the Properties page of the Object Inspector, select the Items property, and then
either double-click [Menu] in the Value column, or click the ellipsis (...) button.
The Menu Designer appears, with the first (blank) menu item highlighted in the
Designer, and the Caption property highlighted in the Object Inspector.
Building menus
You add a menu component to your form, or forms, for every menu you want to include
in your application. You can build each menu structure entirely from scratch, or you can
start from one of the Delphi predesigned menu templates.
This section discusses the basics of creating a menu at design time. For more
information about Delphi menu templates, see “Using menu templates” on page 106.
As with the menu component, Delphi adds any menu item names to the form’s type
declaration, and those names then appear in the Component list.
Menu item on
the menu bar
Menu item in
a menu list Nested menu item
For more information about the Menu Designer SpeedMenu, see the online Help topic
Menu Designer SpeedMenu.
This dialog box lists all the menus associated with the form whose menu is currently
open in the Menu Designer.
3 From the list in the Select Menu dialog box, choose the menu you want to view or
edit.
■ To use the Object Inspector to switch among menus in a form,
1 Give focus to the form whose menus you want to choose from.
2 From the Component list, select the menu you want to edit.
3 On the Properties page of the Object Inspector, select the Items property for this
menu, and then either click the ellipsis button, or double-click [Menu].
3 Select the menu template you want to insert, then press Enter or choose OK.
This inserts the menu into your form at the cursor’s location. For example, if your
cursor is on a menu item in a list, the menu template is inserted above the selected
item. If your cursor is on the menu bar, the menu template is inserted to the left of the
cursor.
■ To delete a menu template,
1 Right-click the Menu Designer window.
The Menu Designer SpeedMenu appears.
2 From the SpeedMenu, choose Delete Templates.
(If there are no templates, the Delete Templates option appears dimmed in the
SpeedMenu.)
The Delete Templates dialog box opens, displaying a list of available templates.
Figure 3.18 Delete Templates dialog box for menus
4 In the Template Description edit box, type a brief description for this menu, and then
choose OK.
The Save Template dialog box closes, saving your menu design and returning you to
the Menu Designer window.
Note The description you enter is displayed only in the Save Template, Insert Template, and
Delete Templates dialog boxes. It is not related to the Name or Caption property for the
menu.
Summary
This chapter has presented the following topics:
• Sharing forms with other units, both in the same project and in other projects
• Using the Browse Gallery to add Form Templates to your project
• Viewing forms and units
• Designing forms, including setting design-time and run-time properties, specifying
the tab order, and setting focus
• Adding and saving forms as ASCII
• MDI and SDI forms
• Creating form menus, including how to use the Menu Designer to create and name
menu items, specifying accelerator keys and keyboard shortcuts, creating nested
menus, and moving menu items
• Setting menu properties through the Object Inspector
• Using the Menu Designer SpeedMenu
• Using and saving menu templates
• Dynamically adding menu items
• Merging menu items
• Importing resource (.RC) files
• Changing the project main form designation
• Controlling the auto-create order of forms
What is a project?
The Delphi application development process centers around the concept of projects. A
Delphi project is a collection of all the files that together make up a Delphi application (or
distributable library). Some of these files are generated as you work on a project at
design time. Others are created when you compile the project source code.
Project directories
Normally, you should store each Delphi project you create in its own directory. If you
begin a project using any Project Template other than the Blank Project template, Delphi
prompts you for a directory path and then (if necessary) creates the specified directory
for the project. If you begin with the Blank Project template, Delphi saves it by default in
the \BIN directory, unless you specify otherwise. To avoid cluttering this directory, and
potentially overwriting files, create the project directory from the Windows operating
environment before saving the new project for the first time. (See “Beginning a project
with a Project Template” on page 122 for more information about Project Templates.)
{$R *.RES}
begin
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Environment options
The settings in the Environment Options dialog box affect all Delphi projects. This
dialog box contains several pages of options that you can change to customize your
installation of Delphi. Some of the settings affect the behavior of Delphi when you open
a new project, or add new forms and units to an open project. This section covers those
particular settings.
■ To open the Environment Options dialog box, choose Options|Environment.
For more information on the Environment Options dialog box, see Chapter 1 or online
Help.
Environment preferences
The options on the Preferences page have the most impact on what occurs when you
open a new project, reopen an existing project, or add forms and units to an open
project.
Autosave options
The Autosave options are Editor Files and Desktop. The settings of these options affect
what you see when you start Delphi.
Gallery
The Gallery check boxes specify whether Delphi displays the Browse Gallery dialog box
when you choose File|New Project or File|New Form.
When checked,
• Use On New Form displays the Browse Gallery dialog box whenever you choose
File|New Form.
• Use On New Project displays the Browse Gallery dialog box whenever you choose
File|New Project.
If you check an option that causes the Browse Gallery dialog box to be used, its
appearance and defaults are controlled by the settings specified in the Gallery Options
dialog box.
Gallery options
The settings in the Gallery Options dialog box affect the behavior of Delphi when you
begin a new project or create a new form in an open project. This is where you specify
• Default Project. The Project Template or Expert to be used whenever you open a new
project.
• Default New Form. The Form Template Form Expert to be used when the Gallery is
disabled in the environment and you open a new form.
• Default Main Form. The Form Template used as the main form for a blank project
only.
■ To open the Gallery Options dialog box, choose Options|Gallery.
Project options
The settings in the Project Options dialog box affect only the current open project. If you
modify any of the defaults, a configuration file with a file extension .OPT is created in
the project directory the next time you save the project. When you reopen the project in
future work sessions, the project options, as saved in the .OPT file, are in effect.
■ To display the Project Options dialog box, choose any of these methods:
• In the Project Manager, choose the Options button on the SpeedBar.
• In the Project Manager, choose the Options SpeedMenu command.
• Choose Options|Project from the Delphi menu bar.
The next sections point out the options in the Project Options dialog box that pertain to
project management. Detailed information for each option in the dialog box can be
found in online Help.
Form options
The options on the Forms page of the Project Options dialog box enable you to change
the form designated as the project’s main form, and to control the creation order of
forms at run time. For more information see Chapter 3.
Title
The text you enter here appears below the application icon when you minimize the
running application. If no title is specified, the minimized application displays the file
name of the .EXE file.
Help file
If you have created a Windows Help (.HLP) file for the project, you “connect” it to the
application by specifying it in the Help File edit box. Either type a file name or use the
Browse button to select an existing Help file.
At run time, the Help file name (and path if it exists) is passed to the Windows
WINHELP.EXE, which attempts to load your help file and access the context topic if
appropriate. For further information, consult your Windows Help documentation, or
the online Help file, “Creating Windows Help.”
Caution Be aware that the Help file for your distributed application might not reside in the same
location, relative to the executable file, as it does on your development system. Avoid
specifying a drive name unless you know for certain that the finished application’s Help
file will always reside on a drive with that name.
Consult your Windows Help documentation for further information on how
WINHELP.EXE attempts to locate Help files.
Icon
Delphi supplies a default icon for all projects, which appears whenever the running
application is minimized, or when the application’s .EXE is specified in creating a
program item for the Windows Program Manager. You’ll probably want to use a
different icon for your applications. The Delphi Image Library supplies some icon files
that you can use directly or modify by using the Delphi Image editor. You can specify
any standard Windows icon file (.ICO) residing in any location. The specified icon is
compiled into the project’s executable file.
Compiler page
The options on this page enable you to specify compiler options. Modified settings affect
only the current project unless the Default box is checked. Checking the Default box
preserves the settings on this page as the default compiler settings for all new projects
(see “Default check box” on page 127).
For information on the individual settings on this page, see online Help.
Linker page
This page enables you to specify how the link options are configured. The two options
that relate to project management are Include TDW Debug Info and the Default check
box.
As shown in the preceding figure, the main elements of the Project Manager window
are
• The SpeedBar
• The project status bar
• The project file list
The Project Manager also has a SpeedMenu which you can display by right-clicking
anywhere inside the window.
Files residing in a
subdirectory of the current
project directory
Notice how this project’s directories are structured. The project directory contains only
project source and configuration files, and a \BIN directory for compiled output and
a \FORMS directory for form unit and graphical form (.DFM) files were created. This
structure is purely optional—storing all these files in the project directory
(D:\AR_DIV1) would work equally well.
In the Path column, observe that
• Files residing in the project directory do not display any path information.
• Files in subdirectories beneath the project directory appear with no preceding
backslash (\) character.
• Files in other locations display full path information. In this case, the ARSplash unit
resides on a different drive. If it resided on the same drive as the project directory, the
path column would display the information as \SPLASH\.
Using the Project Manager is highly recommended because it enables you to track the
location of everything in your project.
Saving a project
This section explains how to save an open project to the directory created to store it (that
is, the project directory).
Note If the project was begun from a Project Template, the Gallery selection process creates
the project directory. Otherwise, Delphi saves projects by default to the \BIN directory,
unless you specify otherwise.
■ To save all open project files to the project directory, use one of the following methods:
• Choose File|Save Project.
• Choose the Save Project button on the Delphi SpeedBar.
• Choose the Save Project command on the Project Manager SpeedMenu.
From here, the save process for projects varies somewhat depending upon whether or
not the project has been saved.
Subsequent saves
If you have previously saved the project, all open files that reside in the project directory
are saved to disk if they have been modified.
If you have opened any new forms or units in the project since the last save, the Save
Unit As dialog box appears and prompts you to name those unit files before saving
them.
The .DPR project file is then updated to reflect any new units and any newly shared files
that you might have specified for the project to use.
If this occurs, respond OK to the error message box and supply a different name for the
.DPR file in the Save As dialog box.
As with unit files, Delphi supplies a default name, PROJECT1.DPR, for the unit source
code (.DPR) file. Again, you should supply a more meaningful name when saving the
file for the first time.
All unit and project file names must conform to DOS naming conventions.
Saving files
You can save individual files in a project, or non-project files (such as text files) that you
may have open in the Code Editor. To save a file, it must be open.
■ To save an individual file,
1 Bring the file to the topmost level of the Code Editor by selecting its tab.
2 Choose File|Save File. If this is the first time you’ve saved the file, you’re prompted
to name it.
3 If necessary, name the file and choose OK.
Delphi saves the file.
■ To save a file under a different name or location,
1 Bring the file to the topmost level of the Code Editor by selecting its tab.
2 Choose File|Save File As.
The Save File As dialog box appears.
3 Specify the new file name, or location, or both, and choose OK.
Delphi saves a copy of the file under the name and location you specify.
Note This changes the name of the file, and if it is already part of the project, includes the
file with the new name in the project. The older unit name still exists as a file but isn’t
included in the project any longer.
You could back up this entire project simply by copying the directory tree to another
location. If you open the project at the backup location, all the project files that reside
within that structure are present, and the project will compile.
If this project uses files that reside outside this tree, the project might or might not
compile at the backup location. Check the Project Manager’s file list to see if these
outside files are accessible from the backup location. If they are, the project will compile.
If other backup processes already preserve these outside files, then there is probably no
need to make separate backup copies of them in the backup project directory.
Status bar
displays message
Unit with error
comes to the top
Compiling a project
■ To compile all the source-code files that have changed since the last time you compiled
them, choose Compile|Compile from the Delphi menu bar.
When you choose this command, this is what happens:
• The compiler compiles source code for each unit if the source code has changed since
the last time the unit was compiled. This creates a file with a .DCU (Delphi Compiled
Unit) extension for each unit.
If the compiler can’t locate the source-code file for a unit, the unit isn’t recompiled.
• If the interface part of a unit’s source code has changed, all the other units that
depend on it are recompiled.
To learn about the interface section of a unit, see “Unit source code (.PAS) files” on
page 119.
• If a unit links in an .OBJ file (a file containing assembly language code), and the .OBJ
file is newer than the unit’s .DCU file, the unit is recompiled.
• If a unit contains an include (.INC) file, and the include file is newer than the unit’s
.DCU file, the unit is recompiled.
Building a project
■ To compile all the source-code files in your project, regardless of when they were last
compiled, choose Compile|Build All from the Delphi menu bar.
The result of this command is similar to that of the Compile|Compile command, except
that all units in the project are compiled, regardless of whether or not they have changed
since the last compile. This technique is useful when you are unsure of exactly which
files have or have not been changed, or when you simply want to ensure that all files are
current and synchronized.
Running a project
You can test run a project from within Delphi, or you can run the compiled .EXE file
from the Windows operating environment without having to run Delphi.
■ To compile and then run your application from within Delphi,
• Choose Run|Run command from the Delphi menu bar.
• Choose the Run button on the Delphi SpeedBar.
These actions are identical to choosing the Compile|Compile command, except that
Delphi runs your application immediately if the compile operation succeeds.
III
Programming topics
Part III
The chapters in this part discuss how to program using the Object Pascal language.
The four chapters making up this part are
• “Writing Object Pascal code”
This chapter explains how to write code to create Delphi applications.
• “Programming with Delphi objects”
This chapter explains what you need to know about objects and how to use them to
create Delphi applications.
• “Writing robust applications”
This chapter explains how to anticipate, recognize, and handle exceptions in your
Delphi applications.
• “Using the integrated debugger”
This chapter explains how to debug Delphi applications using the Delphi integrated
debugger.
Coding style
As you prepare for writing your first code statements, you should realize that it doesn’t
matter to the compiler how you space, indent, or capitalize your Object Pascal code, or
how you break lines of code to continue on the next line. As long as the code is
syntactically correct, the compiler can handle it properly. For example, this code
compiles just fine:
PROCEDURE
TFORM1.
Button1CLICK(SENDER :
TOBJECT);begin
Edit1.Color
:=
CLRED;END;
You would probably find this version of the event handler easier to read, however:
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Color := clRed;
end;
Choose a code indentation and capitalization style, and break lines of code where you
need to, so that your code is easy for you and others to read.
➤ Create an event handler for the OnClick event of the color grid:
Declaring identifiers
Identifiers are names you give to any part of a Delphi application, including variables,
types, procedures, functions, methods, and so on. (All identifiers are italicized in the
Delphi books, except in the code examples.) Object Pascal requires that you declare
identifiers before using them in your code.
If you haven’t used a compiled language before, you might wonder why it is necessary
to declare identifiers before you use them. As with all compiled languages, the compiler
must be given explicit information about the identifiers before the compiler can create
executable code that uses them.
The compiler can then check your code to ensure that the values you assign to variables
or properties are of the correct type. If they aren’t, Delphi displays a syntax error
message, so you can correct the problem. Languages that aren’t compiled can’t protect
you from assigning a value of a wrong type, a common programming mistake. Object
Pascal is known as a strongly typed language.
Also, because Object Pascal is a compiled language, your Delphi applications will run
much faster than applications you build with an interpreted language. Declaring
Declaring variables
A variable is a name in code that stands for a memory address, the contents of which
can change as the code runs. You need to declare a variable before using it. There are
two steps in declaring a variable:
1 Naming a variable
2 Giving a variable a type
Naming a variable
When you declare a variable, you need to select a name for it. You should try to select a
name that reminds you of the variable’s purpose, so your code is easier to read. For
example, Day, Name, and Total are more memorable names than X, Y, and Z.
Beyond choosing meaningful names for your variables, you should remember a few
rules that apply to variables and all other identifiers.
• Identifiers can be up to 63 characters in length.
If your identifiers are longer than 63 characters, the compiler ignores the extra
characters.
• Identifiers must begin with either a letter or an underscore (_) character.
• Subsequent characters can be letters, underscores, or the digits 0–9.
• Identifiers can’t contain any other symbols, such as $, %, *, and so on.
For example, identifiers called Do@Noon or Gross%Return result in a syntax error.
• You cannot use an Object Pascal reserved word for naming an identifier.
Reserved words have special meaning to the compiler. If you use one of these
reserved words to name an identifier, Delphi displays an error message. You can find
a list of Object Pascal reserved words in online Help under the Reserved Words topic.
All reserved words are boldfaced in the Delphi documentation.
• Avoid using identifiers already defined in the Object Pascal language to name your
identifiers.
For example, the words Boolean and Integer are predefined data types (see the section
“Data types” on page 156 to read about predefined data types). You can use either of
these words to name a variable without generating an error message, but if you do,
you won’t be able to use the Boolean and Integer types in your code.
Data types
Object Pascal has several data types built into the language. You can create variables of
any of these predefined types. The following table lists the predefined data types:
Table 5.1 Object Pascal predefined data types
Category Data type Description
Integer Integer Numbers without a fractional part, within the range of –32768 to 32767.
Requires two bytes of memory.
Shortint Numbers without a fractional part, within the range of –128 to 127. Requires
only one byte of memory.
Longint Numbers without a fractional part, within the range of –2147483647 to
2147483647. Requires four bytes of memory.
Byte Numbers without a fractional part, within the range of 0 to 255. Requires one
byte of memory.
Word Numbers without a fractional part, within the range of 0 to 65535. Requires
two bytes of memory.
Real Single A number that can contain a fractional part with 7–8 significant digits.
Requires 4 bytes of memory. Available only when the 8087/80287 option
{N+} is on. (Refer to Real Types in online Help for the range of each real
type.)
Double A number that can contain a fractional part with 15–16 significant digits.
Requires 8 bytes of memory. Available only when the 8087/80287 option
{N+} is on.
Extended A number that can contain a fractional part with 19–20 significant digits.
Requires 10 bytes of memory. Available only when the 8087/80287 option
{N+} is on.
Comp A number that can contain a fractional part with 19–20 significant digits that
requires 8 bytes of memory. Available only when the 8087/80287 option
{N+} is on.
Real A number that can contain a fractional part with 11–12 significant digits.
Requires 6 bytes of memory. Use Real only for compatibility with earlier
Borland Pascal releases; otherwise use Double or Extended.
Boolean Boolean Can contain the values of True or False. Occupies one byte of memory.
Char Char An ASCII character.
String string A sequence of up to 255 ASCII characters.
Pointer Pointer An untyped pointer, that is, a pointer that doesn’t point to any specific type.
PChar PChar A pointer to a null-terminated string.
Besides the predefined data types, you can define your own data types. For many
Delphi applications, the predefined data types are sufficient. This chapter, however, has
already discussed the use of a user-defined data type. The Color property is of type
Declaring constants
While variables contain values that can change as your application runs, constants
contain values that can’t change. Constants are given a value at the time they are
declared.
Just as variables are declared in a variable declaration, constants are declared in a
constant declaration. A constant declaration begins with the reserved word const. This
example declares three constants:
const
Pi = 3.14159;
Answer = 342;
ProductName = 'Delphi';
Pi, Answer, and ProductName are all constant names that describe the value of the
constant. The actual value of the constants, which can’t change while the application
runs, are 3.14159, 342, and ‘Delphi’, respectively. When naming constants, follow the
same rules for naming variables and other identifiers given on page 154.
Calling procedures
Perhaps you’ve noticed that all event handlers begin with the reserved word procedure.
All event handlers are procedures, subroutines that divide the logic of your application
into manageable chunks. Each event handler contains just the code you want executed
when the event occurs.
■ To use an existing procedure, type the name of the procedure as a statement in your
code. This is called “calling a procedure.”
For example, the memo control has a CutToClipboard method that removes the text the
user has selected within the memo control and stores it in the Clipboard object. Because
this functionality is built into the method, you need to know only what the method does
and how to use it. This is how you call the CutToClipboard method of a memo control
named Memo1:
Memo1.CutToClipboard;
➤ Start by opening a new project (choose the Blank form template, if necessary) and
adding a memo control and four buttons to a form.
➤ Use the Object Inspector to change these property settings:
• Name the buttons Cut, Copy, Paste, and ClearAll by changing their Name properties.
Be sure you change the Name property and not the Caption property, or the event
handlers Delphi creates for you won’t have the same names as they do in this
example.
• Delete the text in the Text property of the memo control.
• Set the WordWrap property of the memo control to True.
• Set the ScrollBars property of the memo control to scVertical.
➤ For each button, create an OnClick event handler. Fill in the event handlers as follows:
procedure TForm1.CutClick(Sender: TObject);
begin
Memo1.CutToClipboard;
end;
procedure TForm1.CopyClick(Sender: TObject);
Calling functions
Like a procedure, a function executes code that performs a specific task. Also like a
procedure, a function that is declared within an object, component, or control is called a
method.
The difference between a function and procedure is that a function returns a value when
it stops running, and a procedure doesn’t. Your code then uses the value returned by the
function to do one of two things:
• Assign it to a property or variable
• Use the value to determine the flow of code execution
The if statement
Object Pascal’s if statement evaluates an expression and determines the flow of your
code based on the result of that evaluation. If a certain condition is True, the code flow
branches one way. If the condition is False, the flow branches in another direction. To see
the syntax of an if statement, see the if reserved word topic in Delphi’s online Help.
This example uses a simple if statement. This is how your finished form should look:
Figure 5.4 A sample form to illustrate an if statement
Nesting if statements
You can put if statements within if statements when the logic of your application
requires it. For example, the OKClick handler shown here can now test three conditions:
procedure TForm1.OKClick(Sender: TObject);
begin
if Edit1.Text = 'Saturday' then
Label2.Caption := 'Why are you working today?'
else
if Edit1.Text = 'Sunday' then
Label2.Caption := 'You should be resting'
else
if Edit1.Text = 'Monday' then
Label2.Caption := 'Welcome to a new work week!'
else
Label2.Caption := '';
end;
As soon as a condition is met, the statement part runs and no further testing of
conditions occurs. In other words, if you type Saturday in the edit box, the code displays
the Saturday message in the label, and the rest of the if statement is ignored.
Note No semicolon appears until the end of the final else part. When you write nested if
statements, choose a consistent, clear indentation style. This will help you and anyone
else who reads your code see the logic of the if statement and how the code flows when
your application runs.
A counting example
This is a variation of the same for loop just discussed. It uses a string grid control and a
button the user clicks to start the counting process.
➤ To create the form,
1 Place a string grid control and a button on the form.
2 Use the Object Inspector to
• Change the value of the button’s Name property to CountButton.
• Change the caption of the button to Count.
• Change the ColCount property for the string grid to 6.
• Change the RowCount property for the string grid to 6.
You might have to resize the form and the string grid so that you can see all six columns.
Your form should look like this:
Figure 5.8 A sample form to illustrate a for loop
Row 0
Column 0
3 Create this event handler that runs when you click the Show Coordinates button:
procedure TForm1.ShowCoordinatesButtonClick(Sender: TObject);
var
Col, Row: Integer;
begin
for Col := 1 to 5 do
StringGrid1.Cells[Col, 0] := 'Col ' + IntToStr(Col);
for Row := 1 to 5 do
StringGrid1.Cells[0, Row] := 'Row ' + IntToStr(Row);
for Col := 1 to 5 do
for Row := 1 to 5 do
StringGrid1.Cells[Col, Row] :=
'Col ' + IntToStr(Col) + ', ' + 'Row ' + IntToStr(Row);
end;
4 Run the application and click the Show Coordinates button.
This event handler contains four for statements. The first for statement writes the string
‘Col ’ plus the current value of the Col variable in the row 0 once the value of Col is
converted to a string:
for Col := 1 to 5 do
StringGrid1.Cells[Col, 0] := 'Col ' + IntToStr(Col);
The second for statement writes the string ‘Row ’ plus the current value of the Row
variable in the column 0 once the value of Row is converted to a string:
for Row := 1 to 5 do
StringGrid1.Cells[0, Row] := 'Row ' + IntToStr(Row);
Project1 block
Unit1 block
Button1Click
event handler
block
Understanding scope
The scope of a variable, constant, method, type, or other identifier defines where the
identifier is active. The identifier is local in scope to the smallest block in which it is
declared.
When your application is executing code outside the block in which an identifier is
declared, that identifier is no longer in scope. That means the identifier is no longer
available to the executing code. Only when code execution reenters the same block as
the identifier declaration can the code access the identifier again.
You were introduced to blocks in the previous section. Imagine that you have a project
that contains two units. Each of those units contains three event handlers, or procedures.
Here is your project depicted graphically:
Figure 5.12 Blocks within a simple project
Project1
Unit A
Procedure A
Procedure B
Procedure C
Unit B
Procedure D
Procedure E
Procedure F
Each rectangle in the diagram represents a block. If you declare a variable within
procedure D, only the code within procedure D can access that variable, as that variable
is local in scope to procedure D. If you declare a variable in unit B that is not in any
procedure, all procedures D, E, and F can use the variable, because all these procedures
are within the scope of unit B. The variable is now global in scope to the procedures, but
local in scope to unit B.
In general, declare identifiers that are as local in scope as possible. This gives the data in
your application increased protection from being modified when you do not intend it to
be. Only when you need to share data between different blocks should you consider
using a more global scope.
A scope example
This is an example that illustrates local and global scope. Your finished form should
look something like this:
Figure 5.13 A form for multiplying two numbers together
Each time the user enters two numbers in the first two edit boxes and chooses Multiply,
the application multiplies the two numbers together and displays it in the The Answer
edit box.
➤ To create this application,
1 Put three edit box controls and a button control on a form.
2 Place a label control above each of the three edit boxes.
3 Using the Object Inspector, change these property settings:
• Change the caption of Label1 to First Number.
• Change the caption of Label2 to Second Number.
• Change the caption of Label3 to The Answer.
• Change the value of the Name property of Button1 to Multiply.
• Delete the text in all the edit boxes.
{$R *.DFM}
var
Count: Integer;
Type declarations
Delphi applications can create new types beyond the predefined data types that are part
of the Object Pascal language. You can read about creating user-defined types in the
section “Defining new data types” on page 195, but here you can see what a type
declaration part can look like. A type declaration part begins with the reserved word
type. These are some type declarations:
var
Form1: TForm1;
end.
If the NoValue function is not declared in the interface part, but in the implementation
part instead, only this unit and no other can use NoValue.
When Delphi creates an event handler, the event handler procedure is declared in the
object type declaration. Because the object type declaration is in the interface part of the
unit, any other unit can call the event handler. For more information about the interface
and implementation parts of a unit, see the section “Understanding Object Pascal units”
on page 206.You can also read more about object type declarations in Chapter 6.
The NoValue function as it appears on page 184 is an example of a routine that is not
declared separately from its implementation. Because you want only the code within the
event handlers to be able to use NoValue, you would not declare it in the interface part,
but in the implementation part, as the code in the event handlers is in the
implementation part.
Forward declarations
There is an exception to this rule, however, that allows routine A to call routine B, and
then while routine B is running, routine B calls routine A. This type of calling is called
mutual recursion.
To make such mutual recursion possible, you need to declare a routine as a forward
declaration. When you declare a routine using the forward standard directive, you can
place the implementation of the procedure or function anywhere you choose—between
event handlers, after other procedures and functions that call the routine, and so on. If
the NoValue declaration is declared as a forward declaration, it looks like this:
function NoValue (AnEditBox: TEdit): Boolean; forward;
A forward declaration uses the forward standard directive. The declaration doesn’t
include the implementation of the procedure. Instead, the NoValue implementation has
to appear somewhere after the forward declaration.
The implementation of NoValue can appear after other procedures, functions, event
handlers, and methods that might call it, however.
This is an example of two procedures that call each other recursively. The form in this
application has one button on it. When you click the button, the two procedures begin
calling one another:
unit Unit1;
interface
uses WinTypes, WinProcs, Classes, Graphics, Forms, Controls, Apps;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Passing parameters
When your code calls a procedure or function, it often uses parameters to pass data to
the called procedure or function. The section “Calling procedures with parameters” on
page 160, describes how to use a parameter in calling a procedure; the section “Writing
a procedure or function header” on page 185, describes how to create a parameter list in
a procedure or function header. This section describes the most common kinds of
parameters your procedures and functions can use:
Value parameters
With the exception of the code example in the previous section, “Forward declarations,”
value parameters are the only type of parameters discussed in this chapter so far. A
formal value parameter is a copy of the actual value parameter. In other words, the
compiler puts the actual parameter at one memory address, and the formal parameter at
another memory address. Therefore, the called procedure or function can change the
value of the formal parameter, yet the value of the actual parameter remains unchanged.
➤ To see an example of this,
1 Put two edit box controls and a button on a form.
2 Using the Object Inspector, delete the text specified as the value of the Text property
for the two edit box controls.
Your form should look something like this:
Figure 5.16 A form for a value parameter example
10 10
Because the Calculate procedure changes the value of the CalcNo parameter, the values of
Number and CalcNo are no longer the same when Calculate stops running.
10 100
Value parameters can be any expression. To read about what constitutes an expression,
see the Expressions topic in online Help.
Variable parameters
Sometimes you want the value of a passed parameter to change as the called procedure
or function processes it. In these cases, you need to use a variable parameter. Precede the
formal parameter in the called routine with the reserved word var in the parameter list.
For example,
procedure Calculate(var CalcNo: Integer);
This variable parameter is a reference to the actual parameter, which is Number in the
example. It does not occupy a separate location in memory, but instead, points to the
actual parameter.
When a variable parameter is passed, any changes made to the formal parameter are
reflected in the actual parameter because both parameters refer to the same value.
➤ To see how this works, add the word var in front of the CalcNo parameter in the
Calculate procedure declaration. The Calculate procedure should now look like this:
procedure Calculate(var CalcNo: Integer);
begin
CalcNo := CalcNo * 10;
end;
➤ Run the application and enter a number in the Edit1 edit box.
You can see that the Calculate procedure does indeed change the value of the Number
variable in the OnClick event handler. Because the Number actual parameter and the
formal CalcNo parameter now refer to the same variable, the Number value changes in
the second edit box when Calculate runs.
These drawings demonstrate what happens. When Calculate is called, the value of
Number and the value of CalcNo are the same, because both the actual and the formal
parameters refer to the same memory location.
10
After the Calculate procedure runs, the Number and CalcNo parameters still refer to the
same value, even though that value has changed.
Figure 5.20 The value of Number and CalcNo after Calculate runs
100
Constant parameters
If a formal parameter never changes its value when a procedure or function runs, you
should consider using a constant parameter instead of a value parameter. Make a formal
parameter a constant parameter by typing the reserved word const before the name of
the parameter in the parameter list.
Like a value parameter, a constant parameter can be any expression. Using a constant
parameter instead of a value parameter, however, protects you from accidentally
assigning a new value to the parameter when you don’t want the parameter to change.
If you try to assign a value to a constant parameter, you’ll receive an Invalid Variable
Reference message because the value of a constant isn’t allowed to change.
Enumerated types
An enumerated type declaration lists all the values the type can have. These are some
examples of enumerated type declarations:
type
TDays = (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);
TPrimaryColor = (Red, Yellow, Blue);
TDepartment = (Finance, Personnel, Engineering, Marketing, MIS);
TDog = (Poodle, GoldenRetriever, Dachshund, NorwegianElkhound, Beagle);
These are some variables of those enumerated types:
var
DayOfWeek: TDays;
Hue: TPrimaryColor;
Department: TDepartment;
DogBreed: TDog;
Each value listed in parentheses in an enumerated type declaration has an underlying
integer value determined by the position of the value in the list. For example, Monday in
the TDays type declaration has the value 0, Tuesday has the value 1, and so on. You could
achieve the same result by declaring the DayOfWeek variable to be of type Integer and
then assign an Integer value to represent each day of the week. While this system might
work in an orderly and predictable series such as days of the week or months of the
year, it’s less useful when the order of represented values is arbitrary. Most people are
not very good at remembering what a number stands for. For example, the assignment
DogBreed := Dachshund;
Subrange types
A subrange type is a range of values of any of these types: integer, Boolean, Char, or
enumerated types. Subranges are useful when you want to limit the number of values a
variable can have. To create a subrange, specify the minimum and maximum values in
the range with two periods in between them. For example,
1..100
Array types
An array is an ordered collection of a data type, with each element of the collection
specified by its numeric position within the collection. When the array is created, the
elements don’t contain useful values at first, but you can fill them with data and
manipulate that data as you need to. For example, here is a variable declaration for an
array of Double types:
var
Check : array{1..10] of Double;
This declaration tells Delphi that the variable Check refers to a list of ten variables of type
Double, each with a number (called its index) from 1 to 10.
Each item of an array is referred to by the name of the array, followed by its index
enclosed in brackets ([ ]). So the array Check contains the ten variables Check[1], Check[2],
Check[3], Check[4], and so on, up to Check[10]. You can use any of these variables
wherever you would use a regular Real variable. Also, the index value doesn’t have to
be a constant. It can be any expression that yields an integer in the range 1 to 10. For
example,
J := 5;
Check[J] := 0.0;
These statements assign the value 0.0 to variable Check[5]. (Because Check is an array of
type Double, the value you assign must be Real and contain a decimal point. Also, all
Double values must begin with a digit, not a decimal point, so you can’t write 0.0 as .0)
If you want to assign a value of zero to all the Check variables in the array, you could use
a for loop to do it. Because an index can be a variable, a for loop is easier to use than
assigning a value to each item in an array with separate assignment statements. This for
loop assigns the 0.0 amount to all ten checks:
for J := 1 to 10 do
Check(J) := 0.0;
You can define arrays as types. For example,
type
TCheck = array[1..100] of Double;
You can then declare variables of the array type. For example, this code declares a
CheckingAccount to be a variable of type TCheck, which is an array of 100 real numbers.
Multidimensional arrays
The arrays discussed so far are one-dimensional lists. Arrays can have many
dimensions. Two-dimensional arrays can be used to hold all the values in a table, for
example.
This is how you would create a two-dimensional array that can hold all the values in a
table that contains 20 columns and 20 rows:
type
TTable = array[1..20, 1..20] of Double;
Then you can declare a variable of the TTable type:
var
BigTable: TTable;
To initialize all the values in the table to 0.0, you could use nested for loops:
var
Col, Row: Integer;
ƒ
for Col := 1 to 20 do
for Row:= 1 to 20 do
BigTable[Col, Row] := 0.0
You can find information about using these string procedures and functions in online
Help.
Set types
A set is a collection of elements of one type. That one type must be either an integer,
Boolean, Char, enumerated, or subrange type. Sets are useful for checking if a value
belongs to a particular set.
Here is a simple application that uses a new set type. This is the finished form:
Figure 5.24 A form for a set type example
Record types
Records are collections of data that your application can refer to as a whole. For
example, your application could use a TEmployee record type that is declared like this:
type
TEmployee = record
LastName : string[20];
FirstName: string[15];
YearHired: 1990..2000;
Salary: Double;
Position: string[20]
end;
Records contain fields that hold data values. Each field has a data type. The fields of a
TEmployee type are LastName, FirstName, YearHired, Salary, and Position. You can access
these fields individually, or you can refer to the record as a whole.
For example, here are the declarations of two record variables:
What is a unit?
A unit is a collection of constants, data types, variables, and procedures and functions
that can be shared by several applications. Delphi comes with a large number of
predefined units you use to construct your Delphi applications. The Delphi Visual
Component Library is made up of several units that declare the objects, components,
and controls you use to design the interface for your application. Each time you add a
check box to a form, for example, you are using the StdCtrls unit automatically because
the TCheckBox component is declared in StdCtrls.
As you design the forms for your application, you are automatically creating new units
that are associated with the forms. Units don’t have to be associated with forms,
however. You can use a predefined unit that contains only mathematical routines, for
example. Or you can write your own unit of math functions.
All the declarations in a unit are related to one another. For example, the CDialogs unit
contains all the declarations for using common dialog boxes in your applications.
Interface part
The interface part of a unit begins with the reserved word interface, which appears
after the unit header and ends at the reserved word implementation. The interface
determines what is “visible” (accessible) to any application or other unit using this unit.
In the unit interface part, you can declare constants, data types, variables, procedures,
and functions. If Delphi builds a unit for you as you design a form, the form data type,
the form variable that creates an instance of the form, and the event handlers are
declared in the interface part. You can see examples of these in Chapter 6.
The procedures and functions visible to any unit or application using the unit are
declared in the interface part. Their actual bodies—their implementations—are found
in the implementation part. You don’t need to use forward declarations, and they aren’t
allowed in the interface part. The interface part lists all the procedure and function
headers; the implementation part contains the coded logic of the procedures and
functions, including those that are event handlers.
Implementation part
The implementation part of a unit begins with the reserved word implementation.
Everything declared in the interface part is accessible to the code in the implementation
part.
The implementation can have additional declarations of its own, although these
declarations aren’t accessible to any other application or unit. These declarations are
used by the procedures, functions, and event handlers declared in this unit.
An optional uses clause can appear in the implementation part and must immediately
follow the implementation reserved word.
The bodies of the routines declared in the interface part must appear in the
implementation part. The procedure or function header that appears in the
implementation part can be identical to the declaration that appears in the interface
part, or it can be in the short form.
To use the short form, type the procedure or function reserved word and follow it with
the routine’s name. You can omit any list of parameters, and, if the routine is a function,
the return type. For example, suppose you declare this function in the interface part:
function CalculateInterest(Principal, InterestRate: Double): Double;
When you write the body of the function in the implementation part, you can choose to
write the function like this:
function CalculateInterest;
begin
Result := Principal * InterestRate;
end;
Note that the parameter and the return type have been omitted.
If you declare any routines in the implementation part (not in the interface part), you
must use the long form of the procedure or function header.
Initialization part
If you want to initialize any data the unit uses or makes available through the interface
part to the application or unit using it, you can add an initialization part to the unit.
Above the final end reserved word at the bottom of the unit, add the reserved word
initialization. Between the initialization and end reserved words, you write the code
that initializes the data. For example,
initialization
{ Your initialization code goes here }
end.
When an application uses a unit, the code within the unit’s initialization part is called
before the any other application code runs. If the application uses more than one unit,
each unit’s initialization part is called before the rest of the application runs.
Summary
This chapter presented these topics:
• Writing readable code
It doesn’t matter to the compiler how you space, indent, or capitalize your code, or
where you break lines of code. As long as the syntax of your code is correct, the
compiler can handle it. You should, however, choose a style that makes your code
easily readable by you and others.
Enclose all comments in your code within braces ({ }).
• Writing assignment statements
Assignment statements assign the value on the right side of the statement to the
property or variable on the left side of the assignment statement. The assignment
What is an object?
An object is a data type that wraps up data and code all into one bundle. Before OOP,
code and data were treated as separate elements.
When the user clicks the button, the form changes color to green. This is the event-
handler code for the button OnClick event:
procedure TForm1.Button1Click(Sender: TObject);
begin
Form1.Color := clGreen;
end;
TForm
TObject
TComponent
TControl
Everything in this hierarchy is an object. Components, which inherit data and code from
a TObject type, are objects with additional properties, methods, and events that make
them suitable for specialized purposes, such as the ability to save their state to a file.
Controls, which inherit data and code from a TComponent type (which in turn inherits
elements from TObject) have additional specialized capabilities, such as the ability to
Object scope
An object’s scope determines the availability and accessibility of the data fields,
properties, and methods within that object. Using the earlier bicycle analogy, if you
were to add a headlight only to your customized “bicycle object,” the headlight would
belong to that bicycle and to no other. If, however, the “basic model bicycle object”
included a headlight, then all bicycle objects would inherit the presence of a headlight.
The headlight could lie either within the scope of the ancestor bicycle object—in which
case, a headlight would be a part of all descendant bicycle objects—or within the scope
only of the customized bicycle object, and available only to that bicycle.
Likewise, all data fields, properties, and methods declared within an object declaration
are within the scope of the object, and are available to that object and its descendants.
Even though the code that makes up the methods appears outside of the object
declaration in the implementation part of the unit, those methods are still within the
scope of the object because they were declared within the object’s declaration.
When you write code in an event handler of an object that refers to properties, methods,
or fields of the object itself, you don’t need to preface these identifiers with the name of
the object variable. For example, if you put a button and an edit box on a new form, you
could write this event handler for the OnClick event of the button:
procedure TForm1.Button1Click(Sender: TObject);
begin
Color := clFuchsia;
Edit1.Color := clLime;
end;
The first statement colors the form. You could have written the statement like this:
Form1.Color := clFuchsia
It’s not necessary, however, to put the Form1 qualifier on the Color property because the
Button1Click method is within the scope of the TForm1 object. Any time you are within
an object’s scope, you can omit the qualifier on all properties, methods, and fields that
are part of the object.
The second statement refers to the Color property of a TEdit object. Because you want to
access the Color property of the TEdit1 type, not of the TForm1 type, you need to specify
the scope of the Color property by including the name of the edit box, so the compiler
can determine which Color property you are referring to. If you omit it, the second
statement is like the first; the form ends up lime green, and the edit box control remains
unchanged when the handler runs.
Overriding a method
You can, however, use the name of a method within an ancestor object to declare a
method within a descendant object. This is how you override a method. You would most
likely want to override an existing method if you want the method in the descendant
object to do the same thing as the method in the ancestor object, but the task is
accomplished in another way. In other words, the code that implements the two
methods differs.
It’s not often that you would want to override a method unless you are creating new
components. You should be aware that you can do so, though, and that you won’t
receive any warning or error message from the compiler. You can read more about
overriding methods in the Delphi Component Writer’s Guide.
Responding to exceptions
When an error condition occurs, the application raises an exception, meaning it creates
an exception object. Once an exception is raised, your application can execute cleanup
code, handle the exception, or both.
You can also use nested blocks to define local handling for specific exceptions that
overrides the handling in the surrounding block. Conceptually, that looks something
like this:
You can also mix different kinds of exception-response blocks, nesting resource
protections within exception handling blocks and vice versa.
Heap exceptions
Heap exceptions can sometimes occur when you try to allocate or access dynamic
memory. The SysUtils unit defines two heap exceptions called EOutOfMemory and
EInvalidPointer. Table 7.1 shows the specific heap exceptions, each of which descends
directly from Exception:
Table 7.1 Heap exceptions
Exception Meaning
EOutOfMemory There was not enough space on the heap to complete the requested operation.
EInvalidPointer The application tried to dispose of a pointer that points outside the heap. Usually, this
means the pointer was already disposed of.
Typecast exceptions
Typecast exceptions can occur when you attempt to typecast an object into another type
using the as operator. The SysUtils unit defines an exception called EInvalidCast that the
RTL raises when the requested typecast is illegal.
Conversion exceptions
Conversion exceptions can occur when you convert data from one form to another
using functions such as IntToStr, StrToInt, StrToFloat, and so on. The SysUtils unit
defines an exception called EConvertError that the RTL raises when the function cannot
convert the data passed to it.
Hardware exceptions
Hardware exceptions can occur in two kinds of situations: either the processor detects a
fault it can’t handle, or the application intentionally generates an interrupt to break
execution. Hardware exception-handling is not compiled into DLLs, only into
standalone applications.
The SysUtils unit defines a generic hardware exception called EProcessorException. The
RTL never raises an EProcessorException, but it provides a base from which the specific
hardware exceptions descend.
Table 7.4 shows the specific hardware exceptions.
Table 7.4 Hardware exceptions
Exception Meaning
EFault Base exception object from which all fault objects descend.
EGPFault General protection fault, usually caused by an uninitialized pointer or object.
EStackFault Illegal access to the processor’s stack segment.
EPageFault The Windows memory manager was unable to correctly use the swap file.
EInvalidOpCode Processor encountered an undefined instruction. This usually means the processor
was trying to execute data or uninitialized memory.
EBreakpoint The application generated a breakpoint interrupt.
ESingleStep The application generated a single-step interrupt.
You should rarely encounter the fault exceptions, other than the general protection fault,
because they represent serious failures in the operating environment. The breakpoint
Exception-handling statements
Each statement in the except part of a try..except block defines code to execute to handle
a particular kind of exception. The form of these exception-handling statements is as
follows:
on <type of exception> do <statement>;
You can define, for example, an exception handler for division by zero to provide a
default result:
function GetAverage(Sum, NumberOfItems: Integer): Integer;
begin
try
Result := Sum div NumberOfItems;
except
on EDivByZero do Result := 0;
end;
end;
Note that this is clearer than having to test for zero every time you call the function.
Here’s an equivalent function that doesn’t take advantage of exceptions:
Silent exceptions
Delphi applications handle most exceptions that your code doesn’t specifically handle
by displaying a message box that shows the message string from the exception object.
You can also define “silent” exceptions that do not, by default, cause the application to
show the error message.
Silent exceptions are useful when you don’t intend to handle an exception, but you want
to abort an operation. Aborting an operation is similar to using the Break or Exit
procedures to break out of a block, but can break out of several nested levels of blocks.
Silent exceptions all descend from the standard exception type EAbort. The default
exception handler for Delphi applications displays the error-message dialog box for all
exceptions that reach it except those descended from EAbort.
■ There is a shortcut for raising silent exceptions. Instead of manually constructing the
object, you can call the Abort procedure. Abort automatically raises an EAbort exception,
which will break out of the current operation without displaying an error message.
The following code shows a simple example of aborting an operation. On a form
containing an empty list box and a button, attach the following code to the button’s
OnClick event:
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
for I := 1 to 10 do { loop ten times }
begin
Raising an exception
To indicate an error condition in an application, you can raise an exception which
involves constructing an instance of that type and calling the reserved word raise.
■ To raise an exception, call the reserved word raise, followed by an instance of an
exception object.
When an exception handler actually handles the exception, it finishes by destroying the
exception instance, so you never need to do that yourself.
Summary
Exceptions provide a powerful and flexible mechanism for reporting and responding to
error conditions in your applications. The Delphi run-time library and all the standard
components raise and respond to exceptions.
By handling exceptions in your applications, you can ensure that you don’t lose system
resources when your application must unexpectedly shut down, or you can enable the
application or the user to correct the error condition and retry the operation. In either
case, exceptions provide information necessary to the application and a mechanism you
can use to respond to error conditions.
Types of bugs
The integrated debugger can help find two basic types of programming errors: run-time
errors and logic errors.
Run-time errors
If your program successfully compiles, but fails when you run it, you’ve encountered a
run-time error. Your program contains valid statements, but the statements cause errors
when they’re executed. For example, your program might be trying to open a
nonexistent file, or it might be trying to divide a number by zero. The operating system
Logic errors
Logic errors are errors in design and implementation of your program. Your program
statements are valid (they do something), but the actions they perform are not the actions
you had in mind when you wrote the code. For instance, logic errors can occur when
variables contain incorrect values, when graphic images don’t look right, or when the
output of your program is incorrect.
Logic errors are often the most difficult type of errors to find because they can show up
in places you might not expect. To be sure your program works as designed, you need
to thoroughly test all of its aspects. Only by scrutinizing each portion of the user
interface and output of your program can you be sure that its behavior corresponds to
its design. As with run-time errors, the integrated debugger helps you locate logic errors
by letting you monitor the values of your program variables and data objects as your
program executes.
Trace Into
The Trace Into command executes a single program statement at a time. If the execution
point is located on a call to a function that was compiled with debugging information,
choosing Trace Into causes the debugger to step into that function by placing the
execution point on the function’s first statement. However, if the execution point is
located on a function call that doesn’t contain debugging information (a library function,
for example), then choosing Trace Into runs that function at full speed, after which the
execution point is positioned on the statement following the function call.
If the execution point is located on the last statement of a function, choosing Trace Into
causes the debugger to return from the function, placing the execution point on the line
of code that follows the call to the function you are returning from.
The term single stepping refers to using Trace Into to successively run though the
statements in your program code.
■ To issue the Trace Into command, choose one of the following methods:
• Choose Run|Trace Into.
• Press F7 (default key mapping).
• Click the Trace Into SpeedButton.
Step Over
The Step Over command, like Trace Into, enables you to execute program statements
one at a time. However, if you issue the Step Over command when the execution point
is located on a function call, the debugger runs that function at full speed (instead of
tracing into it), then positions the execution point on the statement that follows the
function call.
■ To issue the Step Over command, choose from one of the following methods:
• Choose Run|Step Over.
• Press F8 (default key mapping).
• Click the Step Over SpeedButton.
As you debug, you can choose to trace into some functions and step over others. If you
know a function performs as it was designed to, you can step over calls to that function
with confidence that the function call will not cause an error. If, on the other hand, you
aren’t sure that a function is well behaved, you can choose to Trace Into the function to
verify that it works as designed.
Running to a breakpoint
You set breakpoints on lines of source code where you want the program execution to
pause during a run. Running to a breakpoint is similar to running to a cursor position in
that the program runs at full speed until it reaches a certain source code location.
However, unlike Run To Cursor, you can have multiple breakpoints in your code, and
you can customize each one so it pauses the program execution only when a specified
condition is met. For more information on breakpoints, see “Using breakpoints” on
page 254.
Using breakpoints
You use breakpoints to pause the program execution at designated source code locations
during a debugging session. By setting breakpoints in potential problem areas of your
source code, you can run your program at full speed, knowing that its execution will
pause at a location you want to debug. When your program execution encounters a
breakpoint, the program pauses, and the debugger displays the line containing the
breakpoint in the Code Editor. You can then use the debugger to view the state of your
program.
Setting breakpoints
Breakpoints are flexible in that they can be set before you begin a program run or at any
time that the integrated debugger has control. For a breakpoint to be valid, it must be set
on an executable line of code. Breakpoints set on comment lines, blank lines,
declarations, or other non-executable lines of code are invalid and become disabled
when you run your program.
■ To set a breakpoint, select the line of code in the Code Editor where you want the
breakpoint set, then do one of the following:
• Click the left margin of the line in the Code Editor where you want the breakpoint
set.
• Press F5 (default key mapping).
• Choose Toggle Breakpoint from the Code Editor SpeedMenu.
• Choose Run|Add Breakpoint, then choose New (in the Edit Breakpoint dialog box)
to confirm a new breakpoint setting, or choose Modify to implement changes to an
existing breakpoint.
• Choose Add Breakpoint from the Breakpoint List SpeedMenu.
Alternately, if you know the line of code where you want the breakpoint set, choose
Run|Add Breakpoint and type the source-code line number in the Line Number box.
When the settings in the Edit Breakpoint dialog box are correct, choose New to complete
the breakpoint entry.
Invalid breakpoints
If a breakpoint is not placed on an executable line of code, the debugger considers it
invalid. For example, a breakpoint set on a comment, a blank line, or declaration is
invalid. If you set an invalid breakpoint, the debugger displays the Invalid Breakpoint
error box when you attempt to run the program. To correct this situation, close the error
box and delete the invalid breakpoint from the Breakpoint List window. You can then
reset the breakpoint in the intended location. However, you can also ignore invalid
breakpoints; the IDE disables any invalid breakpoints when you run your program.
Note During the linking phase of compilation, lines of code that do not get called in your
program are marked as dead code by the linker. In turn, the integrated debugger marks
any breakpoints set on dead code as invalid.
Use the Breakpoint List window to view and maintain all your breakpoints; you don’t
need to search through your source files to find the breakpoints you’ve set. Also, using
the commands on the Breakpoint List SpeedMenu, you can view or edit the code at any
breakpoint location.
Deleting breakpoints
When you no longer need to examine the code at a breakpoint location, you can delete
the breakpoint from the debugging session. You can delete breakpoints using either the
Code Editor or the Breakpoint List window:
■ Use the following methods to delete breakpoints:
• From the Code Editor, place the text cursor in the line containing the breakpoint and
press F5 (or choose Toggle Breakpoint from the Speed Menu).
• Click the stop-sign glyph in the Code Editor window to delete the associated
breakpoint.
• From the Breakpoint List window, highlight the breakpoint you want removed, then
choose Delete Breakpoint from the SpeedMenu.
• To delete all currently set breakpoints, choose Delete All Breakpoints from the
Breakpoint List SpeedMenu.
Caution The breakpoint delete commands are not reversible.
In addition to examining a breakpoint’s properties, you can use the Edit Breakpoint
dialog box to change the location of a breakpoint, set a conditional breakpoint, and set a
pass count for the breakpoint.
Watching expressions
You use watches to monitor the changing values of variables or expressions during your
program run. After you enter a watch expression, the Watch List window displays the
current value of the expression. As your program runs, the value of the watch changes
as your program updates the values of the variables contained in the watch expression.
If the execution point moves to a location where any of the variables in the watch
expression are undefined, then the entire watch expression becomes undefined. If the
execution point returns to a location where the watch expression can be evaluated, then
the Watch List window again displays the current value of the watch expression.
■ To open the Watch List window, choose View|Watches.
Figure 8.3 The Watch List window
If you’re setting up a watch on an element in a data structure (such as an array), you can
display the values of consecutive data elements. For example, suppose you have an
array of five integers named xarray. Type the number 5 in the Repeat Count box of the
Watch Properties dialog box to see all five values of the array. However, to use a repeat
count, the watch expression must represent a single data element.
To format a floating-point expression, indicate the number of significant digits you want
displayed in the Watch List window by typing this number in the Digits edit box.
Disabling a watch
If you prefer not to watch an expression that you’ve entered in the Watch List window,
but you don’t want to delete it because you might need to use it later, you can disable
the watch. Disabling watches speeds up the response of the debugger because it won’t
have to monitor the watch as you step or run through your program.
In the Watch List window, the Enable check box lies to the left of each watch listing.
When you set a watch, the debugger enables the watch by checking this box.
■ To disable a watch, do one of the following:
• Double-click a watch in the Watch List window to open the Watch Properties dialog
box, then uncheck the Enabled check box.
• Select the watch in the Watch window and choose Disable Watch from the
SpeedMenu.
You can also disable all current watches by choosing Disable All Watches from the
SpeedMenu. To reenable a watch, recheck the Enabled check box, or select it in the
Watches window, then choose Enable Watch (or Enable All Watches) from the
SpeedMenu.
Deleting a watch
To delete a watch expression, select the expression in the Watch window, then choose
Delete Watch from the SpeedMenu. You can also delete all the watches by choosing
Delete All Watches from the SpeedMenu.
Evaluating expressions
Choose Run|Evaluate/Modify to open the Evaluate/Modify dialog box.
Figure 8.5 The Evaluate/Modify dialog box
By default, the word at the cursor position in the current Code Editor is placed in the
Expression edit box. You can accept this expression, enter another one, or choose an
expression from the history list of expressions you’ve previously evaluated.
■ To evaluate the expression, click the Evaluate button at the bottom of the Evaluate/
Modify dialog box. Using this dialog box, you can evaluate any valid language
expression, except those that contain
• Local or static variables that are not accessible from the current execution point
• Function and procedure calls
Note The Evaluate/Modify dialog box lets you view and modify the values of object
properties while running the program. However, to view a property, you need to
explicitly specify the property name. For example, you can enter the following
expression to evaluate the Caption property of Button1:
Button1.Caption
When you evaluate an expression, the current value of the expression is displayed in the
Result field of the dialog box. If necessary, you can format the result by adding a comma
For example, to display a result in hexadecimal, type ,H after the expression. To see a
floating point number to 3 decimal places, type ,F3 after the expression.
The top of the Call Stack window lists the last function called by your program. Below
this is the listing for the previously called function. The listing continues, with the first
function called in your program located at the bottom of the list. Note that only
functions in the currently loaded symbol table are listed in this window. To view
functions located in a different module, change symbol tables, as described later in this
chapter.
The Call Stack window is particularly useful if you accidentally trace into code you
wanted to step over. Using the Call Stack window, you can return to the point from
which the current function was called, then resume debugging from there.
■ To use the Call Stack window,
1 In the Call Stack window, double-click the function that called the function you
accidently traced into (it is the second function listed in the Call Stack window). The
Code Editor becomes active with the cursor positioned at the location of the function
call.
IV
Sample applications
Part IV
The chapters in this part show several complete examples of building applications with
Delphi. Although each of the sample applications is a complete and useful application,
the primary purpose of these chapters is to explain how to perform typical application-
building tasks in Delphi within a realistic context.
For example, the text editor example describes how to manipulate menu items, and the
graphics example shows how to create and use tool bars. You will most likely use these
techniques in other kinds of applications, but by seeing these items in the context of
complete applications, you can better see how to integrate them into your own.
You can use the chapters in this part in several ways: to learn to build complete
applications, to see how to use particular components, or to see how to perform a
specific task with a component.
The sample applications in this part describe the following skills:
• “Using string lists”
This chapter presents various skills for using string-list objects, which appear in the
text editor example and the file manager example.
• “Text editor example”
This chapter demonstrates the creation and seamless integration of Multiple-
Document Interface (MDI) applications, fundamental concepts and techniques for
displaying and manipulating text.
• “Using graphics at run time”
This chapter discusses concepts and techniques for creating graphics applications in
Delphi. Encapsulation of Windows GDI functions in the Delphi Canvas.
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
ClickList: TStrings; { declare the field }
var
Form1: TForm1;
implementation
{$R *.DFM}
end.
Methods such as Delete, Clear, and Move operate on items as a whole. That is, deleting an
item deletes both the string and the corresponding object. Also note that the
LoadFromFile and SaveToFile methods operate on only the strings, since they work with
text files.
10
Text editor example
Chapter 10
This chapter presents the steps involved in building a simple Multiple Document
Interface (MDI) text editor that uses the Windows common dialog boxes to open, save,
and print manipulable text files.
It assumes you are familiar with the material covered in Part II, “Fundamental skills.”
For instance, you need to know how to set component properties and build a menu. You
should also be familiar with Object Pascal language constructs, as discussed in Part III,
“Programming topics.” Finally, Chapter 9 discusses concepts that you’ll encounter as
you build the text editor.
The topics discussed in the context of creating this application are
• Multiple Document Interface (MDI) applications
• Working with open child windows
• Manipulating text in a Memo component
• Using common dialog boxes
• Printing the text file
• Exiting the application
Each section of this chapter builds upon preceding sections, but the steps themselves are
modular and can be used in a different context to achieve the same result. If you want to
learn how to load a text file, for example, you don’t need to read the section on creating
an MDI editor window first.
To see the completed application, open the project file TEXTEDIT.DPR, found in the
DELPHI\DEMOS\DOCS\TEXTEDIT directory if you installed Delphi using default
directories. Figure 10.1 shows the application as it appears the first time a new window
is opened.
The File and Window menu items exist in the frame form, because they control
functions of the frame, rather than functions specific to a particular child window. When
the user opens a child window by choosing File|New or File|Open, the application
menu changes to include two new menu options, as shown in Figure 10.3:
The Edit and Character menu items exist in the child form, because they control
functions specific to the child window and its contents. These menu items merge with
the frame form’s menu items to present one application menu, with options appropriate
to the current condition of the application.
Note While most MDI applications merge frame and child menus, you can also choose to
replace menus, rather than merging them.
You’ll use the Delphi Menu Designer to create the text editor application menus. If you
do not know how to use the Menu Designer, see Chapter 3.
Note that specifying a hyphen for the caption (below the Open1 menu item on the file
menu) creates a separator bar. In later sections you’ll set additional properties for the
frame form menu.
Assigning both File menu titles a GroupIndex value of 0 causes the EditForm File menu to
replace the FrameForm File menu at merge time and ensures that the File menu always
appears first, whether or not the menus are merged. Assigning the Window menu title a
GroupIndex a value of 9 ensures that the Window menu always appears last (because
the number 9 exceeds the total number of merged menu items).
Assigning the Edit and Character menu items identical GroupIndex values maintains
their order in the merge, and the value of 1 in this case inserts them after the File menu.
If the frame form had a menu item with a value of 1, the Edit and Character menu items
would, as a unit, replace it.
The following section describes how to create your application’s child windows at run
time.
Selecting text
Before you can send any text to the Clipboard, the text must be selected. The function of
reading and displaying selected text is native to the Memo and Edit components. In
other words, you don’t need to write code so that the Memo component can display
selected text; it comes with this behavior.
The Stdctrls unit in Delphi provides several methods to work with selected text. (Recall
that Delphi automatically adds the Stdctrls unit to the uses clause of any unit whose
form contains a component declared within Stdctrls.) SelText, a run-time only property,
contains a string based on any text selected in the component. The SelectAll method
selects all the text in the memo or other component. The SelLength and SelStart methods
return values for a selected string’s length and starting position, respectively.
The text editor application uses SelLength to determine whether the Memo component
contains any selected text, and then sets the condition of the Edit menu items
accordingly. This is discussed in the section “Dimming menu items” on page 292.
SelStart is discussed in the section “Loading the file” on page 300.
➤ Write the following handler for the Edit|Select All OnClick event:
procedure TEditForm.SelectAll(Sender: TObject);
begin
Memo1.SelectAll;
end;
Declaring a method
If you compile the program now, Delphi generates a “Method identifier expected” error
message. Because UpdateMenus wasn’t generated by using the Object Inspector, Delphi
didn’t create the method declaration. In order for the program to recognize
UpdateMenus as a valid method of the TEditForm class, you need to declare it yourself.
➤ Add the following line to the private part of the TEditForm type declaration in the
interface part of the MDIEdit unit:
procedure UpdateMenus;
Declaring the method in the private part keeps other units from accessing this method.
Because the MDIFrame unit has no reason to use this method (since it contains no such
menus) it’s good programming practice to keep it separate from the MDIEdit unit’s
sharable methods.
The following sections discuss several of the options for the dialog box components
you’ll use as you build the text editor application. Most of these options are unique to
each dialog box. All the common dialog boxes share at least one option in common,
however, which deserves special mention. For each dialog box, you can specify whether
to display a Help button. If you choose to display a Help button, you need to enable it,
so that when the user chooses the Help button at run time, the application’s Help file is
opened to a relevant topic.
The following section describes how to do this.
FileName,
DefaultExt
InitialDir
Filters,
FilterIndex
For the purposes of the text editor application, you’ll specify values only for the Filter
property. For information about the other properties of the OpenDialog component,
refer to online Help.
➤ Add an OpenDialog component to FrameForm. Name it OpenFileDialog.
Note The order in which you enter filters is the order in which they then appear in the List
File Of Type list box.
fdTrueTypeOnly
fdFixedPitchOnly fdNoSizeSelect
fdEffects
fdNoStyleSelect
You can also edit the initial settings for the dialog box by selecting the Font property in
the Object Inspector and clicking the ellipsis (...) button next to (TFont). This opens the
dialog box in a design-time state.
For the purposes of the text editor application, you won’t set any properties for the Font
dialog box component at design time. For more information about the properties of the
Font dialog box component not discussed here, refer to online Help.
Canvas
Canvas represents the surface of the currently printing document. You assign the
contents of your text file to the Canvas property of the printer object. The printer object
then directs the contents of the Canvas property (your text file) to the printer.
Fonts
Fonts represents the list of fonts supported by the current printer. These fonts appear in
the Font list of the Font dialog box.
As described previously, any font selected from the Font dialog box is reflected back
into the Font property for Memo1. However, the printer object has no such relationship
to the Font dialog box or to the Font property for Memo1. Unless your program specifies
otherwise, the printer uses the default (System) font that is returned by the Windows
device driver to print your text file.
PrintRange, FromPage,
MaxPage, MinPage,
Options, ToPage
properties Options|Help property
Copies property
Options | PrintToFile
property Collate property
Although Delphi makes it easy to do so, you don’t usually need to reset the default
options for this dialog box at design time. There are, however, a few print options worth
mentioning here.
MinPage / MaxPage
Use these settings to place an upper or lower limit on the number of pages the user can
specify in the Pages From: and To: edit boxes. Note that any setting you make does not
change what’s displayed in the dialog box. If the user enters a number outside the range
you specify and then presses Enter, the application displays an error message that says
“From (or To) value is below (or above) the minimum (or maximum) range.”
Options | poPageNums
A value of True enables the Pages From: and To: radio buttons, so the user can specify a
page range. For example, you might set this to True at run time once you’ve determined
that more than one page exists in the current document.
Options | poSelection
A value of True enables the Selection radio button, so the user can print selected text. For
example, you might set this to True at run time once you’ve determined that selected
text exists in the current document.
PrintRange
The Print Range settings specify what appears as the Print Range default when the
dialog box first opens. For example, a setting of PrintRange = prPageNums specifies that
the Pages radio button is selected, instead of the All radio button. AllPages is the default
setting.
Note that in order for either of the two non-default settings to take effect in the dialog
box, the corresponding Options setting must be True. For example, if you set PrintRange
to prSelection without also setting Options|Selection to True, the dialog box still opens
with the default Print Range setting of AllPages.
Exiting gracefully
Applications that enable users to modify and save data into files should include
safeguards so that users do not lose their work. The text editor application, for example,
creates a backup file every time the user saves an existing file. Other important safety
measures involve responding to a file or application close event—making sure that
modified files are not closed without giving the user the option to save changes.
So far you’ve given users the ability to open, save, and print their text files—but not the
ability to close them. In Delphi, closing a child window involves the same process as
closing the main MDI application window. In both cases you use the Close method of
TForm.
The Close method executes your form’s OnCloseQuery event handler code, which returns
a Boolean value for the CanClose parameter. If CanClose returns True, then the Close
method executes your form’s OnClose event handler code. You should ensure that the
code you write for the OnCloseQuery event handles any changes made to the text file
before the window closes.
This section discusses
• Closing a window
• Determining whether the file has been modified
• Exiting the application
Closing a window
In the text editor application, there are two menu items that call the Close method: File|
Close, and File|Exit. File|Close closes the child window, and File|Exit closes
FrameForm, which terminates the application (and indirectly closes all child windows).
Note that users can also close an application window in any of the following ways:
• Pressing Alt+F4 from an MDI frame window (terminates the application)
• Pressing Ctrl+F4 from an MDI child window (closes the child window)
Summary
Delphi provides tools to help you quickly and easily create Multiple Document Interface
applications, as well as several text-manipulation tools. This chapter discussed such text
manipulation techniques as cutting, copying, and pasting text, using the Clipboard with
text, and specifying a text font. In addition, the chapter presented such application-
development techniques as creation of MDI frame and child windows and merging
frame and child menus.
Manipulating pixels
You can treat the pixels of a canvas like a two-dimensional array, with each element in
the array having a particular color. You can either read or set individual pixels.
Using pens
The Pen property of a canvas controls the way lines appear, including lines drawn as the
outlines of shapes. Drawing a straight line is really just changing a group of pixels that
lie between two points.
The pen itself has four properties you can change: Color, Width, Style, and Mode.
The values of these properties determine how the pen changes the pixels in the line. By
default, every pen starts out black, with a width of 1 pixel, a solid style, and a mode
called copy that overwrites anything already on the canvas.
You can set the color of a pen as you would any other Color property at run time. Width
is an integer number of pixels. Style gives you solid lines, dashed lines, dotted lines, and
so on. Mode lets you specify various ways to combine the pen’s color with the colors
already in the pixel array.
The sample program in Chapter 12 demonstrates the effects of each pen property.
Using brushes
The Brush property of a canvas controls the way you fill areas, including the interior of
shapes. Filling an area with a brush is a way of changing a large number of adjacent
pixels in a specified way.
The brush has three properties you can manipulate: Color, Style, and Bitmap.
The values of these properties determine the way the canvas fills shapes or other areas.
By default, every brush starts out white, with a solid style and no pattern bitmap.
You can set the color of a brush as you would any other Color property at run time. Style
lets you specify various ways to combine the brush’s color with any colors already on
the canvas. Bitmap lets you specify a bitmap image for the brush to use as a pattern for
filling shapes and other areas.
The sample program in Chapter 12 demonstrates the effects of each brush property.
Drawing polylines
In addition to individual lines, the canvas can also draw polylines, which are groups of
any number of connected line segments.
■ To draw a polyline on a canvas, call the PolyLine method of the canvas. The parameter
passed to the PolyLine method is an array of points. You can think of a polyline as
performing a MoveTo on the first point and LineTo on each successive point.
The following method, for example, draws a rhombus in a form:
procedure TForm1.FormPaint(Sender: TObject);
begin
with Canvas do
PolyLine([Point(0, 0), Point(50, 0), Point(75, 50), Point(25, 50), Point(0, 0)]);
end;
This example takes advantage of Delphi’s ability to create an open-array parameter “on
the fly.” You can pass any array of points, but an easy way to construct an array quickly
is to put its elements in brackets and pass the whole thing as a parameter. For more
information, see online Help.
Drawing shapes
Canvases have methods for drawing four kinds of shapes. The canvas draws the outline
of a shape with its pen, then fills the interior with its brush.
There are three distinct kinds of shape drawing:
• Drawing rectangles and ellipses
• Drawing rounded rectangles
• Drawing polygons
Drawing rectangles, ellipses, and rounded rectangles are quite similar, but polygons are
a little different.
Drawing polygons
■ To draw a polygon with any number of sides on a canvas, call the Polygon method of the
canvas. Polygon takes an array of points as its only parameter and connects the points
with the pen, then connects the last point to the first to close the polygon. After drawing
the lines, Polygon uses the brush to fill the area inside the polygon.
To draw a right triangle in the lower left half of a form, for example, do the following:
procedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.Polygon([Point(0, 0), Point(0, ClientHeight),
Point(ClientWidth, ClientHeight)]);
end;
12
Graphics example
Chapter 12
This chapter presents all the steps to create a simple graphics application that draws
lines and shapes on a window’s canvas in response to mouse clicks and drags. Each
section in the chapter builds on the previous sections, but the individual sections also
explain discrete tasks.
To see the finished application, open the project GRAPHEX.DPR in the DEMOS\
GRAPHEX directory. Figure 12.1 shows the completed application.
Figure 12.1 The finished graphics program, GRAPHEX.EXE
Most of the time, the most important information in a mouse-event handler is the
coordinates, but sometimes you also need to check Button to determine which mouse
button caused the event.
Note Delphi uses the same criteria as Microsoft Windows in determining which mouse
button has been pressed. Thus, if you have switched the default “primary” and
“secondary” mouse buttons (so that the right mouse button is now the primary button),
clicking the primary (right) button will record mbLeft as the value of the Button
parameter.
end;
➤ Just to get a feel for writing a mouse-event handler, try displaying some text at the point
where you press the mouse button. To do that, you use the X and Y parameters sent to
the method, and call the TextOut method of the canvas to display text there:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Canvas.TextOut(X, Y, 'Here!'); { write text at (X, Y) }
end;
The application wouldn’t be able to draw a line yet, because the user would only have
pressed the mouse button. Pressing the button only tells the application where the
drawing will start, and for a line you need both a starting point and an ending point.
➤ For now, you can change the mouse-down event handler to set the current drawing
position to the coordinates where the user presses the button:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Canvas.MoveTo(X, Y); { set pen position }
end;
Pressing the mouse button now sets the pen position, setting the line’s starting point.
You just need to draw a line to the point where the user releases the button. To do that,
you’ll need to respond to a mouse-up event.
Unfortunately, you can’t see the line until you release the mouse button. In the next
section you’ll give the user some intermediate feedback by drawing temporary lines
while the mouse moves.
Mouse-move events occur even when you haven’t pressed the mouse button. You need
to add code so the application acts on mouse-move events only when the mouse button
is down.
To track whether there is a mouse button pressed, you need to add an object field to the
form object.
The problem is that each time you move the mouse, the mouse-move event handler calls
LineTo, which moves the pen position, so by the time you release the button, you’ve lost
the point where the straight line was supposed to start.
In the next section, you’ll use the Origin and MovePt fields you added to track the
starting and intermediate points.
Tracking movement
The problem with the OnMouseMove event handler as currently written is that while it
draws a line to the current position of the mouse, it draws that line from the last mouse
position, not from the original position.
➤ Now that the application tracks the origin, however, that’s easy to correct. Move the
drawing position to the origin point, then draw to the current point:
procedure TForm1.FormMouseMove(Sender: TObject;Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Drawing then
begin
Canvas.MoveTo(Origin.X, Origin.Y); { move pen to starting point }
Canvas.LineTo(X, Y);
end;
end;
That’s better, in that you now get lines to the current mouse position. Unfortunately, the
lines don’t go away, so you can hardly find the final line.
The trick is to erase each line before you draw the next one, and that means you need to
keep track of where the previous one was. That’s the purpose of the MovePt field you
added earlier.
➤ Set MovePt to the endpoint of each intermediate line, so you can use MovePt and Origin
to erase that line the next time a line is drawn:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Drawing := True;
Canvas.MoveTo(X, Y);
Origin := Point(X, Y);
MovePt := Point(X, Y); { keep track of where this move was }
end;
procedure TForm1.FormMouseMove(Sender: TObject;Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Drawing then
begin
Canvas.Pen.Mode := pmNotXor; { use XOR mode to draw/erase }
Canvas.MoveTo(Origin.X, Origin.Y); { move pen back to origin }
Canvas.LineTo(MovePt.X, MovePt.Y); { erase the old line }
Canvas.MoveTo(Origin.X, Origin.Y); { start at origin again }
Canvas.LineTo(X, Y); { draw the new line }
end;
MovePt := Point(X, Y); { record point for next move }
Canvas.Pen.Mode := pmCopy;
end;
Now you get a nice “rubber-band” effect when you draw the line. By changing the pen’s
mode to pmNotXor, you have it combine your line with the background pixels. When
you go to erase the line, you’re actually setting the pixels back to the way they were. By
changing the pen mode back to pmCopy (its default value) after drawing the lines, you
ensure that the pen is ready to do its final drawing when you release the mouse button.
You’ve come a long way with your line drawing, and as you’ll see shortly, it will all pay
off when you want to draw different shapes, such as rectangles and ellipses. Before you
can draw those shapes, however, you need to add a way for the user to choose which
shape to draw. In the next section, you’ll define a tool bar that provides those choices,
then see how to respond to the tool bar’s controls.
LineButton
RectangleButton
EllipseButton BrushButton
RoundRectButton PenButton
The default height of the tool bar is 41, and the default height of speed buttons is 25. If
you set the Top property of each button to 8, they’ll be vertically centered. The default
grid setting snaps the speed button to that vertical position for you.
LINE.BMP BRUSH.BMP
RECT.BMP PEN.BMP
ELLIPSE.BMP ROUNDREC.BMP
Responding to clicks
When the user clicks a control, such as a button on a tool bar, the application generates
an OnClick event. You handle those OnClick events by writing OnClick event handlers
for your forms. In this section, you’ll see how to respond to one such click event, and do
something useful in response.
end;
You then fill in the action you want to occur when the user clicks that button.
In this example, you’ll write several kinds of responses to speed-button clicks. For the
drawing-tool buttons, you’ll select the appropriate drawing tool. For the pen and brush
buttons, you’ll display other tool bars.
Table 12.2 Property settings for pen and brush tool bars
Component Property Value
SolidPen Glyph SOLID.BMP
Down True
DashPen Glyph DASHED.BMP
DotPen Glyph DOTTED.BMP
DashDotPen Glyph DASHDOT.BMP
DashDotDotPen Glyph DASHDOT2.BMP
ClearPen Glyph CLEAR.BMP
PenColor BackgroundEnabled False
GridOrdering go8x2
Height 30
Top 5
Width 144
PenWidth LargeChange 10
Top 12
PenSize FocusControl PenWidth
Caption 1
Top 13
SolidBrush Glyph FSOLID.BMP
Down True
ClearBrush Glyph FCLEAR.BMP
HorizontalBrush Glyph FHORIZ.BMP
VerticalBrush Glyph FVERT.BMP
FDiagonalBrush Glyph FDIAG.BMP
BDiagonalBrush Glyph BDIAG.BMP
CrossBrush Glyph CROSS.BMP
DiagCrossBrush Glyph DCROSS.BMP
Subdividing a panel
Often you want to divide a panel, particularly one used for a status bar, into multiple,
independent areas. Although you can achieve a similar effect by carefully formatting the
text in a single panel, it’s more efficient to use individual panels instead.
■ To create panels within another panel,
1 Place a new panel within the panel.
2 Set any 3-D effects you want for the new panel.
3 Set the Align property of the new panel to alLeft.
4 Move the right side of the new panel to adjust its width.
5 Clear the new panel’s caption.
6 Repeat steps 1 to 5 as needed for additional panels.
As you add new left-aligned panels to the original panel, they align to each others’ right
sides. For the last panel, you probably want to set Align to alClient, rather than alLeft, so
that the last panel takes up all remaining space in the original panel.
➤ For this example, add two panels to the status bar, named OriginPanel and CurrentPanel.
Align OriginPanel to the left and CurrentPanel to the client area.
Drawing on a bitmap
The times when you want to draw directly on a form are relatively rare. More often, an
application should draw on a bitmap, since bitmaps are very flexible for operations such
as copying, printing, and saving. Delphi’s image control is a component that can contain
a bitmap, making it easy to put one or more bitmaps into a form.
In addition, the bitmap need not be the same size as the form: it can be either smaller or
larger. By adding a scroll box control to the form and placing the image inside it, you
can draw on bitmaps that are much larger than the form or even larger than the screen.
Adding a scrollable bitmap for drawing takes two steps:
• Adding a scrollable region
• Adding an image control
Once you move the application’s drawing to the bitmap in the image control, it is easy to
add printing, Clipboard, and loading and saving operations for bitmap files.
Adding a menu
Up to this point, all the features you added to the graphics application use either direct
interaction with the mouse or manipulation of tool-bar controls to activate them. The
next few steps, however, deal with printing, loading, saving, and Clipboard operations.
Although you can invoke these operations from tool bar buttons, the standard, expected
interface for them uses menu commands.
Menu creation is not a major topic of this example, however. If you do not know how to
use the Menu Designer or how to attach event handlers to menu-item clicks, see
Chapter 3.
➤ Add a MainMenu component to the application. You can place it anywhere on the form,
but off to the side on the main tool bar is probably convenient. Create File and Edit
menu titles and the items shown in Table 12.4:
Table 12.4 Graphics example File and Edit menus
&File &Edit
&New Cu&t
&Open... &Copy
&Save &Paste
Save &as...
&Print
- <hyphen>
E&xit
The remaining steps in this chapter assume that you created these menus with the
specified captions and accepted the Name property values created by Delphi. If you
choose other names, or if you choose to activate these features with tool bar buttons, you
need to make the necessary adjustments.
Now that you have a menu, it’s a good idea to attach a handler to the File|Exit item, to
provide the standard method to terminate the application.
Printing graphics
Printing graphic images from a Delphi application is a simple task. The only
requirement for printing is that you add the Printers unit to the uses clause of the form
that will call the printer. The Printers unit declares a printer object called Printer that has
a canvas that represents the printed page.
■ To print a graphic image, copy the image to the printer’s canvas.
You can use the printer’s canvas just as you would any other canvas. In particular, that
means you can copy the contents of a graphic object, such as a bitmap, to the printer
directly.
➤ In this example, you’ll print the contents of the image control in response to a click on
Print item on the File menu:
procedure TForm1.Print1Click(Sender: TObject);
begin
with Printer do
WidthEdit
HeightEdit
Creating a dialog-box form is not the focus of this chapter, so it doesn’t present all the
details of creating the bitmap-dimensions dialog box here. You can create your own, or
you can use the one in the BMPDlg unit included with the GraphEx project. The rest of
this section assumes you use the dialog box in the BMPDlg unit.
➤ Add the BMPDlg unit to your project. You also need to add BMPDlg to the uses clause
in the unit for the main form. You can then attach the following event handler to the
File|New menu item’s OnClick event:
procedure TForm1.New1Click(Sender: TObject);
var
Bitmap: TBitmap; { temporary variable for the new bitmap }
begin
with NewBMPForm do
begin
ActiveControl := WidthEdit; { make sure focus is on width field }
WidthEdit.Text := IntToStr(Image.Picture.Graphic.Width); { use current dimensions... }
HeightEdit.Text := IntToStr(Image.Picture.Graphic.Height); { ...as default }
if ShowModal <> idCancel then { continue if user doesn't cancel dialog box }
begin
Bitmap := TBitmap.Create; { create fresh bitmap object }
Bitmap.Width := StrToInt(WidthEdit.Text); { use specified width }
Bitmap.Height := StrToInt(HeightEdit.Text); { use specified height }
Image.Picture.Graphic := Bitmap; { replace graphic with new bitmap }
CurrentFile := ''; { indicate unnamed file }
end;
end;
end;
The important aspect to understand is that assigning a new bitmap to the picture
object’s Graphic property causes the picture object to destroy the existing bitmap and
take ownership of the new one. Delphi handles the details of freeing the resources
associated with the previous bitmap automatically.
The graphic on the Clipboard could come from this application, or you could have copied
it from another application, such as Windows Paintbrush.
Summary
The sample application described in this chapter covers quite a number of issues, but
leaves several others unresolved. In particular, a polished version of the application
would likely display the name of the current bitmap file in the main form’s caption, and
would track whether the user makes changes to a picture, prompting the user whether
to save the changes before loading or creating another picture.
The skills presented, however, apply to a number of different kinds of applications. In
particular, tool bars and status bars appear in nearly all commercial applications. Using
different combinations of panels in your applications, you can make many functions
easily accessible to users.
In addition, the application uses the standard printer and Clipboard objects with
graphics, much as the sample application in Chapter 10 does with text.
Topics presented in this chapter included:
• Responding to the mouse
• Adding a field to a form object
• Refining line drawing
• Adding a tool bar to a form
13
File manager example
Chapter 13
This chapter presents all the steps necessary to create a small file manager application.
Each section in the chapter builds on the previous sections, but the individual sections
also explain discrete tasks. The material assumes you already know how to perform
most of the basic Delphi tasks, such as placing components on a form and creating a
menu. Those tasks are described in Chapter 2 and Chapter 3.
The complete application appears under the DEMOS\DOC directory and is called
FILMANEX.DPR. Figure 13.1 shows the completed application.
Figure 13.1 The complete file manager example
Note that for the DirectoryOutline component, you can use either the DirectoryOutline
on the Samples page of the Component palette or the standard DirectoryListBox
component from the System page. The DirectoryOutline component can display a more
detailed view of the directory structure of a disk.
The form with all its controls now looks like Figure 13.2.
Figure 13.2 File-manager form with controls
DirectoryOutline
FileList
DriveTabSet
DirectoryPanel FilePanel
➤ Once you have added all the components and set their properties, you should save the
project. When prompted for names, rename Unit1 to FMXWin, and Project1 to FilManEx.
Add FMXUtils to the uses clause at the top of the FMXWin unit.
➤ Before proceeding, create an OnClick event handler for the File|Exit menu item that
closes the application’s main form:
procedure TFMForm.Exit1Click(Sender: TObject);
begin
Close;
end;
Although you can generally terminate the application by double-clicking the Control-
menu box on the caption bar, it’s a good idea to provide the File|Exit option and
respond to it by closing down the application.
Now that you have the application set up, the following sections lead you through
connecting the controls and updating the status bar.
Manipulating files
There are several common file operations built into Object Pascal’s run-time library. The
procedures and functions for working with files operate at a high level: you specify the
name of the file you want to work on, and the routine makes the necessary calls to the
operating system for you. In addition, the FMXUtils unit in the directory with the file-
manager sample application provides some supplementary routines useful for this
example.
Previous versions of the Pascal language perform similar operations on files themselves,
rather than on file names. That is, you have to locate a file and assign it to a file variable
before you can, for example, rename the file. By operating at the higher level, Object
Pascal reduces your coding burden and streamlines your applications. The lower-level
functions are still available, but you shouldn’t need them as often.
These are the file manipulations that Object Pascal handles for your applications:
• Deleting a file
• Changing a file’s attributes
• Moving, copying, and renaming files
• Executing an application
The file manager example attaches all these operations to items on the File menu. Before
attaching functions to the menu items, though, it’s a good idea to make sure those items
are available only when you have a file selected. Otherwise, you would have to check
whether a file was selected each time you performed one of those functions. It’s much
Deleting a file
Deleting a file erases the file from the disk and removes the entry from the disk’s
directory. There is no corresponding operation to restore a deleted file, so applications
should generally allow users to confirm deletions of files.
■ To delete a file, pass the name of the file to the DeleteFile function. DeleteFile returns True
if it deleted the file and False if it did not (for example, if the file did not exist or if it was
read-only).
➤ The following code handles a click on a File|Delete menu item by deleting the selected
file in a file list box, then updating the list so it reflects the deletion.
procedure TFMForm.Delete1Click(Sender: TObject);
begin
with FileList do
if DeleteFile(FileName) then Update;
end;
The application now deletes the selected file in response to either File|Delete or the Del
key, which is the shortcut for that menu item.
CurrentDir
FromFileName
ToFileName
Once you’ve designed the dialog box, you can open it from an event handler shared by
the Move, Copy, and Rename items on the File menu by doing the following:
1 Double-click the main-menu component (not the File menu itself) on the main form
to open the Menu Designer.
2 In the Menu Designer window, choose File|Move.
3 Choose the Events page in the Object Inspector.
4 Click in the Handler column next to the OnClick event.
5 Type in FileChange and press Enter.
Delphi generates an event handler called FileChange.
6 In the Menu Designer window, choose File|Copy and set its OnClick handler to
FileChange.
7 Repeat step 6 for File|Rename.
Executing an application
Many times an application needs to execute another application, either to perform a
specific task or just to have that application run concurrently. The Windows API
provides a function, ShellExecute, that executes an application, but it requires a number
of parameters superfluous to Delphi applications. The FMXUtils unit provides a more
useful alternative, called ExecuteFile.
ExecuteFile operates in two different ways. If passed the name of an executable file,
ExecuteFile runs that application. If passed the name of a document with an associated
application, ExecuteFile runs the application, automatically opening that document at
startup.
Dropping items
Once a control indicates that it can accept a dragged item, it should then also define
some way to handle the item should it be dropped. If a user sees the mouse cursor
change to indicate that a control will accept the item being dragged, it is reasonable for
the user to then expect that dropping the item there will accomplish some task.
■ To handle dropped items, attach an event handler to the OnDragDrop event of the
control accepting the dropped item.
Like the drag-over event, the drag-drop event indicates the source of the dragged item
and the coordinates of the mouse cursor over the accepting control. These parameters
enable the drag-drop handler to get any needed information from the source of the drag
and determine how to handle it.
➤ For example, a directory outline accepting items dragged from a file list box can move
the file from its current location to the directory dropped on:
procedure TFMForm.DirectoryOutline1DragDrop(Sender, Source: TObject; X,
Y: Integer);
begin
if Source is TFileListBox then
with DirectoryOutline do
ConfirmChange('Move', FileList.FileName, Items[GetItem(X, Y)].FullPath);
end;
Dragging and dropping now has the same effect as using File|Move, but the user
doesn’t need to type in the file name.
Summary
The sample application in this chapter demonstrates a number of widely useful tasks,
including specific applications of some outline, list-box, and tab-set controls, using
image controls to store hidden bitmaps, dragging and dropping within an application,
and manipulating files.
There are a number of other features you would probably want to add to the application
for real use, such as dragging and dropping to the drive tab set, handling of multiple file
selections, and display of file information other than the size. All of these are
straightforward extensions to the existing application.
Using DDE
Dynamic Data Exchange (DDE) sends data to and receives data from other applications.
With Delphi, you can use this data to exchange text with other applications. You can
also send commands and macros to other applications, so your application can control
other applications.
Here’s a typical way to use DDE: a link between two applications is established, either
by your application or the other application. Once this link (called a conversation) is
established, the two applications can continuously and automatically send data back
and forth. A typical use for DDE is to exchange text data. When the text changes in one
application, DDE automatically updates the text in the other. For example, in the
Linked text
Note Not all applications support DDE. To determine whether an application supports DDE,
refer to its documentation.
To understand DDE applications, you need to become familiar with the concept of DDE
conversations.
DDE conversations
In order to have a DDE conversation, there must be a DDE client application and a DDE
server application. The application that requests data is the client. The application that
provides the requested data, and updates the DDE client, is the DDE server. With
Delphi, you can create both DDE clients and DDE servers. In fact, a single Delphi
application can be both a DDE client and a DDE server at the same time. A DDE
conversation is defined by its service, topic, and item.
Note Sometimes DDE clients are called destinations, and DDE servers are called sources. The
terminology is interchangeable.
This section explains
• DDE services
• DDE topics
• DDE items
DDE services
The service of a conversation is the name of the DDE server. Typically, this is the server
application’s main executable file without the .EXE extension. For example, if you want
your application to establish a conversation with Novell Quattro Pro 6.0 (QPW.EXE),
the conversation service is QPW.
Sometimes, however, the service differs from the main executable file name. For
example, if you want your application to establish a conversation with Borland
ReportSmith 2.0 (RPTSMITH.EXE), the DDE service would be ReportSmith.
DDE topics
The topic of a DDE conversation is a unit of data, identifiable to the server, containing
the linked information. Typically, the topic is a file. For example, if the data you want to
share is in the Quattro Pro notebook file NOTEBK1.WB2, the topic would be
NOTEBK1.WB2; the full file name is used, including the extension.
If the server is a Delphi application, the topic is (by default) the caption of the form
containing the data you want to link. For example, if you want to link to text in a form
with a Caption of MyApp, the topic would be MyApp. (Optionally, you could use the
name of a DDEServerConv component as explained in “Creating DDE server
applications” on page 388.)
DDE items
The item of a DDE conversation identifies the actual piece of data to link. The syntax
used for specifying the DDE item depends on the DDE server application. Examples of
possible DDE items are spreadsheet cells or database fields. For example, to link to cell
A1 on page A in a Quattro Pro notebook, the item would be $A:$A$1..$A$1.
If the server is a Delphi application, the item is the name of the linked DDEServerItem
component. For example, to establish a conversation with the DDE server component
named DDEServer1, the item would be DDEServer1. DDEServerItems are discussed in
“Creating DDE server applications” on page 388.
Note See the documentation for the DDE server for specific information about specifying the
application, topic, and item of a conversation.
Requesting data
Some DDE items aren’t passed automatically in a DDE conversation. Instead, the client
must explicitly request a specific item to be updated by the DDE server. Also you might
want your client application to obtain data from a DDE server once, and not be
continually updated by the DDE server. In these cases, your DDE client should request
to be updated with the RequestData method.
Note To determine if your DDE client must explicitly request to be updated, see the
documentation of the DDE server application.
■ To request data, use the RequestData method of a DDEClientConv component. Specify
the item to request as a parameter of RequestData. The item is the simply a DDE item.
RequestData returns a PChar null-terminated string containing the requested text.
The requested data is given to the DDE client only in the return value of RequestData.
Even if the DDEClientConv component is connected to a DDEClientItem component,
RequestData won’t update the values of the Text or Lines properties of the
DDEClientItem. Search online Help for RequestData for more information about this
method.
➤ For example, to request the data from cell A1 on page A in a Quattro Pro notebook, and
store the data in a PChar variable named TheData, execute the following code:
TheData := DDEClientConv1.RequestData('$A:$A$1..$A$1');
Note The memory for the PChar string returned by RequestData must be freed after your
application is finished with it. Use the StrDispose function to do this.
➤ For example, after your application has processed TheData, you should deallocate it
with the following code:
StrDispose(TheData);
Poking data
Poking data means sending data from your DDE client application to the DDE server
application, directly opposite the usual data flow direction for DDE.
Using OLE
This section explains
• What is OLE?
• Creating OLE container applications
• OLE data in files
What is OLE?
Object Linking and Embedding (OLE) is a method for sharing data among applications.
To use OLE, one application must be an OLE server, and another application must be an
OLE container. With Delphi, you can create OLE container applications.
An OLE server is an application that can create and edit an OLE object. An OLE
container is an application that can contain an OLE object. An OLE object is simply the
data shared by the two applications. Examples of OLE objects are documents,
spreadsheets, pictures, and sounds.
Here’s a typical way to use OLE: the OLE container application displays a picture
representing the OLE object. The user activates the OLE object, typically by double-
clicking the picture. When the OLE object is activated, the OLE server application opens,
and the user can edit the OLE object using the OLE server. Then the user updates the
OLE object within the OLE container and closes the OLE server.
Note Not all applications support OLE. To determine whether an application supports OLE,
refer to its documentation.
This section explains
• OLE 1.0 and OLE 2.0
• Design-time and run-time object creation
• Linking and embedding
• OLE classes
Note At design time, an object can’t be activated in place. The OLE server activates in its own
window, not in place, even if the object supports in-place activation. At run time,
however, objects that support in-place activation are activated in place.
Linked objects
Linked objects are stored in files. You can’t create a new OLE link unless the OLE object
has previously been saved to a file from within the OLE server application.
The data in an linked OLE object file can be modified by your OLE container application
and by other applications. The OLE server application and other OLE container
applications can all access and modify the OLE object. Data can exist in one location but
be accessible from multiple applications.
You can program your OLE container application in Delphi to continually obtain the
latest data from the OLE object file. When the OLE object data is modified, even by other
applications, the changes will appear in all OLE container applications that contain a
link to the file, including your own.
Embedded objects
Embedded objects are stored in your OLE container application. Other OLE container
applications can’t access the OLE object. The only time the embedded OLE object can be
edited is when the user activates the object from your OLE container application. Only
then can the OLE server edit the OLE object data.
Embedded OLE objects don’t need to exist in files. All the data can be stored in your
container application. This ensures that the OLE data cannot be accidentally deleted,
modified, or corrupted by being stored in an external file. The drawback is that the size
of your OLE container application increases by the size of the included OLE data.
If you want to make the changes you make to the embedded OLE object appear the next
time you run your application, save the OLE data to a file. See “OLE data in files” on
page 395 for more information.
OLE documents
The document of an OLE object determines the source file that contains the data for the
OLE object. The object document must be used for a linked object, because linked
objects exist in files. The object document is used for an embedded object only if you
create the object from an existing source file. If you create a new embedded object that
doesn’t yet exist in a file, you would not specify an OLE document.
For example, if the OLE object is linked to the Quattro Pro notebook TUTOR.WB2
stored in the D:\OFFICE\QPW directory, the OLE document would be D:\OFFICE\
QPW\TUTOR.WB2.
Note The OLE document must be specified only for linked objects. For embedded objects,
only the OLE class should be specified.
OLE items
The item of an OLE object determines what portion of an OLE document contains the
data to link or embed. Items are used when you want the OLE object to contain a smaller
piece of data than an entire document file.
For example, if the OLE object is linked to the cell range B4 to B5 of the page titled
GasCosts in a Quattro Pro notebook, the OLE document would be
$GasCosts:$B$4..$B$5.
Note The OLE item must be specified only for linked objects. For embedded objects, only the
OLE class should be specified.
Note You don’t need to use the OLE item if the OLE object will not contain a piece of data
more specific than the file specified in the OLE document.
3 If you want to insert an object that has already been created and saved in a file by the
OLE server, choose Create From File. Specify the file name and path to the OLE object
file. To link the object, select the Link check box.
If you want to embed a new object, choose Create New and select an OLE object from
the Object Type list. You cannot link a new object, since it has not yet been saved as a
file.
4 Choose OK.
If you are creating a new object, the OLE server becomes active. From the OLE server,
you can edit the OLE object. When you have finished creating the OLE object, update
the OLE server and close the OLE object in your OLE container application.
Typically, do this by choosing File|Close or File|Update within the OLE server
application.
5 The ObjClass property now contains the appropriate value for the OLE class, and the
OLEContainer component contains a picture representing the OLE object. If the OLE
object was created from an existing file and you inserted a linked object, the ObjDoc
property contains the appropriate value for the OLE document.
■ If you have access to the OLE server application and data, you can paste an OLE object
containing an OLE item at design time:
1 Activate the server application and select the item to be contained (in the OLE object)
by your OLEContainer component.
2 Copy the data and OLE object information to the Clipboard from the server
application. Typically, do this by choosing Edit|Copy.
3 Activate Delphi and select the OLEContainer component.
Summary
This chapter presented these topics:
• DDE conversations
A DDE client application and DDE server application exchange text data in a DDE
conversation. A conversation is defined by its service (name of the server), topic (file
containing the linked data), and item (the actual text to link).
• Creating DDE client applications
To create a DDE client, add a DDEClientConv component and a DDEClientItem
component to a form. Client applications can request to be updated by the server
with the RequestData method. Client applications can poke data (send data to the
server) with the PokeData method. Clients can control the server by running it or
sending macros with the ExecuteMacro method.
• Creating DDE server applications
To create a DDE server, add a DDEServerItem component (and optionally, a
DDEServerConv component) to a form. You can then copy DDE data to the
Clipboard with the CopyToClipboard method and paste the link in the client
application.
• What is OLE?
With OLE you can link or embed OLE objects in a container application. An OLE link
is defined by its class (name of the application that created the object), document
(name of the file containing the object), and item (the portion of the document
containing the OLE object to link).
• Creating OLE container applications
To create an OLE container application, add an OLEContainer component to a form.
Then, you can use the Insert Object dialog box to specify the ObjClass or ObjDoc
properties, and the Paste Special dialog box to specify the ObjItem property. You can
also drag-and-drop from an OLE server to embed an OLE object at design time.
• OLE data in files
You can use the SaveToFile method to save OLE data in a file, and the ReadFromFile
method to read OLE data from a file.
15
OLE example
Chapter 15
Now that you have read the material in Chapter 14, you’re ready to practice exchanging
data with Object Linking and Embedding (OLE) by building a simple application.
This chapter assumes you are familiar with basic OLE terms such as objects, linking,
embedding, and OLE servers. It presents the steps involved in building a simple OLE
container application that allows the user to insert, paste, and drop OLE objects into
Multiple Document Interface (MDI) child windows. The application uses Windows
common dialog boxes to save and open OLE objects.
Note The material presented in this chapter assumes you are familiar with the MDI
application and common dialog material discussed in Chapter 10. The OLE example is
also an MDI application that uses Windows common dialog boxes, but this example
focuses on creating an OLE container application. If you are unfamiliar with creating
MDI applications or using common dialog boxes, read Chapter 10 first.
The complete application appears under the DEMOS\DOC directory, and is called
OLE.DPR. Figure 15.1 shows the application as it appears the first time a new window is
opened.
Figure 15.1 The completed OLE container application
Property Value
Caption OLE Example
Next, you need to add an MDI child form. The MDI child will be displayed within
OLEFrameForm at run time.
➤ Add a new form to the project and use the Object Inspector to set the following
properties of the new form:
Property Value
Caption OLE Object
FormStyle fsMDIChild
Name OLEObjectForm
Since this application will create instances of OLEObjectForm dynamically at run time, it
should not create an instance of OLEObjectForm automatically.
➤ Remove OLEObjectForm from the Auto-create list for the project.
1 Choose Options|Project to display the Project Options dialog box.
2 On the Forms page of the Project Options dialog box, move OLEObjectForm from the
Auto-create forms list box to the Available forms list box.
3 Choose OK.
➤ Save the project now, using the following names:
Property Value
Name OLEContainer
Top 8
Left 8
Height 96
Width 192
Any menu items in your container application that have a GroupIndex property value of
1, 3, or 5 will be replaced by the menu items with corresponding index values from the
OLE server application when an OLE object is activated in place. In this example, you’ll
&File
&New
&Open...
- <hyphen>
E&xit
By default the value of the GroupIndex property for the File menu title is 0, which is what
you want. Later in the example, when you activate an OLE object, the menus merged
from the OLE server application will be inserted to the right of the File menu because
their index values are greater than 0.
Next, you will program the sample application to create and show a new
OLEObjectForm window.
➤ To be able to create OLE object forms, the unit where OLEObjectForm is declared must
be referenced by the OLEFrame unit. Add the OLEObj unit name to the uses clause of the
interface section of the OLEFrame unit.
interface
3 Specify the GroupIndex property values for the File, Edit, Object, and Window menu
titles as shown in the following table:
Menu GroupIndex
File 0 (default)
Edit 1
Note The GroupIndex property of the Edit menu has the same value (1) as the index of the Edit
menu group from the OLE server. When an OLE object is activated in place, the Edit
menu item group from the OLE server replaces the Edit menu from OLEObjectForm. The
other menu item groups from the OLE server are merged with the menu of
OLEObjectForm.
The OnClick event handlers for the New and Exit menu items on the File menu of the
OLEObjectForm menu bar simply call the corresponding event handlers of the
OLEFrameForm menu bar.
➤ To be able to call methods of OLEFrameForm, the unit where OLEFrameForm is declared
must be referenced by the OLEObj unit. Add a uses clause to the implementation part
of the OLEObj unit, and refer to the OLEFrame unit.
implementation
Property Value
Name ToolBarPanel
Align alTop
Caption <Blank>
Locked False (default)
Note The OLE server will replace ToolBarPanel when an OLE object is activated in place
because the control is not locked.
Property Value
Name StatusBarPanel
Align alBottom
Caption <Empty string>
Locked True
Note The OLE server cannot replace StatusBarPanel when an OLE object is activated in place
because the control is locked.
When an OLE object is active and the OLE server has a message to display in the status
bar, an OnStatusLineEvent event of the OLE container component occurs. A text string is
passed from the OLE server to this event handler. The Msg parameter of the
OnStatusLineEvent event handler contains the text from the OLE server.
■ To display status bar messages from OLE server applications, assign the value of the
Msg parameter of the OnStatusLineEvent handler to the Caption property of the status
bar panel.
➤ Write the following event handler for the OnStatusLineEvent event of OLEContainer in
OLEObjectForm:
procedure TOLEObjectForm.OleContainerStatusLineEvent(Sender: TObject; Msg: String);
begin
OLEFrameForm.StatusBarPanel.Caption := Msg {Display Msg in status bar}
end;
➤ Save the project now, then run it.
Inserting objects
At this point, the OLE example application is ready to contain OLE objects. This section
describes the following steps involved in inserting OLE objects at run time:
• Using the Insert Object dialog box
• Initializing the OLE container
• Deactivating objects
Deactivating objects
If the OLE object was created by an OLE 1.0 server, it is activated in the OLE server’s
window. Focus and control transfer to the OLE server when an OLE object is activated
within its own window.
■ To deactivate an OLE object created by an OLE 1.0 server, choose the OLE server’s File|
Exit command (or its equivalent in the command structure of the OLE server).
If the OLE object was created by an OLE 2.0 server, it might activate in the OLE
container application’s window (if the OLE server application supports in-place
activation and you’ve added a MainMenu component to the main form of your
container application). The File|Exit command from the OLE server isn’t available
because the available File menu (or any menu with a GroupIndex of 0) is from the OLE
container application.
■ To deactivate an OLE object created by an OLE 2.0 server, focus must shift to a control in
the OLE container application other than the OLEContainer component containing the
active OLE object. You can also deactivate the object by clicking in the client area of the
form that contains the OLEContainer.
Note Shifting focus to another control does not deactivate an OLE object activated in its own
window (rather than in place). Also, shifting focus to a menu item does not deactivate
an OLE object.
■ Another way to deactivate an in-place active OLE object is to set the value of the Active
property of the OLEContainer component to False.
In the sample application, use the Object|Deactivate menu command from the menu
bar of OLEObjectForm to do this. Recall that the Object menu was given a GroupIndex
property value of 2, so it is still available when an OLE server merges menus with the
OLE container application.
➤ Write the following event handler for the OnClick event of the Object|Deactivate item
on the OLEObjectForm menu bar.
type
ƒ
➤ Declare the Fmts array in the public part of the OLEFrameForm type declaration. Fmts is
public instead of private for this example because it is referenced from the OLEObj unit.
type
TOLEFrameForm = class(TForm)
ƒ
private
ƒ
public
Fmts: array[0..1] of BOleFormat; {Declare the array of OLE formats}
end;
Dropping objects
Dragging OLE objects from an OLE server application and dropping them on the OLE
container application is an easy way to link or embed an OLE object into the OLE
example application. By dragging and dropping, the user isn’t required to use the Insert
Object or Paste Special dialog box to specify an OLE object. The user simply “grabs” the
OLE object from the OLE server with the mouse, drags it over the OLE example
application, and drops it by releasing the mouse button.
Note The material presented in this section assumes you are familiar with the general
concepts of drag-and-drop covered in Chapter 13. The OLE example also uses drag-
and-drop, but this example focuses on the registration of OLE object formats. If you are
unfamiliar with drag-and-drop in general, you should read Chapter 13 first.
This section describes the following steps involved in dragging-and-dropping OLE
objects onto the OLE example application:
• Registering a form as an OLE drop target
• Dropping an OLE object onto the OLE example application
Property Value
Name SaveAsDialog
DefaultExt ole
FileName *.OLE
Filter OLE files (*.OLE)|*.OLE
➤ Write the following event handler for the OnClick event of the File|Save As item on the
OLEObjectForm menu bar.
procedure TOLEObjectForm.Saveas1Click(Sender: TObject);
begin
if SaveAsDialog.Execute then
OLEContainer.SaveToFile(SaveAsDialog.FileName) {Save the object to FileName}
end;
Property Value
Name OpenDialog
DefaultExt ole
FileName *.OLE
Filter OLE files (*.OLE)|*.OLE
➤ Write the following event handler for the OnClick event of the File|Open item on the
OLEFrameForm menu bar.
procedure TOLEFrameForm.Open1Click(Sender: TObject);
var
Summary
This chapter presented these topics:
• Creating the MDI framework
For this example, each OLE object that is linked or embedded is contained in an OLE
container component in its own MDI child window. To contain an OLE object, add
an OLEContainer component to the OLE Object window. When an OLE object is
activated in place, menu items from the OLE server can be merged with the OLE
container application’s menus. To control where menu items merge and which menu
items are replaced, specify appropriate values for the GroupIndex property of menu
items. OLE servers can also access the OLE container application’s tool bar and menu
bar. Use the Locked property to prevent the OLE server from replacing the tool bar or
status bar of the OLE container application.
• Inserting objects
To enable the user to use the Insert Object dialog box to insert an OLE object into the
OLEContainer component, call InsertOLEObjectDlg. To initialize the OLEContainer
component, assign a pointer modified by InsertOLEObjectDlg to the PInitInfo
property. To deactivate the OLE object, shift focus to another control, click the client
area of the form that owns the OLEContainer, or set the Active property to False.
• Pasting objects
To register new Clipboard formats for OLE objects, call the Windows API function
RegisterClipboardFormat. To register the Clipboard formats for OLE objects (or any
other data type you want to be able to drop) in the same way as when pasting objects,
call RegisterClipboardFormat and specify an array of BOLEFormat elements. To enable
the user to use the Paste Special dialog box to paste an OLE object into the
Selected Bibliography
Appendix A
A
The following third-party titles are available to help you learn more about Delphi and
the Object Pascal programming language. For details concerning availability of any of
these books, please consult your local bookseller.
• The Delphi Programmer Explorer by J. Duntemann/J. Mischel/D. Taylor
Coriolis Group, ISBN: 1-883577-25-X$39.99
A new type of tutorial: Theory and practice alternate in short chapters, with the
emphasis on creating useful software starting on the very first page.
• Delphi for Dummies by Neil Rubenking
IDG Press, ISBN: 1-56884-200-7$19.99
Readers will learn about Borland's new language in the easy to understand style of
the Dummies series.
• Teach Yourself Delphi by Devra Hall
MIS Press, ISBN: 1-55828-390-0$27.95
Here is a complete, self-guided tour to the new development environment from
Borland, encompassing all the features of the language and all the tools, tricks, and
advantages of Delphi.
• Delphi Nuts and Bolts by Gary Cornell and Troy Strain
Osborne-McGraw-Hill
• Software Engineering with Delphi by Edward C. Webber, J. Neal Ford, and
Christopher R. Webber
Prentice Hall Professional, Trade & Reference
A guide to developing client/server applications with an emphasis on Delphi’s
object-oriented tools.
• Delphi by Example by Blake Watson
Que, ISBN: 1-56529-757-1$29.99
Index 431
AllowAllUp property 334 arrays 199–203 AutoSize property 58
ampersand (&) character 20, 102 See also indexes
ancestor objects 221, 223, 226 accessing elements 199 B
See also inheriting from objects character 200–203
Answer tables (databases) 40 debugging 260, 263 backdrops 47
apostrophes (‘) in strings 200 declaring 200 backgrounds, repainting 317
application files See project files as types 199 backing up files 139, 302–303
application icon 116, 128 defined 199 backup files 116, 117
Application page (Project initializing 200 bar gauges 42
Options) 128 multidimensional 200 BatchMove component 40
applications 75, 96, 126, 224 pixel 314–315 begin reserved word 165, 167,
See also projects string 171, 270 175
zeroing 199 begin..end blocks 174–177
client See DDE applications
as modal form 86 case statements 167
closing 350
file-manager example 362 as operator 238 if statements 165
OLE example 404 as reserved word 228 nesting 176
text editor example ASCII characters 156 BeginDrag method 376
309–312 debugging 262 Bevel component 39
container See OLE ASCII text files beveled panels 346
applications reading from 95 BevelInner property 346
developing 7–33, 37, 80 saving forms as 94 bibliography 429
fundamentals 14–22 assigning icons to forms 94 BiGauge component 42
tools 9–10, 121 assigning types 157 biMazimize constant 87
distributing 22 constants 158 biMinimize constant 87
executing 17, 143, 250, 251, variables 154 binary files 116
375–376 assigning values 151–153 saving as text 94
pausing execution 253, See also setting property BiPict component 42
254, 264 values BiSwitch component 42
to breakpoints 253, 254, fields in records 205 biSystemMenu constant 87
258 functions 161, 186 BitBtn component 39, 88
to specific locations 251, placing limits 197 bitmap buttons 39
254 to strings 200 adding to dialog boxes 88–89
file-manager 359–379 type compatibility and 157 custom 89
initializing 116 zeros, to arrays 199 Bitmap property
Multiple Document Interface assignment operator (:=) 151 brushes 316
See MDI applications equal (=) operator vs. 158 bitmapped flags 371
naming 128 assignment statements 151–153, bitmaps 117, 347–350
predesigned 10 199
robust 231 See also graphics
enumerated types and 195 as form icon 94
sample 267 function calls 161
scrollable regions 348 associating with strings
object variables 226 275–276, 366
server See DDE applications; type compatibility 157 blank 349
OLE applications AssignPrn procedure 305, 307 destroying 354
specifying icons 94 associating bitmaps with displaying 39, 42
starting 119 strings 275–276, 366 editing 14
testing 141, 143, 248 at reserved word 245 file-manager example
version control 94, 144 attributes 366–367
word-processing 280 See also properties draw-item events 369
Archive Manager command file 371–373, 376 measure-item events 368
(Workgroups) 144 reading 371 scrolling 348
arcs 318 setting 373 temporary 348, 349
arguments See parameters AutoActivate property 412, 414 bitwise operators
arranging icons auto-creating forms at run file attributes and 372
child windows 287 time 113–114 bkAbort constant 89
array types 199–203 automatically opening files 375 bkAll constant 89
automatically saving files 31 bkCancel constant 89
Autosave options 31, 123
Index 433
ClearSelection method viewing 12, 79, 139 compatibility of types 157
memos 292 Code Editor window 141 Compile command
clicking mouse buttons 323, 324, debugger and 251 (Compile) 142
326, 334 shared events 65 Compile menu 141
See also mouse events specific event handlers 63 compiler directives 120
client/server applications See Code Editor 62–64, 124 conditional compilation 143
DDE applications; OLE adding pages 62 range checking 199
applications closing pages 141 Compiler Options dialog
Clipboard 291–292 deleting breakpoints 256 box 249
DDE links and 384, 389 event handlers and 60, 63–64, Compiler page (Project
formats 416, 418–420 65 Options) 128
registering 417, 418 moving through 62
compiler-generated files 117
returning 419 overview 11–12
renaming components 44 compiling options 32, 128, 129
graphics and 354–356 command-line
testing for images 356 running projects to specific
locations 251 arguments 250
OLE objects and 394, 415–421 compiling projects 141–144
testing for 420 saving project files 138
setting breakpoints 254 returning status 143
Clipboard object 291 specific parts 143
ClipBrd unit 354 setting watches 259
switching to forms 62 starting compiler 142
Clipbrd unit 291 COMPLIB.DCL 42
CLIPBRD.PAS 291 viewing pages 62–63
colon (:) component classes 72
clock 38 component exceptions 242
function declarations 161
Close buttons 89 variable declarations 155 Component Expert 71–72
Close method Component Expert dialog
Color common dialog box 41
forms 309, 311 box 71
color grids 42, 344
CloseQuery method 309, 310 component libraries 42, 71
Color property
closing applications 350 brushes 316, 345 adding components 69, 70
file-manager example 362 pens 315, 343 creating 68, 72
OLE example 404 customizing 68–73
ColorDialog component 41
text editor example 309–312 deleting components 68, 69
ColorGrid component 42
closing dialog boxes 87 rebuilding 42, 68, 69, 70
closing windows 309, 309–310 colors 42
brushes 316 replacing 73
code 27, 60–68, 150–151, 219 reverting to previous
pens 315, 343
See also source code pixels 314, 315 versions 71
browsing 13 ColWidths property 368 Component list 11
case sensitivity 150 Component palette 37, 38–42
combo boxes 39, 41
comments in 150 adding components 42
data-aware 40
controlling flow 163–174 customizing 68
editing 19, 62 items See string lists
deleting components 68
as ASCII text 94 owner-draw controls 365–369
measure-item events 368 moving components 69
event handlers 63, 66 overview 10
while debugging 255, variant styles 365
ComboBox component 39 pointer icon 38
262, 264 components 37–60, 221–222
executing repeatedly 168 command buttons See buttons;
speed buttons See also specific types
indenting 150, 165 accessing 223
line breaks 150 command-line options See
adding 44–45, 209
machine 210, 249 compiling options container 48
optimizing 183, 339 comments in code 150 multiple 44, 47
protecting 231–234 common dialog boxes 85, 206, new 121
stepping through 252–253 228, 295–304 overview 15
statement by See also specific third-party 42, 68, 69, 70
statement 252 adding 41 aligning 50–52
to first executable Help buttons 296 with grids 52
statement 253 listed 41 copying 47, 49–50
testing conditions 163, 166, options 296 to containers 48
174 Comp data type 156 customizing 10, 11, 53, 59, 71
comparing values 158, 164 data-aware 40
Index 435
database servers 40 deallocating memory 229, 234, not within scope 178
databases 40 235, 273 object types 188
querying 40 debugger 13, 247 objects 217, 222, 224, 228
DataSource component 40 exception handing 238 exception 244
DBCheckBox component 40 restarting 253, 264 procedures 158, 185, 189
DBComboBox component 40 standalone 249 type 26, 185, 186, 195–205
DBEdit component 40 starting 249, 250 enumerated 335–336
DBGrid component 40 debugging options 32, 249 variables 154–157, 217
DBImage component 40 debugging projects 247–265 character arrays 200
bugs, types 247–248 example 226
DBListBox component 40
changing breakpoint for statements and 170
DBLookupCombo procedures and 160
component 40 properties 257–258
coloring breakpoints 258 text editor example 299
DBLookupList component 40 decrementing values 172
DBMemo component 40 editing code 255, 262, 264
examining variables 258–263 default buttons 88
DBNavigator component 40 Default property 88
DBRadioGroup component 40 disabling watches 260
setting watches 259–261 defaults 123, 127
DBText component 40 values, changing 261, brushes 316
.DCL files 68 262–263 component names 55
.DCU files 117, 121, 210 execution point 251, 253, 258 components 38–42
DDE applications 381–390 flickering screens 250 form names 55
accessing data 41, 385, 386 generating debugging forms 86
client 41, 383–388 information 249–250 pens 315
defined 382 handling exceptions 264 restoring 127
executing macros 387 invalid breakpoints 255, 258 defining new types 185, 186,
updating data 386, releasing system 195–205
388–390 resources 254 DEFPROJ.OPT 127
items, defined 383 running applications 250, 251 Delete All Breakpoints command
linking data 383, 384–386, 389 pausing execution 253, (Breakpoint List window) 256
at run time 383, 385, 388 254, 264
OLE applications vs. 396 Delete All Watches command
to breakpoints 253, 254, (Watch List window) 260
poking data 386 258
server 41, 388–390 Delete Breakpoint command
to specific locations 251, (Breakpoint List window) 256
activating 254
disconnected 387 Delete command (Edit) 50
setting breakpoints 254–255
connecting to 384–386 after execution begins 255 Delete command (Menu
defined 382 conditional 257–258 Designer) 105
receiving data 386 stepping over statements 252 Delete method
services, defined 382 stepping through code strings 271, 276
topics, defined 383 252–253 Delete procedure 201
DDE conversations 382–383 statement by Delete Templates command
initiating 41, 383 statement 252 (Menu Designer) 105, 107
DDE Info dialog box 384 to first executable Delete Templates dialog box 107
DDE links 385 statement 253 Delete Watch command (Watch
pasting 384, 389 strategy 248 List window) 260
testing 389 turning off breakpoints 256 DeleteFile function 370
DDEClientConv component 41, viewing function calls deleting
383, 384, 385 263–264 borders 289
DDEClientItem component 41, decimal numbers 156, 262 breakpoints 256
383 declarations 174, 177, 186, 206 components 49, 50
DDEConv property 383 arrays 200 from libraries 68, 69
DDEItem property 385 as types 199 event handlers 67–68
DDEServerConv component 41, begin..end blocks 175 files 135, 370–371
388 constants 157–158 forms from projects 135
DDEServerItem component 41, forward 189–190 graphics 355
388 functions 161, 185, 189 menu items 102, 105
DDEService property 385 identifiers 153–157, 189 menu templates 107
DDETopic property 385 as enumerated types 196 strings 271
Index 437
drop-down lists See combo EDivByZero exception 237 ERangeError exception 237, 242
boxes; lists boxes EFault exception 238 erasing images 355
drop-down menus 38, 103 EGPFault exception 238 erasing lines 330
See also menus EInOutError exception 237 error codes 237
.DSK files 117 EIntError exception 237, 241, 242 error messages 141
duplicate accelerators 103 EIntOverflow exception 237 disabling 243
duplicate identifiers 181, 223 EInvalidCast exception 238 generating 240, 242
Dynamic Data Exchange See EInvalidOp exception 238 getting help with 142
DDE applications EInvalidOpCode exception 238 ErrorAddr variable 244
dynamic-link libraries 77, 117 EInvalidPointer exception 237 errors 231, 244
creating 134, 141 Ellipse method 317 See also exceptions
ELLIPSE.BMP 333 checking 232
E ellipses 39, 317 clearing conditions 232
divide-by-zero 235, 237, 238,
ellipsis (...) in Value column 56
EAbort exception 243 else reserved word 239
EBreakpoint exception 238 case statements and 167 fatal application 240
EConvertError exception 238 except reserved word logic 248
edit boxes 38, 83, 225 and 241 out-of-range 199, 237, 243
See also combo boxes if statements and 164 overflow 237, 238
data-aware 40 EMathError exception 237 range 199
DDE applications and 386, embedding OLE objects 392 run-time 247–248
390 Enable All Watches command syntax 154, 158, 159
incremental values 42 (Watch List window) 260 type mismatch 155
Edit Breakpoint command Enable Breakpoint command undefined forward 67
(Breakpoint List window) 257 Esc key 88
(Breakpoint List window) 256
Edit Breakpoint dialog box 257 ESingleStep exception 238
Enable Watch command (Watch
Edit command (Watch List EStackFault exception 238
List window) 260
window) 259 Enabled property 91 EUnderflow exception 238
Edit component 38 menus 110, 292 Evaluate/Modify command
Edit Source command speed buttons 333 (Run) 261
(Breakpoint List window) 256 end reserved word 165, 167, 175 Evaluate/Modify dialog
Edit Source command (Call exception handling 232 box 261–263
Stack) 264 standing alone 210 event handlers 49, 60, 188, 218
Edit Tab Order dialog box 90 Enter key 88 allocating memory 235
editing enumerated types 166, 195–197 associating events with 64–67
See also changing constants vs. 335 shared events 65
code 19, 62 declaring 335–336 calling procedures and
as ASCII text 94 identifiers as 196 functions 20–21
event handlers 63, 66 environment 232 changing tabs in
while debugging 255, options 123–124 notebooks 363
262, 264 defined 158
Environment command
data 40, 392 deleting 67–68
(Options) 28, 123
forms as ASCII text 94–95 drawing lines 324, 325
Environment Options dialog editing 63, 66
graphics 14 box 28, 68, 123
menu items 105 locating specific 63
environment preferences, menus 109–110
project files 23, 132 setting 28–32
text 38 as templates 108
EOutOfMemory exception 237 handling events 294
Editor Colors page (Environment EOverflow exception 238
Options) 258 naming 66
EPageFault exception 238 overview 18–19
Editor files option 124 EProcessorException redrawing images 316
editors 279 exception 238 renaming files 353
Code See Code Editor equal sign (=) responding to button
Filter 298 as relational operator 164 clicks 334, 336
Image 14 constant declarations 158 reusing 64, 65
Picture 332, 333 type declarations 186 saving files 353
property See property editors equal values 158 selecting items in lists 364
Index 439
saving 301–303, 310, 353 form files 116, 129 specifying at run time 112
automatically 31 backup 117 specifying default 125
selecting types 297 sharing 134–135 moving among 79, 140
size, returning 364 form grid 52 multi-page 39
swap 238 Form SpeedMenu 93 naming 17, 55, 59
writing to 301 Form Templates 10, 29 objects and 216–218
FileSetAttr procedure 373 See also Forms Gallery OLE objects and 393, 395, 401
fill patterns 316, 344 adding to galleries 93, predesigned 10
FILMANEX.DPR 359 126–127 referencing 77
Filter editor 298 adding to projects 78–79 resizing 44
FilterComboBox component 41 loading 29 reusing 38, 76
filters 41, 297–298 opening for reference 79 saving 58
Filters property 298 specifying as default 125 as ASCII text 94
finally reserved word 235 Form Templates page (Gallery as templates 93–94
Find common dialog box 41 Options) 125, 126 sharing 76–94
formal parameters 191, 193, 194 source code, viewing 23, 141
FindDialog component 41
actual parameters vs. 191 specifying default 125–126
finding event handlers 63 testing 112
finding specific strings 270–271, formats
Clipboard 416, 418–420 Forms Gallery 29, 77–79, 80
276 adding templates 93
finding substrings 201 registering 417, 418
returning 419 enabling/disabling 78
flags Forms page (Project
drawings 351 OLE registration 422
formatting data 39 Options) 127
file attributes 371 FormStyle property 85, 96, 281
flickering screens 250 forms 9, 38, 48, 75
adding fields 326–328 forward declarations 189–190
floating-point numbers 260, 262 forward reserved word 189
overflow errors 238 adding to projects 26, 59, 76,
220, 224 fractional numbers 156, 262
floppy disk drives See drives
assigning icons to 94 frame windows See MDI
fmtId constant 416, 419
auto-creating at run applications, main form
fmtIsLinkable constant 416, 419
time 113–114 Free method 229
fmtMedium constant 416, 419
borders 44, 86 freeing allocated resources 234,
fmtName constant 416, 419
resizable 87 235
fmtResultName constant 416, building 80–98 freeing memory 229, 234, 235,
419 changing 26 273
FMXUtils unit 369 in text files 94 FreeMem procedure 235
focus shared 77 fsMDIChild constant 97
container components and 48 child See child windows
dialog boxes 88 fsMDIForm constant 97, 281
customizing 59, 75 fsNormal constant 97
setting 92–93 defaults 86
moving 90, 92 fsStayOnTop constant 85, 97
defined 76 function reserved word 161, 185
OLE objects 413 deleting 135
Font common dialog box 41, functions 121, 183–195, 207
designing 15–17 as standalone program 134,
303–304 displaying 79–80, 139
Font property 303, 304 135
editing as ASCII text 94–95 availability 187
FontDialog component 41, 303 frame See MDI applications,
fonts 269, 305 calling 20–21, 161–163
main form recursively 189–190
downloading 306 input 82–83 viewing order 263–264
setting 303–304 instantiating 207 declaring 161, 185, 189
for loops vs. 199 main 9 defined 161
for reserved word 170 changing 112 headers 185, 208
for statements 170–174 dialog boxes as 60, 85–93 short form 208
arrays and 199 file-manager predefined 158
nesting 172–174 application 360–362 Result variable and 187
Form command (View) 63, 79 MDI applications return type, omitting 208
form components 38, 77 and 280, 281 return values 161–163, 185,
Form Designer options 31 OLE example 400–401, 186
Form Experts 10, 125 403
Index 441
indexes 199 Install Components dialog viewing Code Editor
See also arrays box 69, 73 pages 62
defined 199 Install VBX File dialog box 70 keywords See reserved words
range errors 243 installing component libraries 73 Kind property
string lists 270, 275, 276 installing Delphi 1, 123 bitmap buttons 88
string values 201 installing third-party
IndexOf method 270 components 42, 68 L
Information command instance variables 26
(Compile) 143 instantiation Label component 38
Information dialog box 143 forms 207 labels 38, 40
inheriting from objects 219–222 objects 217, 229 See also captions
initialization reserved instructions, undefined 238 lavender “exit” doors 89
word 208, 210 Integer data type 156 Length function 201
initializing integer types 156, 166 libraries 42
applications 116 exception handling 237, 239, adding components 69, 70
array elements 200 241 application icons 128
data 208, 210 integers 156, 260, 262 backing up 68
objects 336 See also constants; numbers creating 68, 72
OLE containers 412–413, 415, integrated debugger 13, 247 customizing 68–73
422 exception handing 238 deleting components 68, 69
in-place activation (defined) 391 restarting 253, 264 distributable 115
See also OLE applications starting 249, 250 dynamic-link (DLLs) 77, 117
input creating 134, 141
integrated development
dialog boxes 87 multiple versions 68
environment 28 rebuilding 42, 68, 69, 70
exception handling 237 customizing 123–129
masking 83 replacing 73
minimizing 32 reverting to previous
input focus moving among windows 140
container components and 48 versions 71
starting 8 run-time 158
dialog boxes 88 interactive tutors 2–3
setting 92–93 exceptions 236–242
interface reserved word 77, 187, saving 71
moving 90, 92 206, 207
OLE objects 413 Library page (Environment
interfaces 76 Options) 71
input forms 82–83 testing 248
InputBox function 82 line breaks in code 150
interrupts 238 LINE.BMP 333
InputQuery function 82 IntToStr function 155, 161, 238
Insert command (Menu lines
Invalid Breakpoints dialog drawing 315, 316–317,
Designer) 105 box 255 328–331
Insert From Resource command invalid component names 44 changing pen width 344
(Menu Designer) 105, 112 invalid drives 362 event handlers 324, 325
Insert from Resource dialog invalid identifiers 101 erasing 330
box 112 invalid types 153 Lines property
Insert From Template command invalid variable references 194 DDE items 385, 388
(Menu Designer) 105, 107 invisible images 366 memos 308
Insert method is reserved word 227, 228 LineTo method 316
menus 110 items (defined) linker options 128, 249
strings 271 DDE conversations 383 Linker page (Project
Insert Object dialog box 394, OLE objects 393 Options) 128
410–411 iterating strings in lists 272 linking database tables 40
options 411 linking DDE items 383, 384–386,
Insert procedure 201 K 389
Insert Template dialog box 107 See also DDE links
inserting a string in a string 201 keyboard shortcuts 43 at run time 383, 385, 388
InsertOLEObjectDlg accessing property values 54 linking OLE objects 392
function 410, 411 adding to menus 102–103 list boxes 38, 41
Install Components command menu commands 12 See also combo boxes
(Options) 69 data-aware 40
Index 443
message boxes 80–82, 310, 374 moving nesting
See also status bars components to different begin..end blocks 176
confirming file deletions pages 69 exception handlers 233–234
370–371 files 373 for statements 172–174
creating 43 input focus 90, 92 if statements 165–166
predefined 209 menu items 104 menu items 103
MessageDlg function 81–82, 310 pens 315, 324 networks 116
MessageDlgPos function 82 strings in lists 271 New Component command
messages 81 moving among IDE (File) 71
See also message boxes windows 140 new forms 29
exception-handling 240, 242, moving among menus 106 New Project command (File) 19
243 moving through Code Editor 62 New Unit command (File) 209
modeless forms as 85 moving through databases 40 non-resizeable borders 87
status bar 409 mrOK constant 88 non-textual information 39
metafiles 39, 42, 348 MsgDlg unit 209 nonvisual components 37,
methods 20, 339–340 multidimensional arrays 200 38–42, 52
See also functions; procedures; multimedia players See media nonvisual objects 228–229
routines players Notebook component 39, 47
accessing 224, 225 multi-page forms 39 notebooks 39
constructor 229 See also notebooks See also tabs
defined 158 multiple components adding pages 39
deleting event handlers adding 44, 47 as containers 47
and 67 copying to containers 48, 49 changing pages 363
destructor 229 removing from containers 49 null-terminated strings 156
objects and 205, 216, 218, resizing 46 numbers 156
222, 224 selecting 46 See also constants
overriding 223 setting properties 54, 55 debugging 260, 262
Microsoft Help Compiler 118 sharing events 65–67 overflow errors 237, 238
MIDI sequencers See media Multiple Document Interface See range checking 157, 237, 241
players MDI applications subranges 197
Minimize button 44, 86 multiple tool bars 342
removing from forms 87
minimum numeric ranges 197
multiplication example 178
multitasking 381
O
MinPage property 306 mutual recursion 189 ObjClass property 394
mismatch errors 155 mutually exclusive options 38, ObjDoc property 394
modal dialog boxes 81, 85–86 333 Object Browser 13
ModalResult property 88 Object Inspector 54, 218
Mode property
pens 315
N See also property editors
accessing properties 54
modeless dialog boxes 85–86 name conflicts 44 displaying components 11
Modified property Name property 16, 27, 44 editing code 19
memos 300, 310 Caption property vs. 17 overview 11
modifying See changing multiple components and 54 renaming components 44
mouse buttons 323, 326 scope 55 selecting menus 106
clicking 323, 324, 326, 334 naming setting properties 54, 55
mouse events 322–326 See also identifiers writing event handlers 18, 60
defined 322 applications 128 Object Linking and Embedding
dragging and dropping component classes 72 See OLE applications
376–379 components 44, 55 Object Pascal language 149–214
OLE objects 395, 421–423 third-party 70 Object selector 11
handling 322, 323, 324, 325 event handlers 66 object types 205, 244
testing for 326, 351 files See file names declaring 188
Move method forms 17, 55, 59 ObjectMenuItem property 407
strings 271, 276 menu items 101, 108 object-oriented
MoveFile function 373 menus 101 programming 215–230
MoveTo method 315 tabs 269 accessing components 223
Index 445
owner-draw controls 275, PASSWORD.PAS 84 Polygon method 318
365–369 PasswordChar property 83, 84 polygons 318
drawing 367–369 Paste command (Edit) 50 PolyLine method 317
events and 367, 369 Paste Special dialog box 395, polylines 316, 317
resizing 367 415, 417 poPageNums constant 306
styles 365 PasteFromClipboard poPrintToFile constant 307
method 291 pop-up menus 38
P PasteSpecialDlg function See also menus
415–417, 418 displaying 104
.~PA files 116 pasting components 49–50 drop-down menus and 103
pages DDE links 384, 389 handling events 109, 110, 294
Code Editor 12 OLE objects 394, 415–421 MDI applications 294–295
moving through 62–63 pasting graphics 355 PopupMenu component 38, 99,
Component palette 10, 38–42 109, 294
pasting text 291
notebook 39
paths See directories PopupMenu property 295
changing 363
text, printing options 306 Pause Program command Pos function 201
Pages property 275 (Run) 253 poScreenCenter constant 44
Paint Box component 41 PChar data type 156 poSelection constant 307
painting (defined) 314 Pen property 315 predefined procedures and
See also repainting PEN.BMP 333 functions 158
Palette page (Environment PenPos property 315 predefined types 156
Options) 68 pens 315–316 predefined units 206, 210
palettes colors 315, 343 predesigned applications 10
Alignment 50 default settings 315 predesigned forms 10, 29
Component See Component drawing modes 330 adding to galleries 93,
position, setting 315, 324 126–127
palette styles 342 adding to projects 78–79
Panel component 39, 47 width 344 opening for reference 79
panels 39, 331, 332, 345, 408 period (.) specifying as default 125
adding buttons 39 declarations not within predesigned menus 100,
aligning text 346 scope 178 106–109
as containers 47 identifiers and 152 loading 106
multiple 331 method calls 159 predesigned projects 10, 115,
subdividing 346 subrange types 197
three-dimensional 346 122–123
Picture editor 332, 333 adding to galleries 126–127
parameters Picture Editor dialog box 57 saving 136
actual 191, 193
Picture property 349 specifying as default 124
changing values 193, 194
pictures 117 preexisting units 135
constant 194
formal 191, 193, 194 See also graphics Preferences page (Environment
functions 185 loading 56–57 Options) 28–32, 123
mouse-event 322, 323 pie slices 318 preferences, setting 28–32, 123
omitting 208 pie-shaped gauges 42 pressing mouse buttons 323,
passing 190–195 pixels 324, 326, 334
procedures 160, 185 reading 314 See also mouse events
specifying 160 setting 315 preventing data corruption and
value 191–193, 194 Pixels property 314 loss 231
variable 193–194 plus sign (+) concatenating Print common dialog box 41,
Parameters command (Run) 250 strings 201 305, 306–307
parent-child relationships pmCopy constant 330 PrintDialog component 41
components 48, 49 pmNotXor constant 330 Printer object 305
MDI applications 97 Pointer data type 156 Printer Setup common dialog
.PAS files 24–26, 116, 119–121 pointer icon 38 box 41, 305, 307
pass counts 258 pointers 156, 237 printers
passing parameters 190–195 debugging 262, 263 setting up 307
password entry screens 82, 83 PokeData method 387 specifying 305
password invalid exceptions 245 PokeDataLines method 387 Printers unit 209, 305, 351
Index 447
RECT.BMP 333 case 166 routines 20, 121, 338
Rectangle method 317 const 157, 194 See also functions; methods;
rectangles 39, 317 downto 172 procedures
recursion 189 else 164, 167, 241 accessing 209
redeclaring identifiers 181 end 165, 167, 175, 210, 232 file operations 369
redistributable files ii except 239, 241 string-handling 201
redrawing images 316 finally 235 visibility in units 207, 208
references (third-party for 170 RowHeights property 368
books) 429 forward 189 Run command (Run) 17
referencing forms 77 function 161, 185 Run Parameters dialog box 250
referencing units 26, 286 if 163, 164 Run to Cursor command
implementation 187, 207, 208, (Run) 251
regenerating images 317
209 running applications 17, 143,
RegisterClipboardFormat initialization 208, 210
function 418 250, 251, 375–376
interface 187, 206, 207 pausing execution 253, 254,
RegisterFormAsOLEDropTarget private 224–225
function 421–422 264
procedure 158, 185 to breakpoints 253, 254, 258
registering Clipboard public 224–225
formats 417, 418 to specific locations 251, 254
raise 244
registering OLE run-time errors 247–248
repeat 168
applications 421–422 restrictions 154 run-time graphics 313–319
relational operator (=) 164 string 200 run-time libraries 158
assignment operator vs. 158 try 232, 235, 239 exceptions 236–242
ReleaseOLEInitInfo function 412 type 120, 185, 335 run-time properties
releasing memory 229, 234, 235, unit 206 OLE objects 407
273 until 168 setting 59–60
releasing mouse buttons 324 uses 76, 77, 207, 208, 209
See also mouse events var 120, 155, 193 S
releasing system resources 234, while 169
with 205 sample applications 267
235 Samples page (Component
remote database servers 40 resizable borders 87
palette) 42
Remove button (Project resizing components 45, 46, 58
graphics 58, 353 Save As command (File) 138
Manager) 131 Save As dialog box 136, 302
Remove File command (Project owner-draw controls 367
resizing forms 44 Save as Form Template dialog
Manager) 131 box 94
removing See deleting resource files 112, 117
loading 112 Save as Template command
RenameFile function 373 (Menu Designer) 105, 108
RenameFile method 302 resources 116, 129, 234
system See system resources Save command (File) 138
renaming components 44, 49, Save common dialog box 41,
218–219 responding to exceptions 231,
232 301–303
renaming files 353, 373–375 Save File command (File) 58
repainting backgrounds 317 responding to multiple
events 64 Save Project As command
repeat reserved word 168 (File) 137
repeat statements 168–169, 174 restoring deleted components 50
Result variable 187 Save Project command (File) 58
for statement vs. 170 Save Project Template dialog
while statements vs. 169 Retry buttons 89
return values See functions box 126
Replace common dialog box 41 Save Template dialog box 108
ReplaceDialog component 41 reusing event handlers 64, 65
reusing forms 38, 76 Save Unit As dialog box 136
replacing existing libraries 73 SaveDialog component 41, 301,
Report component 40 reusing menus 105, 110
Rewrite procedure 308 424
ReportSmith 40 SaveToFile method 353
RequestData method 384, 386 robust applications 231
rounded rectangles 39, 318 OLE objects 396, 424
reraising exceptions 242 strings 273, 276
.RES files 116 ROUNDREC.BMP 333
RoundRect method 318 SaveToStream method 426
reserved words 154 saving 71
at 245 component libraries 71
begin 165, 167, 175
Index 449
nested if 165–166 allocating memory 201 tabbing through dialog
stepping over 252 assigning values 200 boxes 90–91
stepping through 252 associating graphics with 367 tabbing through forms and
terminating character 151, concatenating 201 components 54
165 debugging 262 Table component 40
with 225–226 finding length 201 TabOrder property 90
status bars 39, 345–347 inserting strings 201 tabs 39
adding panels 346 null-terminated 156 See also notebooks
aligning text 346 size 201, 291 changing 363–364
file-manager example 360, returning 201 default width 368
364 starting position 201, 291 draw-item events 369
OLE example 409–410 Strings property 270 file-manager application 362,
Project Manager 131 StrPCopy function 387 363–364
subdividing 360 StrToFloat function 238 measure-item events 368
updating information in 347 StrToInt function 238 naming 269
status lines 47 Style property owner-draw styles 365
Stdctrls unit 291 brushes 316, 344 TabSet component 39
Step Over command (Run) 252 owner-draw variants TabStop property 90, 91
stepping through code 365–366 TCheckBox component 222
(debugger) 252–253 pens 315, 343 TComponent type 221
statement by statement 252 subrange types 166, 197–199 TDragDropEvent type 422
to first executable subranges 197 technical support 3
statement 253 subroutines 158 templates 29, 30
stopping project execution 253, substrings adding to projects 78–79
264 deleting specific 201 forms 10
Stored Procedure component 40 finding 201 adding to galleries 93,
storing project files 115–116, 132 returning position 201 126–127
streams 426 string lists and 272 opening for reference 79
Stretch property 58 swap files 238 specifying as default 125
string arrays 171, 270 symbol tables 249 MDI applications 281
string grids 39, 269 symbolic debugging menus 100, 106–109
displaying data 172 information 249–250 loading 106
string lists 269–277, 368 symbols 13, 154 projects 10, 115, 122–123
accessing strings 270, 276 local 249 adding to galleries
at run time 274 Syntax Check command 126–127
adding objects 275–276, (Compile) 142 saving 136
366–367 syntax errors 154, 158, 159 specifying as default 124
copying 272 System menu 86 saving forms as 93–94
counting strings 270 removing from forms 87 user-defined 126–127
creating 273–275 System page (Component Templates page (Browse
deleting strings 271 palette) 41 Gallery) 78
inserting strings 271, 276 system resources temporary windows 60
iterating 272 preventing loss 231 terminating applications 350
loading 272 protecting 233, 234–236 file-manager example 362
locating specific string releasing 234, 235 OLE example 404
270–271, 276 SysUtils unit 236, 372 text editor example 309–312
manipulating strings 269–272 testing applications 141, 143, 248
owner-draw controls testing forms 112
and 365, 366–367 T text 200, 381
saving 272 Tab key 54, 90, 91 See also lists; memos; outlines
string reserved word 200 tab order 90–91 aligning 289
string types 156, 200–203 changing 90 in panels 346
StringGrid component 39 testing 91 changing 300
string-handling routines 201 Tab Order command (Edit) 90 copying 291
strings 200 TabbedNotebook with DDE links 389
See also string lists; substrings component 39, 47 deleting 291–292
accessing characters 201
Index 451
user-defined types 185, 186, local 177, 180 Visible property
195–205 naming 154 Enabled property vs. 292
uses reserved word 76, 77, 207 objects and 222, 226–228, 229 menus 110
implementation reserved values, limiting 197 tool bars 342
word and 209 watching 259–261 Visual Basic controls 42, 70
interface reserved word VBX controls 42, 70 Visual Component Library
and 208 VBX page (Component (VCL) 42
palette) 42 adding components 69, 70
V VCL See Visual Component customizing 68–73
Library deleting components 69
valid characters in VCRs See media players visual components 37, 38–42
identifiers 154 version control 94, 144
valid drives, getting 362–363
value parameters 191–193, 194
vertical scroll bars 290 W
video files See media players
values 203 View Form button (Project Watch List window 259–261
See also constants Manager) 131 opening 259
assigning 151–153 View Form command (Project Watch Properties dialog
fields in records 205 Manager) 131 box 259, 260
functions 161 View Form dialog box 63, 79 watches 259–261
placing limits 197 View menu 139 setting 259
to properties See setting View Source command stopping 260
property values (Breakpoint List window) 256 Watches command (View) 259
to strings 200 while reserved word 169
View Source command (Call
type compatibility while statements 169–170, 174
and 157 Stack) 264
View Unit button (Project for statements vs. 170
zeros, to arrays 199 whole numbers 156, 260, 262
changing while Manager) 131
Width property
debugging 261, 262–263 View Unit command (Project
pens 315, 344
comparing 158, 164 Manager) 131
Window List command
declaring as identifiers 196 View Unit dialog box 23, 62, 80
(View) 140
decremental 172 viewing
bitmaps 39, 42 Window List dialog box 140
equal 158 Window menu, creating 283,
incremental 42, 171 breakpoints 255, 258
child windows 287 287
numeric, valid ranges 156
code 12, 79, 139 WindowMenu property 288
return See functions
Code Editor window 141 windows
sequential 335
debugger and 251 closing 309–310
string 201
shared events 65 flickering 250
True/False 156
specific event handlers 63 moving among IDE 140
types, returning 195
components 11 temporary 60
var reserved word 120, 155, 193
data 40, 172 Windows applications See
variable parameters 193–194
data types 153 applications
variables 26, 179
directories 42, 363, 366 Windows common dialog boxes
assigning values 151, 152, 157
control 170 files 280 See common dialog boxes
declaring 154–157 in list boxes 297 Windows resources 116, 234
character arrays 200 project 12, 23, 25 with reserved word 205
example 217, 226 forms 79–80, 139 with statements 225–226
for statements and 170 grids 31 .WMF files 117
procedures and 160 menus 104, 105 See also metafiles
text editor example 299 messages 80, 409 Word data type 156
defined 154 non-textual information 39 word wrapping 290
examining 258–263 OLE objects as icons 411, 414 word-processing
giving a type 154 property values 54 applications 280
global 177, 181–183 shared 54, 55
WordWrap property 290
invalid 194 text 39
in columns and rows 39 writing units 206–208, 209
tool bars 342 begin..end blocks 175–176
headers 206
™
Delphi
Borland International, Inc., 100 Borland Way
P.O. Box 660001, Scotts Valley, CA 95067-0001
Redistributable files
For a list of redistributable files, please see the REDIST.TXT file in the DELPHI\DOC directory.
Borland may have patents and/or pending patent applications covering subject matter in this document. The
furnishing of this document does not give you any license to these patents.
COPYRIGHT © 1995 Borland International. All rights reserved. All Borland products are trademarks or registered
trademarks of Borland International, Inc. Other brand and product names are trademarks or registered trademarks of
their respective holders.
Printed in the U.S.A.
1E0R195
9596979899-987654321
W1
Contents
Introduction 1 The uses clause in the .PAS file . . . . . . . . . 25
The form (.DFM) file. . . . . . . . . . . . . . . . 26
Installing Delphi . . . . . . . . . . . . . . . . . . . 1 The type declaration in the .DFM file . . . . . 26
Documentation overview . . . . . . . . . . . . . . 2 Source code for units without forms . . . . . . 27
Using this manual . . . . . . . . . . . . . . . . . .2 Setting environment preferences . . . . . . . . . 28
Using Help. . . . . . . . . . . . . . . . . . . . . . .2 Accessing environment options preferences . 28
Using Interactive Tutors . . . . . . . . . . . . . . .2 Gallery options . . . . . . . . . . . . . . . . . . 29
Manual conventions . . . . . . . . . . . . . . . . . 3 Use On New Form option . . . . . . . . . . 29
Contacting Borland. . . . . . . . . . . . . . . . . . 3 Use On New Project . . . . . . . . . . . . . 30
Enabling the Gallery options . . . . . . . . . . 31
Part I Desktop Contents option . . . . . . . . . . . . 31
Desktop Only . . . . . . . . . . . . . . . . . 31
Getting started with Delphi 5 Desktop And Symbols . . . . . . . . . . . . 31
Autosave Options . . . . . . . . . . . . . . . . 31
Chapter 1 Editor Files . . . . . . . . . . . . . . . . . . . 31
Introducing Delphi 7 Desktop . . . . . . . . . . . . . . . . . . . . . 31
Form Designer options (grid). . . . . . . . . . 31
The Delphi programming environment . . . . . 7 Debugging options . . . . . . . . . . . . . . . . 32
Starting Delphi . . . . . . . . . . . . . . . . . . . .8 Integrated Debugging . . . . . . . . . . . . 32
Elements of the Delphi interface . . . . . . . . . . 8 Step Program Block . . . . . . . . . . . . . . 32
Elements visible upon starting Delphi. . . . . . .9 Break On Exception . . . . . . . . . . . . . . 32
Form . . . . . . . . . . . . . . . . . . . . . . . . . 9 Minimize On Run . . . . . . . . . . . . . . . 32
Form tools. . . . . . . . . . . . . . . . . . . . . 9 Compiling option. . . . . . . . . . . . . . . . . 32
Component palette. . . . . . . . . . . . . . . . 10 Summary . . . . . . . . . . . . . . . . . . . . . . . 32
Object Inspector . . . . . . . . . . . . . . . . . 11
Object selector . . . . . . . . . . . . . . . . . 11 Part II
Code Editor . . . . . . . . . . . . . . . . . . . . 11 Fundamental skills 35
SpeedBar . . . . . . . . . . . . . . . . . . . . . 12
Elements not visible upon starting Delphi . . . 12
Project Manager . . . . . . . . . . . . . . . . . 12 Chapter 2
Menu Designer . . . . . . . . . . . . . . . . . . 13 Using components and code 37
Integrated debugger . . . . . . . . . . . . . . . 13
ObjectBrowser . . . . . . . . . . . . . . . . . . 13 Delphi components . . . . . . . . . . . . . . . . . 37
Image editor. . . . . . . . . . . . . . . . . . . . 14 The form component . . . . . . . . . . . . . . . 38
Default Component palette pages. . . . . . . . 38
The Delphi development model . . . . . . . . . 14
Installing additional components . . . . . . . . 42
Designing a form . . . . . . . . . . . . . . . . . . 15
Creating a new form. . . . . . . . . . . . . . . 15 Manipulating components in your forms . . . . 43
Adding components to the form. . . . . . . . 15 Setting form properties . . . . . . . . . . . . . . 43
Setting component properties . . . . . . . . . 16 The Name property . . . . . . . . . . . . . . . 44
The Name property . . . . . . . . . . . . . . 16 Adding components to the form . . . . . . . . 44
Running the program . . . . . . . . . . . . . . 17 Sizing a component as you add it . . . . . . . 45
Handling events . . . . . . . . . . . . . . . . . . 18 Selecting components in the form . . . . . . . . 46
Starting a new project . . . . . . . . . . . . . . . 19 Resizing components in the form . . . . . . . 46
Calling procedures and functions from Adding multiple copies of a component . . . 47
event handlers . . . . . . . . . . . . . . . . . 20 Grouping components . . . . . . . . . . . . . . 47
Distributing your application . . . . . . . . . 22 Cutting, copying, and pasting components . . 49
Overview of Delphi projects . . . . . . . . . . . 22 Deleting and restoring components. . . . . . . 50
The project (.DPR) file . . . . . . . . . . . . . . . 22 Aligning components . . . . . . . . . . . . . . . 50
Viewing the .DPR file . . . . . . . . . . . . . . 23 Using the form grid as an alignment guide. . 52
The uses clause in the .DPR file . . . . . . . . 24 Locking the position of components. . . . . . 52
The unit (.PAS) file . . . . . . . . . . . . . . . . . 24 Controlling the creation order of nonvisual
Viewing the .PAS file . . . . . . . . . . . . . . 25 components . . . . . . . . . . . . . . . . . . . . 52
i
Setting component properties . . . . . . . . . . 53 Viewing forms and units. . . . . . . . . . . . . . 79
How the Object Inspector displays Building forms. . . . . . . . . . . . . . . . . . . . 80
properties . . . . . . . . . . . . . . . . . . . . . 54 Using routines to display dialog boxes . . . . . 80
Tab-jumping to property names in the Object Displaying message boxes . . . . . . . . . . . 80
Inspector . . . . . . . . . . . . . . . . . . . . . . 54 ShowMessage procedure. . . . . . . . . . . 81
Displaying and setting shared properties. . . . 55 MessageDlg() function . . . . . . . . . . . . 81
Scope of the Name property . . . . . . . . . . 55 Creating simple input forms . . . . . . . . . . 82
Using property editors. . . . . . . . . . . . . . . 56 Masking input characters . . . . . . . . . . . . 83
Dialog box editors . . . . . . . . . . . . . . . . 56 Developing custom dialog boxes . . . . . . . . 85
Loading an image . . . . . . . . . . . . . . . 56 Making a dialog box modal or modeless . . . 85
Sizing an image . . . . . . . . . . . . . . . . 58 Displaying a dialog box modelessly . . . . 85
Saving your project. . . . . . . . . . . . . . . . . 58 Displaying a dialog box modally . . . . . . 86
Setting properties at run time. . . . . . . . . . . 59 Setting form properties for a dialog box . . . 86
Using properties to customize forms at run Specifying a caption for the dialog box. . . 87
time. . . . . . . . . . . . . . . . . . . . . . . . . 59 Providing command buttons . . . . . . . . . . 87
Working with code . . . . . . . . . . . . . . . . . 60 Executing button code on Esc . . . . . . . . 88
Generating the default event handler . . . . . . 60 Executing button code on Enter. . . . . . . 88
Displaying the form as a dialog box. . . . . . 60 Closing a dialog box when the user
Working with the Code Editor . . . . . . . . . . 62 chooses a button . . . . . . . . . . . . . . . 88
Viewing pages in the Code Editor. . . . . . . 62 Creating standard-command buttons . . . . . 88
Locating an existing event handler. . . . . . . . 63 Setting the tab order . . . . . . . . . . . . . . . 90
Locating default event handlers . . . . . . . . 63 Testing the tab order . . . . . . . . . . . . . . . 91
Modifying an existing event handler . . . . . 63 Removing a component from the tab order . 91
Associating an event with an existing event Enabling and disabling components . . . . . 91
handler . . . . . . . . . . . . . . . . . . . . . . . 64 Setting the focus in a dialog box . . . . . . . . 92
Using the Sender parameter . . . . . . . . . . 64 Setting focus at design time . . . . . . . . . 92
Displaying and coding shared events. . . . . 65 Setting focus at run time . . . . . . . . . . . 92
Modifying a shared event handler . . . . . . 66 Saving a form as a template . . . . . . . . . . . 93
Deleting event handlers . . . . . . . . . . . . . 67 Saving form files as ASCII text. . . . . . . . . . 94
Converting text files back to .DFM format . . 95
Customizing the Delphi Visual Component
Sample ASCII Form file . . . . . . . . . . . . . 95
Library (VCL) . . . . . . . . . . . . . . . . . . . 68
MDI and SDI forms . . . . . . . . . . . . . . . . 96
Adding and removing components from the
library. . . . . . . . . . . . . . . . . . . . . . . . 69 Creating form menus. . . . . . . . . . . . . . . . 98
Adding VBX controls . . . . . . . . . . . . . . 70 Opening the Menu Designer . . . . . . . . . . . 99
Handling an unsuccessful compilation . . . . . 70 Building menus . . . . . . . . . . . . . . . . . .100
Saving library source code . . . . . . . . . . . 71 Naming menus . . . . . . . . . . . . . . . . . .101
Using the Component Expert. . . . . . . . . . . 71 Naming the menu items. . . . . . . . . . . . .101
Using customized libraries . . . . . . . . . . . . 72 Adding, inserting, and deleting menu
items . . . . . . . . . . . . . . . . . . . . . ..101
Summary. . . . . . . . . . . . . . . . . . . . . . . 73 Adding separator bars . . . . . . . . . . . .102
Specifying accelerator keys and keyboard
Chapter 3 shortcuts . . . . . . . . . . . . . . . . . . .102
Building forms and menus 75 Creating nested (sub)menus . . . . . . . . . .103
Creating nested menus by demoting
What is a form? . . . . . . . . . . . . . . . . . . . 76 existing menus. . . . . . . . . . . . . . . .103
Designing usable forms . . . . . . . . . . . . . . 76 Moving menu items . . . . . . . . . . . . . . .104
Sharing forms . . . . . . . . . . . . . . . . . . . . 76 Viewing the menu . . . . . . . . . . . . . . . .104
Making forms visible to other forms . . . . . 76 Editing menu items without opening the
Enabling forms to reference each other . . . . 77 Menu Designer . . . . . . . . . . . . . . . . . .104
Modifying a shared form . . . . . . . . . . . . 77 Using the Menu Designer SpeedMenu . . . . .105
Using the Form Templates of the Browse Commands on the SpeedMenu . . . . . . . .105
Gallery . . . . . . . . . . . . . . . . . . . . . . . 77 Switching among menus at design time . . .106
Adding a template form to a project . . . . . 78 Using menu templates . . . . . . . . . . . . . .106
Opening a Form Template for reference Saving a menu as a template . . . . . . . . . . .108
only . . . . . . . . . . . . . . . . . . . . . . 79
ii
Naming conventions for template menu Adding templates to the Gallery . . . . . . . .126
items and event handlers . . . . . . . . . . . 108 Project options . . . . . . . . . . . . . . . . . . .127
Associating menu events with code . . . . . . 109 Default check box. . . . . . . . . . . . . . . . .127
Menu component events . . . . . . . . . . . . 109 Form options . . . . . . . . . . . . . . . . . . .127
Handling menu item events . . . . . . . . . . 109 Application page . . . . . . . . . . . . . . . . .128
Associating a menu item with an existing Title . . . . . . . . . . . . . . . . . . . . . . .128
event handler . . . . . . . . . . . . . . . . . . 110 Help file. . . . . . . . . . . . . . . . . . . . .128
Adding menu items dynamically . . . . . . . 110 Icon . . . . . . . . . . . . . . . . . . . . . . .128
Merging menus . . . . . . . . . . . . . . . . . . 111 Compiler page . . . . . . . . . . . . . . . . . .128
Specifying the active menu: Menu Linker page . . . . . . . . . . . . . . . . . . . .128
property . . . . . . . . . . . . . . . . . . . 111 Directory and Conditional options . . . . . .129
Determining the order of merged menu Managing project content . . . . . . . . . . . . 129
items: GroupIndex property . . . . . . . 111 Using the Project Manager . . . . . . . . . . . .129
Importing resource (.RC) files. . . . . . . . . . 112 Displaying the Project Manager . . . . . . . .130
Managing run-time behaviors of forms . . . . 112 The Project Manager window . . . . . . . . .130
Specifying a form as the project main form. . 112 Project Manager SpeedBar . . . . . . . . . .131
Specifying forms to auto-create. . . . . . . . . 113 Project Manager status bar. . . . . . . . . .131
Controlling the form auto-create order . . . . 113 Project Manager file list. . . . . . . . . . . .132
Summary. . . . . . . . . . . . . . . . . . . . . . 114 Project Manager Path column . . . . . . . .132
Integrating forms and units into a project . . .133
Chapter 4 Creating new form units . . . . . . . . . . . .134
Creating new source code units . . . . . . . .134
Managing projects, files, Creating new component units. . . . . . . . .134
and directories 115 Sharing files from other projects or
directories . . . . . . . . . . . . . . . . . . . .134
What is a project? . . . . . . . . . . . . . . . . . 115 Using Borland Pascal source code units. . . .135
Project directories. . . . . . . . . . . . . . . . . 115 Removing constituent files from a project . . .135
Constituent files of a project. . . . . . . . . . . 116 Saving projects and individual project files . .135
Files generated at design time . . . . . . . . . 116 Saving a project . . . . . . . . . . . . . . . . . .136
Compiler-generated project files. . . . . . . . 117 First project save. . . . . . . . . . . . . . . .136
Non-Delphi resource files. . . . . . . . . . . . 117 Subsequent saves . . . . . . . . . . . . . . .136
Understanding the files in a project . . . . . . 118 Naming unit and project source code
The project source code (.DPR) file. . . . . . . 118 files . . . . . . . . . . . . . . . . . . . . . .136
Unit source code (.PAS) files . . . . . . . . . . 119 Saving a separate version of the project
Form-associated unit files. . . . . . . . . . . . 120 file. . . . . . . . . . . . . . . . . . . . . .. . .137
Form unit type declaration . . . . . . . . . 120 Saving files. . . . . . . . . . . . . . . . . . . . .138
Form unit var declaration. . . . . . . . . . 120 File|Save versus File|Save As . . . . . . .138
Form unit compiler directive. . . . . . . . 120 Creating a backup of an entire project. . . . .139
Unit files for procedures and functions . . . . 121 Navigating among project components . . . .139
Unit files for components . . . . . . . . . . . . 121 Viewing forms and units . . . . . . . . . . . .139
Unit object code (.DCU) files . . . . . . . . . . 121 Toggling between form image and unit
Graphical form (.DFM) files. . . . . . . . . . . 121 source code. . . . . . . . . . . . . . . . . .140
Bringing a window to the front. . . . . . . . .140
Beginning new projects . . . . . . . . . . . . . 122
Using the Project Manager to view or edit
Beginning a project with a Project Template . 122 units . . . . . . . . . . . . . . . . . . . . . . .140
Customizing project options . . . . . . . . . . 123 Viewing the project source code (.DPR)
Environment options. . . . . . . . . . . . . . . 123 file. . . . . . . . . . . . . . . . . . . . . . . . .141
Environment preferences . . . . . . . . . . . . 123 Compiling, building, and running projects . . 141
Autosave options . . . . . . . . . . . . . . 123 Checking source code syntax . . . . . . . . . .141
Gallery. . . . . . . . . . . . . . . . . . . . . 124 Compiling a project . . . . . . . . . . . . . . . .142
Gallery options . . . . . . . . . . . . . . . . . . 124 Obtaining compile status information. . . . .143
Specifying the default new project . . . . . . 124 Building a project . . . . . . . . . . . . . . . . .143
Specifying a Project Template . . . . . . . 124 Running a project . . . . . . . . . . . . . . . . .143
Specifying a Project Expert . . . . . . . . . 125 Executing a project from Windows . . . . . .143
Specifying the default new form. . . . . . . . 125
Specifying the default main form . . . . . . . 125
iii
Managing multiple project versions and A scope example . . . . . . . . . . . . . . . . . .178
team development . . . . . . . . . . . . . . . 144 Redeclaring identifiers in a different scope . .181
Enabling team development support . . . . . 144 Using a global variable . . . . . . . . . . . . .181
Summary. . . . . . . . . . . . . . . . . . . . . . 145 Writing a procedure or function . . . . . . . . 183
Writing a procedure or function header . . . .185
Part III Writing a procedure or function block . . . . .185
Programming topics 147 Declarations within a procedure or
function block . . . . . . . . . . . . . . . . . .185
Type declarations . . . . . . . . . . . . . . .185
Chapter 5 Variable and constant declarations . . . . .186
Writing Object Pascal code 149 Ordering the declaration parts . . . . .
Writing the statement part . . . . . . . . .
.
.
.186
.186
Writing readable code . . . . . . . . . . . . . . 150 Assigning a return value in a function . . .186
Coding style . . . . . . . . . . . . . . . . . . . . 150 Positioning a procedure or function in your
Commenting your code . . . . . . . . . . . . . 150 code . . . . . . . . . . . . . . . . . . . . . . . .187
Writing assignment statements. . . . . . . . . 151 Forward declarations . . . . . . . . . . . . . .189
Assigning values to properties and variables 152 Passing parameters . . . . . . . . . . . . . . . .190
Declaring identifiers . . . . . . . . . . . . . . . 153 Value parameters. . . . . . . . . . . . . . . . .191
Declaring variables . . . . . . . . . . . . . . . . 154 Variable parameters . . . . . . . . . . . . . . .193
Naming a variable . . . . . . . . . . . . . . . . 154 Constant parameters . . . . . . . . . . . . . . .194
Giving a variable a type . . . . . . . . . . . . . 154 Deciding which kind of parameter to use . .194
Data types. . . . . . . . . . . . . . . . . . . 156 Defining new data types . . . . . . . . . . . . . 195
Type and assignment compatibility. . . . 157 Enumerated types . . . . . . . . . . . . . . . . .195
Declaring constants. . . . . . . . . . . . . . . . 157 Subrange types . . . . . . . . . . . . . . . . . . .197
Calling procedures and functions . . . . . . . 158 Array types . . . . . . . . . . . . . . . . . . . . .199
Calling procedures . . . . . . . . . . . . . . . . 158 Multidimensional arrays . . . . . . . . . . . .200
Cut, Copy, Paste, and Clear All: An String types: Arrays of characters . . . . . . .200
example . . . . . . . . . . . . . . . . . . . . . 159 Finding the length of a string . . . . . . . .201
Calling procedures with parameters . . . . . 160 Set types . . . . . . . . . . . . . . . . . . . . . . .203
Calling functions . . . . . . . . . . . . . . . . . 161 Record types . . . . . . . . . . . . . . . . . . . .204
Assigning a function’s returned value . . . . 161 A few words about objects . . . . . . . . . . . .205
Using functions that return a Boolean Understanding Object Pascal units. . . . . . . 206
value to branch code. . . . . . . . . . . . . . 162 What is a unit? . . . . . . . . . . . . . . . . . . .206
Controlling the flow of code execution . . . . 163 The structure of a unit. . . . . . . . . . . . . . .206
The if statement . . . . . . . . . . . . . . . . . . 163 Interface part . . . . . . . . . . . . . . . . . . .207
Using an else part in an if statement . . . . . 164 Implementation part . . . . . . . . . . . . . . .208
Writing multiple statements within an if Initialization part . . . . . . . . . . . . . . . . .208
statement . . . . . . . . . . . . . . . . . . . . 165 How units are used . . . . . . . . . . . . . . . .209
Nesting if statements . . . . . . . . . . . . . . 165 The uses clause in the implementation part .209
The case statement . . . . . . . . . . . . . . . . 166 Writing a unit “from scratch” . . . . . . . . . .209
Writing loops . . . . . . . . . . . . . . . . . . . 168 Adding an existing unit to a project. . . . . . .210
The repeat statement. . . . . . . . . . . . . . . 168 Summary . . . . . . . . . . . . . . . . . . . . . . 210
The while statement . . . . . . . . . . . . . . . 169
The for statement. . . . . . . . . . . . . . . . . 170 Chapter 6
A counting example . . . . . . . . . . . . . 171
Using nested for loops. . . . . . . . . . . . . . 172 Programming with Delphi objects 215
Deciding which loop to use. . . . . . . . . . . 174 What is an object? . . . . . . . . . . . . . . . . . 215
Object Pascal blocks . . . . . . . . . . . . . . . 174 Examining a Delphi object . . . . . . . . . . . .216
Blocks within event handlers . . . . . . . . . . 175 Changing the name of a component. . . . . .218
Blocks within units . . . . . . . . . . . . . . . . 175 Inheriting data and code from an object. . . . 219
Blocks within blocks . . . . . . . . . . . . . . . 176 Objects, components, and controls . . . . . . .221
Understanding scope. . . . . . . . . . . . . . . 177 Object scope . . . . . . . . . . . . . . . . . . . . 222
Accessing declarations that are not within Accessing components on another form . . . .223
scope . . . . . . . . . . . . . . . . . . . . . . . 178 Scope and descendants of an object . . . . . . .223
iv
Overriding a method . . . . . . . . . . . . . . 223 Debugging your application startup code . .253
Public and private declarations. . . . . . . . . 224 Running to a breakpoint . . . . . . . . . . . . .253
Accessing object fields and methods. . . . . . 225 Pausing the program . . . . . . . . . . . . . . .253
Assigning values to object variables . . . . . . 226 Restarting the program. . . . . . . . . . . . . . 253
Creating nonvisual objects . . . . . . . . . . . 228 Using breakpoints. . . . . . . . . . . . . . . . . 254
Creating an instance of an object . . . . . . . . 229 Setting breakpoints . . . . . . . . . . . . . . . .254
Destroying your object. . . . . . . . . . . . . . 229 Invalid breakpoints. . . . . . . . . . . . . . . .255
Summary. . . . . . . . . . . . . . . . . . . . . . 230 Setting breakpoints after starting a
program . . . . . . . . . . . . . . . . . . . . .255
Chapter 7 Working with breakpoints . . . . . . . . . . . .255
Viewing and editing code at a breakpoint . .255
Writing robust applications 231 Disabling and enabling breakpoints . . . . . .256
Protecting blocks of code . . . . . . . . . . . . 231 Deleting breakpoints . . . . . . . . . . . . . . .256
Responding to exceptions . . . . . . . . . . . . 232 Modifying breakpoint properties . . . . . . . .257
Executing cleanup code . . . . . . . . . . . . . 232 Creating conditional breakpoints . . . . . . .257
Handling the exception . . . . . . . . . . . . . 232 Setting Boolean conditions. . . . . . . . . .257
Exceptions and the flow of execution . . . . . 232 Using pass counts . . . . . . . . . . . . . . .258
Nesting exception responses . . . . . . . . . . 233 Customizing the breakpoint and execution
Protecting resource allocations . . . . . . . . . 234 point colors . . . . . . . . . . . . . . . . . . . .258
What kind of resources need protection? . . . 234 Examining program data values . . . . . . . . 258
Creating a resource-protection block . . . . . 235 Watching expressions . . . . . . . . . . . . . . .259
Handling RTL exceptions . . . . . . . . . . . . 236 Formatting watch expressions . . . . . . . . .260
What are the RTL exceptions? . . . . . . . . . 236 Disabling a watch. . . . . . . . . . . . . . . . .260
Deleting a watch . . . . . . . . . . . . . . . . .260
Creating an exception handler . . . . . . . . . 239
Providing default exception handlers. . . . . 241
Evaluating and modifying expressions. . . . .261
Evaluating expressions . . . . . . . . . . . . .261
Handling classes of exceptions . . . . . . . . . 241
Modifying the values of variables . . . . . . .262
Reraising the exception . . . . . . . . . . . . . 242
Viewing function calls . . . . . . . . . . . . . . 263
Handling component exceptions. . . . . . . . 242
Navigating to function calls . . . . . . . . . . .264
Silent exceptions . . . . . . . . . . . . . . . . . 243
Handling hardware and language
Defining your own exceptions . . . . . . . . . 244 exceptions. . . . . . . . . . . . . . . . . . . . . 264
Declaring an exception object type. . . . . . . 244 Summary . . . . . . . . . . . . . . . . . . . . . . 265
Raising an exception . . . . . . . . . . . . . . . 244
Setting the exception address . . . . . . . . . 244 Part IV
Summary. . . . . . . . . . . . . . . . . . . . . . 245
Sample applications 267
Chapter 8
Using the integrated debugger 247 Chapter 9
Types of bugs . . . . . . . . . . . . . . . . . . . 247 Working with string lists 269
Run-time errors . . . . . . . . . . . . . . . . . . 247 Manipulating the strings in a list . . . . . . . . 269
Logic errors . . . . . . . . . . . . . . . . . . . . 248 Counting the strings in a list . . . . . . . . . . .270
Planning a debugging strategy . . . . . . . . . 248 Accessing a particular string . . . . . . . . . . .270
Starting a debugging session . . . . . . . . . . 249 Finding the position of a string . . . . . . . . .270
Generating debugging information . . . . . . 249 Adding a string to a list . . . . . . . . . . . . . .271
Before you begin . . . . . . . . . . . . . . . . . 250 Moving a string within a list . . . . . . . . . . .271
Running your program . . . . . . . . . . . . . 250 Deleting a string from a list. . . . . . . . . . . .271
Specifying program arguments . . . . . . . . 250 Copying a complete string list . . . . . . . . . .272
Controlling program execution. . . . . . . . . 251 Iterating the strings in a list. . . . . . . . . . . .272
Running to the cursor location . . . . . . . . . 251 Loading and saving string lists . . . . . . . . . 272
The execution point . . . . . . . . . . . . . . . 251 Creating a new string list . . . . . . . . . . . . 273
Stepping through code. . . . . . . . . . . . . . 252 Short-term string lists . . . . . . . . . . . . . . .273
Trace Into . . . . . . . . . . . . . . . . . . . . . 252 Long-term string lists . . . . . . . . . . . . . . .274
Step Over . . . . . . . . . . . . . . . . . . . . . 252
v
Adding objects to a string list . . . . . . . . . . 275 Loading the file . . . . . . . . . . . . . . . .300
Operating on objects in a string list . . . . . . 276 Using the Save dialog box . . . . . . . . . . . .301
Accessing associated objects . . . . . . . . . . 276 SaveDialog component properties. . . . . . .301
Adding associated objects . . . . . . . . . . . 276 Saving the text file . . . . . . . . . . . . . . . . .301
Summary. . . . . . . . . . . . . . . . . . . . . . 277 Creating a backup file . . . . . . . . . . . . . .302
Using the Font dialog box . . . . . . . . . . . .303
Chapter 10 Font dialog box component properties . . . .303
Changing the font in the Memo component. .304
Text editor example 279 Printing the text file . . . . . . . . . . . . . . . . 305
Multiple Document Interface (MDI) Using the printer object . . . . . . . . . . . . . .305
applications . . . . . . . . . . . . . . . . . . . 280 Canvas . . . . . . . . . . . . . . . . . . . . .305
Creating the MDI frame form. . . . . . . . . . 281 Fonts. . . . . . . . . . . . . . . . . . . . . . .305
The FormStyle property. . . . . . . . . . . . . 281 Using the printer dialog box(es) . . . . . . . . .306
Creating the MDI child form . . . . . . . . . . 281 Print dialog box component properties . . . .306
Creating the application menus . . . . . . . . 282 MinPage / MaxPage . . . . . . . . . . . . .306
Creating the frame form menu. . . . . . . . . 283 Options | poPageNums . . . . . . . . . . .306
Creating the child form menu . . . . . . . . . 283 Options | poPrintToFile . . . . . . . . . . .307
Merging the application menus . . . . . . . . 284 Options | poSelection . . . . . . . . . . . .307
Creating child windows at run time . . . . . . 285 PrintRange . . . . . . . . . . . . . . . . . . .307
Referencing other units . . . . . . . . . . . . . 286 Using the Printer Setup dialog box
Working with open child windows . . . . . . 287 component. . . . . . . . . . . . . . . . . . . .307
Arranging and accessing open child Handling the File | Print Setup OnClick
windows . . . . . . . . . . . . . . . . . . . . . 287 event. . . . . . . . . . . . . . . . . . . . .
.307
Coding the Window menu commands . . . . 287 Directing your text file to the printer . . . .
.307
Including a list of open documents in a Downloading the text . . . . . . . . . . . . .
.308
menu . . . . . . . . . . . . . . . . . . . . . . . 288 Printing the contents of the memo . . . . . . .308
Providing an area for text manipulation . . . 288 Exiting gracefully . . . . . . . . . . . . . . . . . 309
Adding the Memo component . . . . . . . . . 288 Closing a window . . . . . . . . . . . . . . . . .309
Manipulating text in a Memo component . . 289 Closing the child window. . . . . . . . . . . .310
Setting text alignment and word wrapping . 289 Determining whether the file has been
Setting text alignment . . . . . . . . . . . . . . 289 modified. . . . . . . . . . . . . . . . . . . . . .310
Adding scroll bars dynamically . . . . . . . . 290 Exiting the application . . . . . . . . . . . . . .311
Using the Clipboard with text . . . . . . . . . 291 Summary . . . . . . . . . . . . . . . . . . . . . . 312
Selecting text . . . . . . . . . . . . . . . . . . . 291
Cutting, copying, and pasting text. . . . . . . 291 Chapter 11
Deleting text without changing the Drawing graphics at run time 313
contents of the Clipboard . . . . . . . . . . . 292
Dimming menu items . . . . . . . . . . . . . . 292 Drawing versus painting. . . . . . . . . . . . . 314
Declaring a method . . . . . . . . . . . . . 293 Using the pixel array . . . . . . . . . . . . . . . 314
Calling a procedure from an event Manipulating pixels . . . . . . . . . . . . . . . .314
handler . . . . . . . . . . . . . . . . . . . 293 Reading a pixel’s color. . . . . . . . . . . . . .314
Providing a pop-up menu. . . . . . . . . . . . 294 Setting a pixel’s color. . . . . . . . . . . . . . .315
Handling the OnPopup event . . . . . . . . . 294 Using pens . . . . . . . . . . . . . . . . . . . . .315
Specifying the pop-up menu for the form . . 295 Using brushes . . . . . . . . . . . . . . . . . . .316
Using common dialog boxes . . . . . . . . . . 295 Drawing lines and polylines. . . . . . . . . . . 316
Common dialog box options in the Object Drawing straight lines. . . . . . . . . . . . . . .316
Inspector . . . . . . . . . . . . . . . . . . . . . 296 Drawing polylines . . . . . . . . . . . . . . . . .317
Enabling the Help button from a common Drawing shapes . . . . . . . . . . . . . . . . . . 317
dialog box . . . . . . . . . . . . . . . . . . . . 296
Drawing rectangles and ellipses. . . . . . . . .317
Using the OpenDialog component. . . . . . . 297
OpenDialog component properties . . . . . . 297
Drawing rounded rectangles. . . . . . . . . . .318
Specifying file filters . . . . . . . . . . . . . . . 297 Drawing polygons. . . . . . . . . . . . . . . . .318
The Filter property. . . . . . . . . . . . . . 298 Drawing special parts . . . . . . . . . . . . . . 318
Opening an existing text file . . . . . . . . . . 298 Summary . . . . . . . . . . . . . . . . . . . . . . 319
Declaring a form-level variable . . . . . . . . 299
vi
Chapter 12 Using the Clipboard with graphics. . . . . . . 354
Copying graphics to the Clipboard . . . . . . .355
Graphics example 321 Cutting graphics to the Clipboard. . . . . . . .355
Responding to the mouse . . . . . . . . . . . . 322 Pasting graphics from the Clipboard . . . . . .355
What’s in a mouse event? . . . . . . . . . . . . 322 Summary . . . . . . . . . . . . . . . . . . . . . . 356
Responding to a mouse-down action . . . . . 323
Responding to a mouse-up action . . . . . . . 324 Chapter 13
Responding to a mouse move . . . . . . . . . 325
Adding a field to a form object . . . . . . . . . 326
File manager example 359
Refining line drawing . . . . . . . . . . . . . . 328 Creating the file-manager form . . . . . . . . . 360
Tracking the origin point . . . . . . . . . . . . 328 Laying out the form . . . . . . . . . . . . . . . .360
Tracking movement . . . . . . . . . . . . . . . 329 Placing the controls . . . . . . . . . . . . . . . .360
Designing the menu . . . . . . . . . . . . . . . .361
Adding a tool bar to a form . . . . . . . . . . . 331
Building the drive list. . . . . . . . . . . . . . . 362
Adding speed buttons to a tool bar . . . . . . 331
Determining valid drives . . . . . . . . . . . . .362
Adding a speed button to a tool bar . . . . . . 332
Connecting the controls. . . . . . . . . . . . . .363
Assigning a speed button’s glyph . . . . . . . 332
Setting the initial condition of a speed Creating an owner-draw control . . . . . . . . 365
button. . . . . . . . . . . . . . . . . . . . . . . 333 Setting the owner-draw style . . . . . . . . . .365
Creating a group of speed buttons. . . . . . . 333 Adding graphical objects to a string list . . . .366
Allowing toggle buttons . . . . . . . . . . . . 334 Drawing owner-draw items . . . . . . . . . . .367
Responding to clicks . . . . . . . . . . . . . . . 334 Manipulating files. . . . . . . . . . . . . . . . . 369
Responding to a button click . . . . . . . . . . 334 Deleting a file . . . . . . . . . . . . . . . . . . . .370
Drawing with different tools . . . . . . . . . . 334 Confirming file deletions . . . . . . . . . . . .370
Declaring an enumerated type . . . . . . . . . 335 Changing a file’s attributes . . . . . . . . . . . .371
Reading file attributes . . . . . . . . . . . . . .371
Changing the tool with speed buttons. . . . . 336
Changing individual file attributes . . . . . .372
Using the drawing tools . . . . . . . . . . . . . 337
Setting file attributes . . . . . . . . . . . . . . .373
Drawing the appropriate shapes. . . . . . . . 337
Moving, copying, and renaming files. . . . . .373
Customizing pens and brushes. . . . . . . . . 340 Executing an application . . . . . . . . . . . . .375
Adding hidden tool bars . . . . . . . . . . . . 340
Dragging and dropping . . . . . . . . . . . . . 376
Hiding and showing tool bars . . . . . . . . . 342
Starting a drag operation . . . . . . . . . . . . .376
Changing the pen style . . . . . . . . . . . . . 342
Accepting dragged items . . . . . . . . . . . . .377
Changing the pen color . . . . . . . . . . . . . 343
Dropping items . . . . . . . . . . . . . . . . . .378
Changing the pen width. . . . . . . . . . . . . 344
Ending a drag operation . . . . . . . . . . . . .378
Changing the brush style . . . . . . . . . . . . 344
Changing the brush color . . . . . . . . . . . . 345 Summary . . . . . . . . . . . . . . . . . . . . . . 379
Adding a status bar. . . . . . . . . . . . . . . . 345 Chapter 14
Placing a status-bar panel . . . . . . . . . . . . 345
Subdividing a panel . . . . . . . . . . . . . . . 346 Exchanging data with DDE or OLE 381
Creating 3-D panels . . . . . . . . . . . . . . . 346 Using DDE . . . . . . . . . . . . . . . . . . . . . 381
Updating the status bar . . . . . . . . . . . . . 347 DDE conversations . . . . . . . . . . . . . . . .382
Drawing on a bitmap. . . . . . . . . . . . . . . 347 DDE services . . . . . . . . . . . . . . . . . . .382
Adding a scrollable region . . . . . . . . . . . 348 DDE topics. . . . . . . . . . . . . . . . . . . . .383
Adding an image control . . . . . . . . . . . . 348 DDE items . . . . . . . . . . . . . . . . . . . . .383
Placing the control . . . . . . . . . . . . . . . . 348 Creating DDE client applications . . . . . . . .383
Setting the initial bitmap size. . . . . . . . . . 349 Establishing a link with a DDE server. . . . .384
Drawing on the bitmap . . . . . . . . . . . . . 349 Requesting data. . . . . . . . . . . . . . . . . .386
Adding a menu . . . . . . . . . . . . . . . . . . 350 Poking data . . . . . . . . . . . . . . . . . . . .386
Controlling other applications . . . . . . . . .387
Printing graphics . . . . . . . . . . . . . . . . . 351
Creating DDE server applications. . . . . . . .388
Working with graphics files. . . . . . . . . . . 352 Establishing a link with a DDE client
Loading a picture from a file . . . . . . . . . . 352 application. . . . . . . . . . . . . . . . . . . .389
Saving a picture to a file . . . . . . . . . . . . . 353 Using OLE . . . . . . . . . . . . . . . . . . . . . 390
Replacing the picture. . . . . . . . . . . . . . . 353 What is OLE? . . . . . . . . . . . . . . . . . . . .390
vii
OLE 1.0 and OLE 2.0. . . . . . . . . . . . . . . 391 Adding the tool bar . . . . . . . . . . . . . . .408
Design-time and run-time object creation . . 391 Adding the status bar . . . . . . . . . . . . . .409
Linking and embedding . . . . . . . . . . . . 392 Inserting objects . . . . . . . . . . . . . . . . . . 410
Linked objects . . . . . . . . . . . . . . . . 392 Using the Insert Object dialog box . . . . . . .410
Embedded objects . . . . . . . . . . . . . . 392 Initializing the OLE container . . . . . . . . . .412
OLE classes . . . . . . . . . . . . . . . . . . . . 393 Deactivating objects . . . . . . . . . . . . . . . .413
OLE documents . . . . . . . . . . . . . . . . . 393
Pasting objects . . . . . . . . . . . . . . . . . . . 415
OLE items . . . . . . . . . . . . . . . . . . . . . 393
Using the Paste Special dialog box . . . . . . .415
Creating OLE container applications . . . . . 393
Using OLE objects with the Clipboard . . . . .417
OLE data in files . . . . . . . . . . . . . . . . . 395
Registering Clipboard formats . . . . . . . . .418
Comparing DDE and OLE . . . . . . . . . . . 396 Specifying OLE formats . . . . . . . . . . . . .418
Summary. . . . . . . . . . . . . . . . . . . . . . 397 Pasting the OLE object . . . . . . . . . . . . . .420
Dropping objects . . . . . . . . . . . . . . . . . 421
Chapter 15 Registering a form as an OLE drop target . . .421
OLE example 399 Dropping an OLE object onto the OLE
Creating the MDI framework. . . . . . . . . . 400 example application . . . . . . . . . . . . . . .422
Creating the frame and child forms . . . . . . 400 Working with objects in files . . . . . . . . . . 423
Adding the OLE container component . . . . 401 Saving objects to files . . . . . . . . . . . . . . .424
OLE application menus . . . . . . . . . . . . . 402 Loading objects from files . . . . . . . . . . . .424
Creating the frame form menu. . . . . . . . . 403 Summary . . . . . . . . . . . . . . . . . . . . . . 426
Creating the child form menu . . . . . . . . . 405
The OLE object menu item . . . . . . . . . . . 407 Appendix A
OLE tool bars and status bars. . . . . . . . . . 408 Selected Bibliography 429
Setting up tool bars and status bars . . . . . . 408
Index 431
viii
Tables
1 Typefaces and symbols in these manuals. . . .3 9.1 Corresponding string and object methods
2.1 Components on the Standard page . . . . . . 38 in string lists . . . . . . . . . . . . . . . . . . . 276
2.2 Components on the Additional page . . . . . 39 10.1 Text editor property values . . . . . . . . . . 281
2.3 Controls on the Data Access page . . . . . . . 40 10.2 Child form property settings for the text
2.4 Components on the Data Controls page . . . 40 editor example . . . . . . . . . . . . . . . . . . 282
2.5 Components on the Dialogs page . . . . . . . 41 10.3 Frame form menu items . . . . . . . . . . . . 283
2.6 Components on the System page . . . . . . . 41 10.4 Child form menu items . . . . . . . . . . . . . 284
2.7 Components on the VBX page . . . . . . . . . 42 10.5 Naming the project files . . . . . . . . . . . . 284
2.8 Components on the Samples page. . . . . . . 42 10.6 GroupIndex property settings. . . . . . . . . 285
2.9 AboutBox component properties . . . . . . . 53 10.7 Memo component settings. . . . . . . . . . . 288
3.1 MessageDlg parameters . . . . . . . . . . . . . 81 10.8 File filter settings for the text editor. . . . . . 298
3.2 Alternate form settings. . . . . . . . . . . . . . 87 10.9 SaveDialog component properties . . . . . . 301
3.3 Delphi’s predefined bitmap button types . . 89 12.1 Mouse-event parameters . . . . . . . . . . . . 323
3.4 Property settings for demonstrating 12.2 Property settings for pen and brush
ActiveControl . . . . . . . . . . . . . . . . . . . 93 tool bars . . . . . . . . . . . . . . . . . . . . . . 341
3.5 FormStyle property settings. . . . . . . . . . . 97 12.3 Image control properties for GRAPHEX . . 349
3.6 Sample captions and their derived names . 101 12.4 Graphics example File and Edit menus . . . 350
3.7 Menu Designer SpeedMenu commands . . 105 13.1 Property values for the file manager
4.1 Design-time project files . . . . . . . . . . . . 116 example’s main form . . . . . . . . . . . . . . 360
4.2 Compiler-generated project files . . . . . . . 117 13.2 Property values for the main-form
4.3 Project Manager SpeedBar buttons . . . . . 131 components in FILMANEX . . . . . . . . . . 360
5.1 Object Pascal predefined data types . . . . . 156 13.3 File-menu items for the file manager
5.2 String procedures and functions . . . . . . . 201 example . . . . . . . . . . . . . . . . . . . . . . 362
7.1 Heap exceptions. . . . . . . . . . . . . . . . . 237 13.4 Fixed vs. variable owner-draw styles . . . . 366
7.2 Integer math exceptions . . . . . . . . . . . . 237 13.5 Property values for the file-attribute
7.3 Floating-point math exceptions . . . . . . . 238 dialog box form . . . . . . . . . . . . . . . . . 371
7.4 Hardware exceptions . . . . . . . . . . . . . 238 13.6 Property values for the file-attribute
8.1 Expression format specifiers . . . . . . . . . 262 dialog box components . . . . . . . . . . . . . 372
ix
Figures
1.1 The Delphi programming environment . . . .8 3.9 Save Form Template dialog box. . . . . . . . .94
1.2 Object Inspector with Caption property 3.10 Sample MDI child and parent forms . . . . . .97
selected . . . . . . . . . . . . . . . . . . . . . . . 16 3.11 Delphi menu terminology . . . . . . . . . . . .99
1.3 Events page . . . . . . . . . . . . . . . . . . . . 18 3.12 MainMenu and PopupMenu components . .99
1.4 Browse Gallery dialog box displaying 3.13 Menu Designer for a main menu . . . . . . . 100
application templates. . . . . . . . . . . . . . . 19 3.14 Menu Designer for a pop-up menu. . . . . . 100
1.5 A default Delphi project . . . . . . . . . . . . . 22 3.15 Nested menu structures . . . . . . . . . . . . 103
1.6 Default project source code . . . . . . . . . . . 23 3.16 Select Menu dialog box . . . . . . . . . . . . . 106
1.7 Modified project file source code. . . . . . . . 24 3.17 Sample Insert Template dialog box for
1.8 Default unit source code. . . . . . . . . . . . . 25 menus . . . . . . . . . . . . . . . . . . . . . . . 107
1.9 Form type declaration . . . . . . . . . . . . . . 27 3.18 Delete Templates dialog box for menus . . . 107
1.10 Modified type declaration. . . . . . . . . . . . 27 3.19 Save Template dialog box for menus. . . . . 108
1.11 Environment Options dialog box, 4.1 Project Manager window. . . . . . . . . . . . 130
Preferences page . . . . . . . . . . . . . . . . . 29 4.2 Example Project Manager project listing. . . 133
1.12 The Forms Gallery . . . . . . . . . . . . . . . . 30 4.3 Example project directory tree. . . . . . . . . 139
1.13 The Projects Gallery . . . . . . . . . . . . . . . 30 4.4 The Window List dialog box. . . . . . . . . . 140
1.14 The Compiling dialog box. . . . . . . . . . . . 32 4.5 Syntax or compile error display. . . . . . . . 142
2.1 About box . . . . . . . . . . . . . . . . . . . . . 43 5.1 A sample form for assigning a property
2.2 AboutBox with BitBtn component. . . . . . . 45 value to another property . . . . . . . . . . . 152
2.3 Sizing handles . . . . . . . . . . . . . . . . . . . 46 5.2 A sample form for the Cut, Copy, Paste,
2.4 Form with Panel component . . . . . . . . . . 47 and Clear All example . . . . . . . . . . . . . 159
2.5 AboutBox with Panel and Label 5.3 A form for an example that uses the
components . . . . . . . . . . . . . . . . . . . . 49 Execute function . . . . . . . . . . . . . . . . . 162
2.6 Panel with Labels and Image components . . 50 5.4 A sample form to illustrate an if
2.7 Alignment palette. . . . . . . . . . . . . . . . . 51 statement . . . . . . . . . . . . . . . . . . . . . 163
2.8 Alignment dialog box . . . . . . . . . . . . . . 51 5.5 A form for a case statement example. . . . . 166
2.9 Aligned Label components . . . . . . . . . . . 52 5.6 A form for a repeat statement example . . . 168
2.10 Form grid. . . . . . . . . . . . . . . . . . . . . . 52 5.7 A form for a while statement example . . . . 169
2.11 Form2 with two Button1 component 5.8 A sample form to illustrate a for loop . . . . 171
captions. . . . . . . . . . . . . . . . . . . . . . . 56 5.9 A form with string grid displaying
2.12 Picture Editor dialog box . . . . . . . . . . . . 57 column and row coordinates . . . . . . . . . 172
2.13 Image displayed in Picture Editor dialog 5.10 A form for a nested for loop example . . . . 173
box. . . . . . . . . . . . . . . . . . . . . . . . . . 57 5.11 Blocks within blocks. . . . . . . . . . . . . . . 176
2.14 About box with image . . . . . . . . . . . . . . 57 5.12 Blocks within a simple project. . . . . . . . . 177
2.15 About box with sized image . . . . . . . . . . 58 5.13 A form for multiplying two numbers
2.16 Run-time About box . . . . . . . . . . . . . . . 62 together . . . . . . . . . . . . . . . . . . . . . . 178
2.17 About box displaying program name in 5.14 A form for a scope example . . . . . . . . . . 179
form title bar . . . . . . . . . . . . . . . . . . . . 64 5.15 A form that uses a global variable . . . . . . 181
2.18 About box with run-time icon . . . . . . . . . 67 5.16 A form for a value parameter example . . . 191
2.19 The Component Expert dialog box . . . . . . 71 5.17 The value of Number and CalcNo when
3.1 Standard Delphi Form Templates in the Calculate begins running. . . . . . . . . . . . 192
Browse Gallery . . . . . . . . . . . . . . . . . . 78 5.18 The values of Number and CalcNo after
3.2 Example ShowMessage message box . . . . . 81 Calculate runs . . . . . . . . . . . . . . . . . . 193
3.3 Confirmation message dialog box . . . . . . . 82 5.19 The value of Number and CalcNo when
3.4 Sample input box in running form. . . . . . . 83 Calculate begins running. . . . . . . . . . . . 194
3.5 Password Dialog Template at design time . . 84 5.20 The value of Number and CalcNo after
3.6 Password dialog box at run time. . . . . . . . 84 Calculate runs . . . . . . . . . . . . . . . . . . 194
3.7 Password dialog box displaying masked 5.21 A form for an enumerated type example . . 196
characters. . . . . . . . . . . . . . . . . . . . . . 84 5.22 A form for a subrange example . . . . . . . . 198
3.8 Edit Tab Order dialog box. . . . . . . . . . . . 90 5.23 A form for a string-handling example . . . . 202
x
5.24 A form for a set type example . . . . . . . . 203 12.6 Straight line with intermediate drawing. . . 329
6.1 A simple form . . . . . . . . . . . . . . . . . . 217 12.7 Persistent intermediate lines . . . . . . . . . . 330
6.2 Inheriting from TForm. . . . . . . . . . . . . 221 12.8 Line after rubber banding . . . . . . . . . . . 331
6.3 A simplified hierarchy diagram . . . . . . . 221 12.9 The tool bar with 6 buttons: . . . . . . . . . . 332
7.1 Nested resource protections . . . . . . . . . 233 12.10 The tool bar buttons with glyphs assigned . 333
7.2 Nested exception handlers . . . . . . . . . . 234 12.11 The pen and brush tool bars . . . . . . . . . . 341
8.1 The Breakpoint List window . . . . . . . . . 255 12.12 Bitmap-dimension dialog box from the
8.2 The Edit Breakpoint dialog box . . . . . . . 257 BMPDlg unit. . . . . . . . . . . . . . . . . . . . 354
8.3 The Watch List window . . . . . . . . . . . . 259 13.1 The complete file manager example . . . . . 359
8.4 The Watch Properties dialog box. . . . . . . 260 13.2 File-manager form with controls . . . . . . . 361
8.5 The Evaluate/Modify dialog box . . . . . . 261 13.3 Confirming a file deletion . . . . . . . . . . . 371
8.6 Call Stack window . . . . . . . . . . . . . . . 263 13.4 The file-attribute dialog box . . . . . . . . . . 372
10.1 The finished text editor program, 13.5 The change-file dialog box . . . . . . . . . . . 374
TEXTEDIT.EXE . . . . . . . . . . . . . . . . . 280 14.1 A DDE conversation between a Delphi
10.2 Text editor application menu with no application and Microsoft Word 6.0. . . . . . 382
child windows open . . . . . . . . . . . . . . 282 14.2 The DDE Info dialog box . . . . . . . . . . . . 384
10.3 Text editor application menu with child 14.3 The WordPerfect Paste Special dialog box . 389
window open . . . . . . . . . . . . . . . . . . 283 14.4 The Insert Object dialog box . . . . . . . . . . 394
10.4 Open child window . . . . . . . . . . . . . . 286 14.5 The Paste Special dialog box. . . . . . . . . . 395
10.5 Font dialog box component options . . . . . 296 15.1 The completed OLE container application . 399
10.6 OpenDialog component properties . . . . . 297 15.2 The OLEFrameForm and OLEObjectForm
10.7 The Filter editor . . . . . . . . . . . . . . . . . 298 windows . . . . . . . . . . . . . . . . . . . . . 405
10.8 Font dialog box component properties . . . 304 15.3 The OLE container application menu . . . . 408
10.9 Print dialog box component properties . . . 306 15.4 The OLE container application tool bar
12.1 The finished graphics program, and status bar. . . . . . . . . . . . . . . . . . . 410
GRAPHEX.EXE . . . . . . . . . . . . . . . . . 321 15.5 The Insert Object dialog box . . . . . . . . . . 410
12.2 Drawing text at the point clicked. . . . . . . 324 15.6 A Paintbrush picture OLE object . . . . . . . 414
12.3 Graphics application with lines drawn . . . 325 15.7 The Paste Special dialog box. . . . . . . . . . 415
12.4 Graphics application following the mouse . 326 15.8 The Save As dialog box . . . . . . . . . . . . . 425
12.5 Line with lost origin . . . . . . . . . . . . . . 328 15.9 The Open dialog box . . . . . . . . . . . . . . 426
xi
xii