Introduction
In recent years, the concept of visual development in Windows has been popularised by the availability of tools that support Rapid Application Development (RAD) . However, professional developers intending to exploit the benefits of visual design very rapidly run up against the inherent limitations of first-generation interpreter-based products such as Visual Basic Pro, PowerBuilder and SQLWindows.
This document introduces the next generation approach to visual development that has been pioneered by Borland s Delphi and Delphi Client/Server, and the advantages it offers in comparison to Visual Basic Pro. Delphi is unique among development tools in that it combines the benefits of a high-performance optimising native code compiler, visual two-way rapid
application development (RAD) tools and fully scalable database access. It is Delphi s underlying compiler technology, built upon more than ten years of compiler development expertise at Borland, that is the key to its significant performance lead over Visual Basic Pro.
Specifically, this document is aimed at programmers with at least intermediate knowledge and experience in Visual Basic. It assumes an awareness of GUI design concepts, component properties and the event-driven programming model. While it does not set out to provide a
comprehensive tutorial on Delphi or its underlying Object Pascal language, this document does cover some of the key differences between Delphi and Visual Basic, so that Visual Basic users may more quickly get up to speed with Delphi programming.
For many concepts in Visual Basic, there are parallel facilities offered by Delphi. However, there are several significant features of Delphi such as creating reusable components or Dynamic Link Libraries (DLLs) that are simply impossible within the Visual Basic environment. This
documents outlines some of the key similarities and differences in visual development between the two products.
The development environment
Both Delphi and VB feature visually oriented development environments. As in VB, you see a main window, a property inspector and a crisp new form called Form1. On the left side of the main window, you have a toolbar with similar functionality to the one in VB. To the right, however, you find the Component palette, to provide a better organization, and easier access, than the VB Toolbox.
The components are grouped on the palette by functionality, on a series of tabbed pages. You will discover as you delve deeper into Delphi that you can customize these pages but for now it is just important to know that you use this Component palette the same way you use the floating toolbox in VB. One difference that you will appreciate is that the Delphi palette has Help hints for the controls so that you know right away what they are.
Adding Controls to Forms
You add controls to a form in a manner similar to that of Visual Basic. You can add a control in each of the following ways:
· Click the tool, draw the control
· Click the tool, click the form
· Double-click the tool
· Shift-click the tool to create multiple controls of the same type
You can move controls around the form and resize them. You can also select multiple components via a rubber-band box or by Shift-clicking the components you want to select. On the Edit menu, you will see familiar commands to manipulate the Z-Order of the controls. In addition, there are some new component-manipulation tools such as alignment, sizing, scaling and tab order. Delphi also features an intuitive and easy-to-use Tab Order dialog box, available from the Edit menu but, if you are more familiar with VB s TabIndex property, you can also use the equivalent TabOrder property of Delphi.
Setting Properties
Once you place a control on a form, you can set various properties in Delphi s property window, called the Object Inspector. By default, this window is placed on the left hand side of the development environment. At the top of the window, there is a combo box that displays, and provides a means for you to choose, the component whose properties you are editing. The component name is on the left and the component type (or class) is on the right. Below is a list of properties available for that control at design time. Delphi s Object Inspector allows direct selection and editing of properties, rather than only at the top of the window.
There are several property editors that appear in the Object Inspector. For properties such as Caption, for which direct user input is expected and there is no assistance available, the only property editor is a text box. For others, more sophisticated alternatives are available. For example, the Visible property provides a choice between True and False. The BorderStyle property of a form provides for a selection of valid settings. As in VB, you can double-click a property value to iterate through the available choices. Many Delphi properties, such as Color, Picture, and Icon, have dialog-based property editors.
One significant improvement over Visual Basic is that properties with enumerated choices, such as BorderStyle, display actual built-in constant values that you can use within your code. In VB, BorderStyle is an enumerated property from 0 to 3, the constants for which are in CONSTANT.TXT. In Delphi, you see the actual constant values in the Object Inspector (i.e. bsDialog, bsNone, bsSingle and bsSizeable) and these are always available within your code.
Properties can be objects
An important distinction between Delphi and VB is that in Delphi there are many properties that are themselves objects. An example of this in Visual Basic is the RecordSet property of a data control. The name of the property is RecordSet but the datatype, rather than being a simple type like string or integer is an object, Dynaset. This leads to a syntax like this in VB, where MoveNext is a method supported by all Dynaset objects:
Data1.RecordSet.MoveNext
However, VB does not support the creation of objects, so support for this type of object organization and syntax is limited. Because Delphi is a completely object-oriented environment, you can easily create your own objects. Not surprisingly, then, Delphi has a wide variety of properties that are also objects For example, the Font property of an object is itself an object of type Font. A Font object has its own properties: Color, Height, Name, Pitch, Size and Style. Therefore, instead of using ForeColor, in Delphi, you would change the color of the caption of a label like this:
Label1.Font.Color := clRed;
To accommodate this, the Object Inspector functions as an outliner. Properties with a + character in front of them can be expanded to reveal the properties of that property. Double-click on the property name and it will be expanded for a result like this:
-Font
Color
Height
Name
Pitch
Size
+Style
There is another data type in Delphi called a set, discussed in more detail below, which is a collection of Boolean values. The Style property of a Font object is a set. When expanded, the Style property provides a set of choices for bold, italic, underline and strikethrough. You can always double-click a property value to see if there is a dialog associated with it. The Font property is a good example where the Font common dialog is used to set all of the relevant font properties of an object.
Creating Event Handlers
In Delphi, as with Visual Basic, once you add controls to a form, you create event handlers "behind" those controls, which represent the logic of your application. To edit the handler for the default event of a component, simply double-click the component. For example, double-clicking on a button component will place you in the OnClick event handler and double-clicking on an edit box component will place you in the OnChange event handler.
As a simple example, create a new Delphi project and place an edit control on the form. The edit control can be found on the "Standard" page of the Component palette. Now, double-click the Edit control and enter the single line of code as shown below:
procedure TForm1.Edit1Change(Sender: TObject);
begin
Form1.Caption := Edit1.Text; {Add this line of code}
end;
As you can see, with the exception of the colon before the = sign and the semicolon at the end of the line, this code is very similar to the corresponding code in Visual Basic. Now, press F9 to run your program. As you would expect, the caption of the form changes to reflect the text typed into the edit control. Double-click the system menu to exit the application and return to design mode. One minor difference you will see is that no underscore character is added between the object name and the event name in the creation of the event procedure name.
A more significant difference you will notice is that the procedure code appears in a single full-featured code-editing window, not in a separate code window. As you create more event handlers, you will see that they are all available in this same code-editing window. Usability testing has shown that people are more comfortable with less segmented code.
The most significant difference in event handlers between Delphi and VB is that Delphi treats events in a manner very consistent with its treatment of properties. Notice that the Object Inspector has a separate page labeled "Events." It is here that you create event handlers for the selected object by switching to the Events page and selecting the event you wish to handle. At this point, you may either type in the name you would like the event handler to have or simply double-click to generate a default procedure name. The ability to choose the event procedure for an object will prove very powerful, as you ll see later.
Running your Application
The function keys for running your application and setting a breakpoint in your code are different in Delphi. Press F9 to run your application. In addition, you can use the Run selection from the Run menu or the toolbar icon that looks like a VCR s Play button (). This process actually creates a stand-alone, native code .EXE file and then launches it. In other words, once you have tested your application, there is an .EXE in the project directory that you can launch from File Manager or Program Manager. This .EXE runs without any run-time interpreter DLL, and runs up to 10-20 times faster than interpreted p-code.
Exiting your application
To exit your application, you can double-click the system menu of the main form or select Program Reset from the Run menu. The function key equivalent for this is Ctrl-F2. To create a simple event handler that closes the main form, you could do the following in the OnClick event handler of a button:
procedure TForm1.Button1Click(Sender: TObject);
begin
Form1.Close;
end;
Saving your Work
When you select "Save Project" from the File Menu, you are first prompted to save the form. If you enter the name you would like the form file to have (without an extension), the appropriate files will be saved for you using the .PAS file extension; the default name is UNIT1.PAS. Next, you will be prompted to name the project itself. Because Delphi projects themselves contain executable code, Delphi does not permit you to give the same name to project and one of its constituent forms. You might want to prefix your form names with F or a similar convention that will help you quickly and easily identify them as forms.
When you save a form, two files are created: the DFM file and the PAS file. The DFM is a binary file which contains the form layout information. The PAS file contains the code associated with that form. Any time you add a form to a project, you select it via the DFM file but both files are actually added to the project. The project is saved with the extension DPR.
From the View menu, select Project Manager to see the Project Manager window. From this window, you can choose to see the form or associated code of any form in the project. Selecting "Save Project" from the File menu when all items have been saved once will simply save all of the files in the project.
Beginning to Code
In this section, you ll begin to look at Delphi code just enough to get you started. Of course, there is really no substitute for learning as much as you can about the Object Pascal language and it is beyond the scope of this paper to describe the entire language. However, there are enough similarities between Object Pascal and Visual Basic that a few notes should be enough to get you started. More language elements are covered later in this chapter.
Variables
While the use of so-called "automatic variables" in BASIC is considered risky and unsafe, all Delphi variables must be explicitly declared. This is as if Option Explicit were used in VB.
To create local variables in a procedure, you need to create a var clause in your procedure in which to declare them. Declaration of variables takes the form of
Name:Type;
where Name is the name of the variable and Type is the variable type. The colon takes the place of the As keyword in VB. The result in a procedure might look something like this:
procedure TfrmMain.Button2Click(Sender: TObject);
var
i:Integer;
s,z:string;
begin
end;
As you can see, it is possible to create a number of variables of the same type by simply separating their names with commas.
With the exception of variant and currency, all of the Visual Basic data types are available in Delphi as this table shows:
VB Delphi
Integer Integer
Long LongInt
Single Single
Double Double
String String
Variables declared in the var section of a procedure are local to that procedure. There are, of course, several data types available in Delphi, not found in VB such a boolean, char and byte.
Code Blocks
One thing that you will notice about Object Pascal code right away is that all code blocks are surrounded by begin and end. That is why the event handler procedures that are generated by Delphi all have a begin..end section. This is the main executable code of your procedure. If there is a var section, it must come before the begin.
In addition to the begin and end which surround the code of a procedure, there might be several code blocks within the procedure which require their own begin and end pairs. A good example of this is an if statement. Suppose you create a form with several buttons and a checkbox that determines the visibility of those buttons. The OnClick event of the checkbox might look something like this:
procedure TForm1.chkShowClick(Sender: TObject);
begin
if chkShow.State = cbChecked then
begin
Button1.Visible := True;
Button2.Visible := True;
Button3.Visible := True;
end
else
begin
Button1.Visible := False;
Button2.Visible := False;
Button3.Visible := False;
end;
end;
Don't worry too much about the structure of the if statement at this point but notice that there are two code blocks, each of which is surrounded by a begin and end pair.
You will also notice that Delphi uses the semicolon to find the end of a statement, rather than the actual end of a line. Therefore, you may break up a line in any way you find most readable. For example, coming from Visual Basic, you might be most comfortable looking at an if statement like this:
if chkShow.State = cbChecked then begin
Button1.Visible := True;
Button2.Visible := True;
Button3.Visible := True;
end;
As you might imagine, a code block is defined as more than one line of code together. Therefore, a single line of code in an if statement doesn't require a begin..end block. In other words, the following code is perfectly valid, because only one line of code needs to be executed:
if chkShow.State = cbChecked then Button1.Visible := True;
Remembering to encase code blocks in begin..end pairs will be one of the most challenging "mental blocks" when moving from VB to Delphi.
Assignment
As you will have noticed, the assignment operator in Delphi is the := sign. This is distinguished from the comparison operator which is simply the = sign. This is like the distinction between = and == in C. Accordingly, the code to toggle the buttons above might look something like this instead:
procedure TForm1.chkShowClick(Sender: TObject);
begin
Button1.Visible := chkShow.State = cbChecked;
Button2.Visible := chkShow.State = cbChecked;
Button3.Visible := chkShow.State = cbChecked;
end;
where chkShow.State = cbChecked is a Boolean expression, the result of which is assigned to the Boolean property Visible.
Note In Delphi, you enclose string literals in single quotes, not double quotes as in VB. Therefore, to make an assignment to the caption of a form, you would do something like this:
Form1.Caption := 'Hello World!';
Commenting your code
It is appropriate to mention the topic of comments early in the discussion of any development environment. In Delphi, you create a comment by surrounding text in curly braces. This is an example of a comment:
{This is a comment}
{This is an example of
a multi-line comment}
There is no equivalent to the ' comment in VB. A comment begins with a brace and continues until the next closing brace.
Components in Delphi
There are several component types in Delphi which can be used in the design environment. You will notice when you place a component on a form that the class name for the component (which shows up in the Object Inspector) begins with a T for type. This is a convention that is used in Object Pascal frequently. Therefore, the class name of the button control is TButton, an edit control TEdit and so on. The time it is most important to know this is when you are trying to get help on a component by searching for it by name.
The following table is a list of Visual Basic controls and the corresponding components found in Delphi:
This VB control...... corresponds to this Delphi component...... found on this page of the Delphi Component palette
Image Timage Additional
Label Tlabel Standard
TextBox Tedit Standard
Frame TGroupBox Standard
CommandButton Tbutton Standard
CheckBox TCheckBox Standard
OptionButton TRadioButton Standard
ComboBox TComboBox Standard
ListBox TListBox Standard
HScrollBar TScrollBar Standard
VScrollBar TScrollBar Standard
Timer Ttimer System
DriveListBox TDriveComboBox System
DirListBox TDirectoryListBox System
FileListBox TFileListBox System
Shape Tshape Additional
OleControl TOleContainer System
Grid TStringGrid Additional
CommonDialog TOpenDialog Dialog
TSaveDialog Dialog
TFontDialog Dialog
TColorDialog Dialog
TPrintDialog Dialog
TPrinterSetupDialog Dialog
TFindDialog Dialog
TReplaceDialog Dialog
Gauge Tgauge Samples
Graph Tchart VBX
MMControl TMediaPlayer Additional
MaskEdBox TMaskEdit Additional
Outline Toutline Additional
SpinButton TSpinButton Samples
SSCommand TBitBtn Additional
In addition, there are several controls included with Delphi that you would need to purchase separately with Visual Basic: the SpeedButton, TabSet, Notebook, Header, Scrollbox, TabbedNotebook and Calendar, and Grid components.
What follows is a discussion of the more prominent control types and how they compare to their VB equivalents.
Forms
Forms in Delphi are very similar in function and operation to forms in Visual Basic. They both act as the center of an application and as containers for controls. The following is a list of form properties in VB and their equivalents in Delphi:
Visual Basic Delphi
ActiveControl ActiveControl
ActiveForm ActiveMDIChild
BackColor Color
BorderStyle BorderStyle
Caption
Caption
Enabled Enabled
FontBold Font.Style
FontItalic Font.Style
FontName Font.Name
FontSize Font.Size
FontStrikThru Font.Style
FontUnderline Font.Style
ForeColor Font.Color
HDC Canvas*
Height Height
HelpContextID HelpContext
Hwnd Handle
Icon Icon
KeyPreview KeyPreview
Left Left
MDIChild FormStyle
MousePointer Cursor
Name Name
Picture Picture
ScaleHeight ClientHeight
ScaleWidth ClientWidth
Tag Tag
Top Top
Visible Visible
Width Width
WindowState WindowState
Where there isn't a direct property relationship, there is alternative functionality such as in the case of DDE and scaling. In addition, there are several methods that the forms have in common, as the following table shows:
Visual Basic Delphi
Circle Canvas.Elipse, Canvas.Arc
Hide Hide
Line Canvas.LineTo
Move SetBounds
Point
PrintForm Print
Print Canvas.TextOut
Refresh Refresh
SetFocus SetFocus
Show Show
TextHeight Canvas.TextHeight
TextWidth Canvas.TextHeight
Zorder BringToFront, SendToBack
(Load) Create
(Unload) Destroy
As you can see, there is a property of a form which is its canvas. It is on the canvas that you do your drawing. As you will see below, there is a canvas associated with every object in Delphi on which you are able to draw.
Finally, there is more overlap in the events available from a Delphi form and those available in VB.
Visual Basic Delphi
Activate OnActivate
Click OnClick
DblClick OnDblClick
Deactivate OnDeactivate
DragDrop OnDragDrop
DragOver OnDragOver
GotFocus OnGotFocus
KeyDown OnKeyDown
KeyPress OnKeyPress
KeyUp OnKeyUp
Load OnCreate
LostFocus OnLostFocus
MouseDown OnMouseDown
MouseMove OnMouseMove
MouseUp OnMouseUp
Paint OnPaint
QueryUnload OnQueryClose
Resize OnResize
Unload OnDestroy
The equivalent of Me is Self in Delphi. You can access the object that triggered an event at any point by using the Sender parameter. To act on the form, you would use the syntax:
TForm(Self).Caption := 'Hello World!';
Because ObjectPascal is such a strongly typed language, you need to cast a generic object variable to a specific type. In the example above, this is done by using the type as if it s a function call for example, TForm(Self). This allows access to all of the methods and properties of that object.
CommandButtons
The TButton component in Delphi is the equivalent of the CommandButton control type in VB. It is nearly identical in operation to the CommandButton. The CommandButton properties (which are not shared with a form) are below:
The only new method for the CommandButton is the Drag method which has an equivalent in the BeginDrag method of the TButton component. All of the events of the CommandButton are covered in the table for the form object.
Text Boxes
The equivalent of the VB TextBox in Delphi is the TEdit component. As with the button objects, the TextBox and TEdit have most properties and methods in common. The really significant difference is that in Delphi there are two controls which correspond to the TextBox in VB: the TEdit and the TMemo components. Here are the equivalent properties of the TextBox, as reflected in Delphi s TEdit and TMemo components:
The Lines property of the TMemo component is similar to the List property of a Listbox and allows line by line access to the contents of the control. This property is a TStringList object which exists in several places in Delphi and is discussed in conjunction with the ListBox component. There are no new methods in the TextBox and the new event, OnChange, is one the TextBox has in common with the TEdit component.
The Font.Style property is an Object Pascal "set" which is a bit flag variable but with a cleaner syntax than is available in Visual Basic. For example, the code behind the chkBold checkbox looks like this:
procedure TForm1.chkBoldClick(Sender: TObject);
begin
if TCheckBox(Sender).State = cbChecked then
txtDisplay.Font.Style := txtDisplay.Font.Style + [fsBold]
else
txtDisplay.Font.Style := txtDisplay.Font.Style - [fsBold];
end;
Simply by adding the appropriate constant in brackets, you add that attribute to the style and you remove it by subtracting it.
ListBoxes
Once again, the TListBox component in Delphi is very similar to the ListBox control in Visual Basic. Here are the properties of a ListBox:
Visual Basic Delphi
Columns Columns
ItemData Items.Objects*
List Items
ListCount Items.Count
ListIndex ItemIndex
MultiSelect MultiSelect*
NewIndex (Items.Add)
Selected Selected*
Sorted Sorted
TopIndex TopIndex
* Not a direct equivalent
The primary methods a little different because they are the methods of the Items collection but the methods for the ListBox are as follows:
The contents of a ListBox are in the Items property, which is much like the List property in VB except it is more than an array; it is also a class of type TStringList. This object has many interesting features but fundamentally, manipulation of the list takes place via methods of the Items property.
A VB example of Listbox functionality can be found in the LISTBOX.FRM example in the SAMPLES\CONTROLS\CONTROLS.MAK sample Visual Basic project. This is a good demonstration of the differences in using the TListbox and the VB ListBox. In the VB sample, the Add button executes the following code:
Sub cmdAdd_Click ()
lstClient.AddItem txtName.Text
txtName.Text = ""
txtName.SetFocus
lblDisplay.Caption = lstClient.ListCount
End Sub
The equivalent code in Delphi looks something like this:
procedure TfrmListBox.cmdAddClick(Sender: TObject);
begin
lstClient.Items.Add (txtName.Text);
txtName.Text := ';
txtName.SetFocus;
lblDisplay.Caption := IntToStr (lstClient.Items.Count);
end;
The first thing you should notice is that the Add method is on the Items property, not the listbox itself. A brief aside is that you must surround the parameters of both subroutines and functions in parentheses, unlike in Visual Basic where subroutines (and methods) don't use parentheses. Second, you should see that the absence of variants means that you need to explicitly convert data types for assignment. Therefore, in order to display the Items.Count property in the label lblDisplay, use the IntToStr function which is similar in functionality to STR in VB.
The code behind the VB Remove button looks like this:
lstClient.RemoveItem lstClient.ListIndex
while the equivalent Delphi code looks like this:
lstClient.Items.Delete(lstClient.ItemIndex);
where again the Delete method is supported by the Items property. In both VB and Delphi, the Clear method is a method of the listbox object itself so the code looks identical except for the semicolon on the end of the line of Delphi code.
A major advantage of the TStringList property type is that it is compatible with lots of other properties so the following represent working statements in Delphi:
ListBox1.Items := Memo1.Lines;
ListBox2.Items := Screen.Fonts;
ListBox3.Items.LoadFromFile('mylist.txt');
PictureBoxes/Images
The TImage component of Delphi is equivalent to the Image control in Visual Basic except that it has the equivalent drawing functionality of a PictureBox, thereby allowing it to serve the same purpose as both controls in VB. It is a lightweight control just like the Image control and shares a number of properties in common with the Image and the PictureBox. The core display property is the Picture property which operates in much the same way in both environments.
An example of pictureboxes in VB is the SAMPLES\FIRSTAPP\BUTTERF.MAK demo shipped with Visual Basic. The timer code in Visual Basic looks like this:
Sub Timer1_Timer ()
Static PickBmp As Integer
Main.Move (Main.Left + 20) Mod ScaleWidth,_
(Main.Top - 5 + ScaleHeight) Mod ScaleHeight
If PickBmp Then
Main.Picture = OpenWings.Picture
Else
Main.Picture = CloseWings.Picture
End If
PickBmp = Not PickBmp
End Sub
whereas the equivalent code in Delphi looks pretty much the same:
procedure TForm1.Timer1Timer(Sender: TObject);
const
PickBmp:Boolean = False;
begin
Main.SetBounds ((Main.Left + 20) Mod ClientWidth,
(Main.Top - 5 + ClientHeight) Mod
ClientHeight,Main.Width, Main.Height);
if PickBmp = True then
Main.Picture := OpenWings.Picture
else
Main.Picture := CloseWings.Picture;
PickBmp := Not PickBmp;
end;
There are a couple of differences worth noting. First, the SetBounds method, unlike the Move method in VB has no optional parameters so you need to supply the Width and Height values. Second, there is no so-called static variable type in Delphi. Instead you may use a typed consant in its place. The point is that the assignment to the Picture property works just like it does in VB.
Another key difference is that instead of a LoadPicture function that returns a picture, the Picture property of a TImage has its own LoadFromFile method as demonstrated in the next section.
File Controls
Just as in Visual Basic, there are a set of file-oriented components in Delphi for the construction of browsers and customized file dialogs. These components are the TDirectoryListBox, TFileListBox, TDriveComboBox and TFilterComboBox. There is no equivalent to the FilterComboBox in VB but you have seen similar functionality in the Filter property of the common dialog control.
The TDriveComboBox is the counterpart to the DriveListBox in VB. The relevant property in both is the Drive property. The primary difference is that the DirectoryListBox in Delphi also has a Drive property for direct assignment from the DriveComboBox. Therefore, in place of the code
Sub Drive1_Change ()
Dir1.Path = Drive1.Drive
End Sub
in Visual Basic, the Delphi equivalent is:
procedure TForm1.Drive1Change(Sender: TObject);
begin
Dir1.Drive := Drive1.Drive;
end;
The TDirectoryListBox and DirListBox are the Delphi and Visual Basic components to represent a directory. Both display a similar hierarchical structure. The core property of the TDirectoryListBox is Directory which is the equivalent of the Path property in VB's DirListBox. So the following code in VB
Sub Dir1_Change ()
file1.Path = Dir1.Path
End Sub
translates to the following in Delphi:
procedure TForm1.Dir1Change(Sender: TObject);
begin
File1.Directory := Dir1.Directory;
end;
Certainly, you can see that the operation of these controls is very similar in Visual Basic and Delphi. Most of the differences you encounter are subtle changes to the object design.
Finally, there comes the TFileListBox control which is the counterpart to the FileListBox in Visual Basic. Again, the operation of these controls is similar but there are enough differences that they bear closer scrutiny. Here are the relevant properties of each:
Visual Basic Delphi
Archive FileType
FileName FileName
Hidden FileType
Normal FileType
Path Directory
Pattern Mask
ReadOnly FileType
System FileType
As you can see, the biggest difference between the two controls is the selection of file types to display. In VB, this is a set of Boolean properties whereas in Delphi it is a set property type like the Style property of a TFont object. In the Object Inspector, you simply double-click on FileType to expand the component choices. In addition to the choices in VB, there is also the ability in the TFileList to include the directories and volume id. To change these values programmatically, you simple add or subtract the constants from the property. In other words:
File1.FileType := File1.FileType + [fsDirectory] - [fsHidden];
File1.FileType := File1.FileType + [fsNormal] + [fsSystem];
would be valid operations with the FileType property. If you want to check membership in a set, you simply use the in operator. For example,
if fsHidden in File1.FileType then ...
is the code you would use to test whether the TFileListBox was displaying hidden files.
The operation of the two file lists is similar so that the following code from PICVIEW.MAK
Sub File1_DblClick ()
' When at the root level (for example, C:\) the Path property
' has a backslash (\) at the end. When at any other level,
' there is no final \. This code handles either case to build
' the complete path and filename of the selected file.
If Right(file1.Path, 1) <> "\" Then
label1.Caption = file1.Path & "\" & file1.FileName
Else
label1.Caption = file1.Path & file1.FileName
End If
' Load the selected picture file.
Form1.open.Picture = LoadPicture(label1.Caption)
End Sub
would look like this in Delphi
procedure TForm1.File1DblClick(Sender: TObject);
begin
if Length(File1.Directory) = 3 then
Form1.Caption := File1.Directory + File1.FileName
else
Form1.Caption := File1.Directory + '\' + File1.FileName;
Image1.Picture.LoadFromFile (Form1.Caption);
end;
The only difference here is the result of no Right function in Delphi. You could code it with Copy command in Delphi (which is like MID, see string handling below) but it was just as simple to check the length instead.
Menus
Menus are handled a little differently in Delphi than in VB and allow for much greater flexibility. However, the common functionality between them is fairly straightforward.
To create a menu for a form in Delphi, place a TMainMenu component on the form. By default, this is the first control in the Standard page of the Component palette. This component encapsulates all the functionality of the menu. To get to the Menu Designer, simply double-click the main menu component. The Delphi Menu Designer looks very much like a menu. When it first appears, there is one blank menu item. Simply type in a caption. You will notice that the Object Inspector will record what you type in the Caption property and, when you press Enter, will use the menu caption to generate a default name for this menu item.
Once you press Enter, you can start typing the caption of the first item in this menu and so on. When a particular menu item is selected, it appears in the Object Inspector. Menu items in Delphi have similar properties to menu items in Visual Basic.
Visual Basic Delphi
Caption Caption
Checked Checked
Enabled Enabled
ShortCut ShortCut
Tag Tag
Menu items are used the same way for the most part. An & in the caption creates an accelerator. Using a hyphen "-" as the caption creates a separator bar in the menu.
Unlike in the menu designer in VB, you are directly manipulating menu items. Therefore, to move a menu item, you can simply drag it from one place in the menu to another, including to another menu. For example, you can drag an item from the File menu to the Edit menu. To create a sub-menu, right-click a menu item and choose Create Sub-menu or use Ctrl-Right Arrow to create it directly.
To associate code with a menu item, simply double-click the item in the menu designer to get to the OnClick event of the menu item. Bear in mind that the only way to see these menu items is to open the Menu Designer by double-clicking on the TMainMenu component.
This section doesn't really do justice to the menu functionality of Delphi. Be sure to read the documentation on merging menus and on creating them dynamically. While there are no control arrays as such in Delphi, the ability to dynamically create objects provides even more flexibility and power. A method of emulating control arrays is discussed below.
VBX Support
Delphi provides robust support for Visual Basic version 1 custom controls (VBXs). The great majority of commercial VBXs have been written to detect the version of VB and respond accordingly. The new aspects of VBXs in version 2 and 3 dealt with support for graphical controls and data binding; not many of the former appeared, and the latter are unnecessary, given the database functionality of Delphi.
To add a VBX control to the component library,
1 Open the Install Components dialog box.
2 Choose VBX to open the Install VBX File dialog box.
3 Navigate until you locate the .VBX file you want to add, then choose OK.
4 Once you have added all the VBX controls and other modules you want, choose OK to close the Install Components dialog box and rebuild the component library.
Delphi will then build a wrapper VCL component around the VBX control, thereby integrating it into the Delphi environment. The VBX is not directly linked into your application in any way. Instead it remains as a separate and shareable resource. As such it is important to remember that whatever license file was required to use it in Visual Basic will continue to be required to use it in the Delphi development environment. Note that some VBX controls will only operate properly if they are in your path. If you're unsure, you may wish to place the VBX in the \Windows\system subdirectory.
The Component Palette
Now is a good time to mention the differences in the component palette and the toolbox in Visual Basic. In Visual Basic, you define a set of custom controls to be associated with a particular project. By contrast in Delphi, custom components become part of the development environment itself when installed. Of course, in the case of VBXs, this is only a wrapper but the VBX remains "installed", if not loaded into memory beyond the current project.
This is a sensible and beneficial approach, because the overhead associated with Delphi components is much less than that of VBXs in VB. In Visual Basic, each VBX is a separate dynamic-link library (though it may contain multiple controls) and as such consumes memory and resources. Therefore, in VB it is very important to limit the number of VBXs you keep loaded during development, because you will quite literally run out of resources.
By contrast, there are three reasons this situation is far better and more efficient in Delphi. First, components are typically smaller because they are all inherited from other components you already have installed. For example, the TFileList component is based on the TListbox component which is already loaded. Second, the code behind each component is compiled down to native code when installed in the IDE. For example, the DLL containing all of the standard controls is just over 1 Mb in size. Third, all of the installed components are added to a single dynamic-link library for greater memory and resource efficiency.
That said, it is possible to control which custom components are loaded at a particular point by changing the dynamic-link library currently installed in the IDE. At any point, you can make a copy of the current COMPLIB.DCL under a new name. You can then load that library at some future point. Bear in mind that, like in Visual Basic, it is essential you have all of the required controls installed into the IDE when using a project that requires them. This is not the case with distribution of your completed applications, as Delphi Visual Component Library (VCL) components are linked directly into your EXE file.
Advanced Code
The following sections describe some of the more advanced programming concepts of both Visual Basic and Delphi and how they compare.
Units
While there are many differences, the Unit in Delphi is the functional equivalent of the module in Visual Basic. It represents the fundamental unit of code. In VB, there is an implied module associated with each form and the ability to "Add" further modules to your project containing, procedures, DLL declarations as well as global constants and variables.
In Delphi there is an explicit unit associated with each form that contains all of the code associated with a form, including its class definition. That is why when you save a project in Delphi, you are prompted for a unit name (*.PAS). The form is simply saved with the same name and different extension (DFM). In addition, it is possible to make use of any addition units you desire by way of the Uses clause. Unlike Visual Basic, where modules must be loaded into a project and then are available throughout the application, the actual availability of unit resources in Delphi has nothing to do with project membership a very flexible arrangement!
You gain access to one unit from another by listing that unit in the uses clause of your current unit. As you look at the form in a new project, you can see a tab beneath it labeled "Unit1" as this is the default name for the unit. If you click that tab, you will see the code which already exists in the unit. On the fifth line there is a uses clause which lists a series of units separated by commas:
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs;
These are the default units which are available to all new forms. You don't need to add any of them to your project; Delphi does this for you. Their presence in the uses clause makes their functionality available from within the form. Some of these are significant. For example, WinProcs and WinTypes add all of the functions of the core Windows API. Some of these such as Classes, Graphics, Controls and Forms are required by Delphi to make forms work within your application. You should remove units from this default list with care. In most cases, you won't touch this list because if no functionality from a particular unit is exploited, the code for that unit is not linked in. If you would like to exploit the functionality of Unit1 inside of Unit2, you need to include Unit1 in a uses clause within Unit2.
Like modules, units may contain procedures, DLL declarations, user-defined types and global variables and constants. There are two sections to a unit, the interface and the implementation. The interface is the "public" area of the unit and functionality defined in that area is available anywhere in the application where that unit is listed in a uses clause. The implementation portion of a unit defines the "private" area of that unit so variables, constants and functions defined only there are available only within that unit. This is discussed further in the discussion of variable scope and procedures below.
So, remember that adding a unit to a project is just a convenience for editing and compiling. If you want to access the functionality of that unit, it must find its way into a uses clause in your code.
Variable Scope
Delphi supports nearly all of the levels of scope found in Visual Basic and more. The following table represents the different levels of scope in Visual Basic and their corresponding scopes in Delphi.
Visual Basic Delphi
Local Local
Static typed constant
Module Level Unit Level
Global Global
n/a Object Level
In Visual Basic, if you use the Dim keyword inside a procedure definition, you are defining a variable which is local to that procedure. Likewise if you add a variable to the var section of a procedure in Delphi, you are defining a local variable. There is no equivalent to a static variable in Delphi, but a static variable is really just a module level variable which is used in only one procedure. It is a naming convenience more than anything else.
In Visual Basic, if you use the Dim keyword in the declarations section of a module or form, you are creating a module level variable. Likewise, if you place a variable in the Var clause of the Implementation section of a unit, you are defining a unit level variable (i.e. one which can only be seen from within that unit).
In Visual Basic, if you use the Global keyword in the declarations section of a module, you are defining a global variable. In Delphi, you simply put a variable in the var clause of the interface section of a unit and that variable is available to any other unit which includes the variable's unit in its uses clause. The following code segment helps to clarify:
unit MyUnit;
interface
uses
WinProcs, WinTypes; {these are the units used by this unit}
var
globalInt:integer;
globalStr:string;
implementation
var
unitInt:Integer;
unitStr:String;
procedure unitProc;
const
staticInt:Integer = 0;
staticStr:String = ';
var
localInt:Integer;
localStr:String;
begin
{code goes here}
end;
end.
The preceding was a complete unit with an interface and an implementation section. The variables defined in the interface section are global. The variables defined in var clause of the unit are unit level and finally those defined in the var section of the procedure are local.
Be aware that unit-level variables created inside a form are available across multiple instances of that form. In other words, unlike in Visual Basic, those variables exist only once per application so even though you might have multiple instances of a form, unit level variables are shared.
The way around this is to define a set of variables as part of the new form class you are creating. A typical form definition might look something like this:
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
private
{ Private declarations }
public
{ Public declarations }
end;
You can create the equivalent of VB's "form level" variables by adding them to the private section of the form definition. So the change might look something like this:
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
private
{ Private declarations }
formInt:Integer;
formStr:String;
public
{ Public declarations }
end;
If you don't create multiple instances of your forms in your applications, you'll never know the difference between unit level and form level variables. However, a great many MDI applications begin as single form applications so it is best to use the most restrictive level of scoping you can for flexibility in the future.
Conditional Execution
There are two types of conditional execution in Delphi as in Visual Basic, if..then and case. These constructs are similar in both environments.
If...Then...Else
Nearly every language has some form of the if statement. In its simplest form in Visual Basic, it takes the form:
If <condition> Then <action> Else <action>
which is exactly like the simple form in Delphi. Therefore, the statement,
If chkShow.Value = True Then Text1.Visible =True Else Text1.Visible = False
in Visual Basic, looks like the following in Delphi:
If chkShow.State = cbChecked Then Edit1.Visible := True Else Edit1.Visible := False;
The difference appears when you need to execute multiple lines of code in a condition. As stated above, Object Pascal requires that blocks of code be enclosed in a begin..end pair. So the following would be the Delphi code to set the Visible property of multiple controls to True given a particular condition:
if chkShow.State = cbChecked then
begin
Edit1.Visible := True;
Edit2.Visible := True;
end;
Now take a look at an example involving else. You will notice a small anomaly in syntax in this instance:
if chkShow.State = cbChecked then
begin
Edit1.Visible := True;
Edit2.Visible := True;
end
else
begin
Edit1.Visible := False;
Edit2.Visible := False;
end;
The one exception to the rule about ending each line with a semicolon is with lines immediately preceding an else. Accordingly, you will notice above that the first end statement doesn't have a semicolon because it is immediately followed by else. These begin..end pairs should not be confused with VB's requirement to complete a multi-line if block with an EndIf. There is no EndIf equivalent in Delphi. You can, of course, nest if statements as long as each block of code is wrapped in begin..end.
Case
The Select Case statement in Visual Basic is designed to provide a more elegant structure than a series of multiple if clauses. The case statement in Delphi provides similar functionality. The following code in Visual Basic:
Select Case MyVar
Case 0
J = "Hello"
Case MY_CONST
j = "Goodbye"
Flag = False
Case 2, 3, 5 To 10
j = "How are you?"
End Select
would translate into the following in Delphi's Object Pascal:
case MyVar of
0:
J := 'Hello';
MY_CONST:
begin
j := 'Goodbye';
Flag := False;
end;
2, 3, 5..10:
j := 'How are you?';
Two things should be clear. First, the code block after MY_CONST required a begin..end pair and second, there is nothing like End Select. The case construct simply ends with the last line of code which is the case with most constructs in Object Pascal, including loops, discussed in the next section.
As in Visual Basic, you can combine multiple cases by separating them with a comma. A range is denoted by <LowerVal..HigherVal> rather than the to keyword. There is no equivalent for "Is < 500" Instead, you need to use a range.
When using the case statement in Delphi, remember that you cannot use strings, only numbers for comparison. If you need to compare a series of strings, you will need to create a set of if..then statements. There is, however, a data type in Delphi called char which is a single letter. Because this can be represented as a number, it is possible to use the case statement to compare char values. In other words, the following example would be valid:
var
C:Char;
begin
Case C of
'A':
DoSomething;
'B', 'D'..'G':
DoSomethingElse;
end;
If you need to compare a series of strings, you will need to do that with a set of if..then statements rather than with case.
Loops
As in any language, there are two different kinds of loops, determinate and indeterminate. The difference is simply whether you know the number of times you want the loops to be executed before code execution proceeds. The determinate loop in Visual Basic is the For..Next loop and there is a similar construct in Delphi called the for loop. For indeterminate loops in VB you have the While..Wend and Do..Loop loops. In Delphi, you have the while and repeat..until looping constructs.
The For Loop
As in Visual Basic, the for loop in Delphi allows you to execute a block of code a predetermined number of times. The syntax is very similar. In VB, you might have something that looks like this:
For X = 1 To 10
A = A + X
Next
whereas in Delphi the same thing would be represented like this:
for X := 1 To 10 do
A := A + X;
The two differences are the do keyword at the end of the for statement and the missing Next which is implied by the end of the code block. In other words if you had more than one operation to perform it might look like this in Delphi:
for X := 1 To 10 do
begin
A := A + X;
Caption := IntToStr(X);
end;
where the begin..end block defined the lines of the loop.
In Visual Basic, you can use the Step keyword to specify the increment by which the variable (i.e. X) should be changed. This is used to count by more than one (i.e. Step 5) or to create a decrementing counter (i.e. Step -1). While there is no way to create an increment larger than one in Delphi, it is possible to create a decrementing counter with the downto keyword. It is used in the following manner:
for X := 10 downto 1 do
begin
A := A + X;
Caption := IntToStr(X);
end;
where X begins at 10 and is decremented to 1. As in Visual Basic, loops in Delphi can be nested.
The Do Loop
The functionality of Visual Basic's Do..Loop construct is provided by Delphi's repeat..until style loop. Therefore, the following loop in Visual Basic
Do
K = I Mod J
I = J
J = K
Loop Until J = 0
would look like the following in Delphi
repeat
K := I Mod J;
I := J;
J := K;
until J = 0;
In this example, it is important to remember that the comparison operator in Delphi is a simple = sign, not the := used for assignment. The other thing you will notice for the first time is the conspicuous absence of begin..end. This is because the repeat..until loop takes the place of the begin and end statements. It is the only loop that is contained in this way. All of the other loops are defined only by their first line and therefore require the begin..end pair for multiple lines of code.
The While Loop
The repeat loop, like the Do loop, does its testing at the bottom so the code is executed at least once. Sometimes you want to do your test at the top because there are certain instances in which the code block shouldn't be executed at all. In Delphi, as in Visual Basic, this is accomplished with the while loop. The following example of Visual Basic code:
While CanDraw = True
A = A + 1
Wend
would look like this in Delphi
while CanDraw = True do
A := A + 1;
where, as with the for loop, there is no terminator necessary. Instead, if you want to execute a block of code, you use the begin..end construct. In other words, this Visual Basic code:
While Not Eof(1)
Line Input #1, Text
Process Text
Wend
might look something like this
This is actually taken fron the thread How to choose between VB and Delphi. Since Pradeep has not moved the material, I have done it. All the credit to spradeepraj
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.