Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Delphi Does
.NET
The Delphi for .NET
Compiler Preview
ON THE COVER
4
First Look
FEATURES
9
Greater Delphi
12
Dynamic Delphi
22
OP Tech
27
Sound+Vision
REVIEWS
31
Pascal Analyzer
34
17
Delphi Tools
38
Delphi at Work
NitroSort
DEPARTMENTS
Delphi
T O O L S
New Products
and Solutions
Book Picks
Mastering Kylix 2
Marco Cant and Uberto Barbini
SYBEX
Delphi/Kylix Database
Development
Eric Harmon
SAMS
ISBN: 0-672-32265-X
Cover Price: US$49.99
(500 pages)
www.samspublishing.com
Crystal Decisions
announced Crystal
Reports 9. Designed
for use in all three
major development environments
(Java, .NET, and
COM), Crystal
Reports 9 addresses
key requirements
in the developer
and IT community
today: the need
for improved productivity and high
efficiency in report
creation, the need
for tight integration of reporting into enterprise
Web applications, and the need
for dynamic end-user access,
interaction, and modification.
Crystal Reports provides
sophisticated technology for
rapidly transforming data
from virtually any data source
including XML, OLAP,
enterprise, and relational data
sources into interactive
content. Using Crystal Reports
9, developers and IT professionals can tightly integrate content
Delphi
T O O L S
New Products
and Solutions
Book Picks
JBuilder 7.0 EJB Programming
Chuck Easttom
WORDWARE
ISBN: 1-55622-874-0
Cover Price: US$49.95
(464 pages)
www.wordware.com
ISBN: 0-7897-2748-X
Cover Price: US$49.99
(864 pages)
www.quepublishing.com
a one-way
secure IM
application
for emergency
notifications
and other
broadcast
applications; and a
Web-based
IM interface.
These can
be readily
adapted to
internal and
customerfacing
applications, such as CRM, ERP,
Enterprise Information Portals
(EIP), Web front-ends, line-ofbusiness, and legacy applications.
WiredReds e/pop Enterprise
Server provides the server component for the e/pop SDK RunTime Client. The Server delivers
authentication, security, directory service integration, groups,
profiles, and other central management capabilities to custom
client applications. The Server
supports multi-server topologies,
multi-threading, and symmetric multi-processing (SMP),
FlexCompress is a high-speed
compression library developed
to provide archive functionality for your applications.
Easy Compression Library is
a toolkit with everything you
need to compress and encrypt
files, streams, strings, data
packets, and even BLOB fields.
Single File System is a library
thats designed to provide an
easy way to work with multiple
First Look
Microsoft .NET Framework / Delphi for .NET Compiler Preview / Delphi 7 Studio
he new version of Borlands Delphi product, Delphi 7 Studio, comes with a preview version of Delphi Compiler for .NET. In this article, well begin to discuss
its features and possibilities. However, keep in mind that this material is based on
a pre-release version of the software; the shipping version may differ from what is
described here.
First Look
Console.WriteLine('Hello, World!');
end.
First Look
program Env_Demo;
{$APPTYPE CONSOLE}
uses System;
var
Args : array of string;
Str : string;
I
: Integer;
begin
Str:= System.Environment.CommandLine;
Console.WriteLine('The command line is ' +
System.Environment.CommandLine);
Console.WriteLine('The directory is ' +
System.Environment.CurrentDirectory);
Console.WriteLine('The .NET Framework version is ' +
System.Environment.Version.ToString);
Console.WriteLine('The Path variable is ' + System.
Environment.ExpandEnvironmentVariables('%Path%'));
Args := System.Environment.GetCommandLineArgs;
for I := Low(Args) to High(Args) do
Console.WriteLine('The command line argument number ' +
IntToStr(I) + ' is ' + Args[I]);
end.
Microsoft has implemented similar classes to support porting of pre.NET VB code in the Microsoft.VisualBasic.Compatibility assembly that
comes as part of the Microsoft .NET Framework. (If youre interested
in Delphi for .NET code internals, the best way to examine them is to
study the IL code generated by the compiler using the ILDASM utility.)
Lets go back to the console application and add some interactivity to
it. For example, you can use the ReadLine method of the Console class:
program Greetings;
var
Name : System.String;
begin
Console.WriteLine('What is your name?');
Name := Console.ReadLine();
Console.WriteLine('Hello, ' + Name + '!');
end.
First Look
program Ref_Demo;
{$APPTYPE CONSOLE}
program Ref_Demo2;
{$APPTYPE CONSOLE}
uses System.Reflection;
uses System.Reflection;
var
I : Integer;
T : System.Type;
M : System.Reflection.Module;
Types : array of System.Type;
begin
T := Int32.GetType;
M := T.Module;
Console.WriteLine('The module name is ' +
T.Module.Name + chr(10));
Console.WriteLine('The list of types: ');
Types := M.GetTypes;
for I := Low(Types) to High(Types) do
Console.WriteLine(Types[I].FullName);
end.
var
I : Integer;
T : System.Type;
Asmb, LoadedAsmb : System.Reflection.Assembly;
Types : array of System.Type;
begin
LoadedAsmb := Asmb.Load('mscorlib.dll');
Console.WriteLine('The list of types: ');
Types := LoadedAsmb.GetTypes;
for I := Low(Types) to High(Types) do
Console.WriteLine(Types[I].FullName);
end.
library TestNamespace.TestDelphiClass;
uses System;
type
TTestClass = class
constructor Create;
procedure Output(S: string);
end;
constructor TTestClass.Create;
begin
Inherited Create;
end;
procedure TTestClass.Output(S: string);
begin
Console.WriteLine('Hello, ' + S + '!');
end;
end.
Language Interoperability
Another great thing .NET provides is language interoperability
based on the Common Language Specification the set of rules
every .NET-compliant language must obey. This means we can
mix code written in one language into applications written in
another language, and even create descendants of classes written
with different languages.
First Look
Imports System,TestNamespace.TestDelphiClass
Module DelphiVBDemo
Sub Main()
Dim DelphiClass As New TTestClass
Dim Name As String
Console.WriteLine("What is your name?")
Name = Console.ReadLine()
DelphiClass.Output(Name)
End Sub
End Module
Lets look at how Delphi can join the family of .NET languages.
Lets start with a new Delphi class. To do this we need to create
a library where we define such a class (see Figure 11). This class
is named TTestClass, which has an Output method that accepts a
string and writes it to the .NET Console object.
Now lets use this newly created Delphi class in the Visual Basic
.NET application. To do this, we need to refer to the appropriate
namespace defined in our library, as shown in Figure 12.
To compile this VB .NET application, use the following command:
vbc DelphiVBDemo.vb /r: TestDelphiClass.dll
Conclusion
Weve created console applications with the preview version of the
Delphi for .NET compiler. We also saw how to implement simple
Greater Delphi
Windows XP Themes / Delphi 7
By Corbin Dunn
ne of the great new features in Delphi 7 Studio is its native support for Microsoft
Windows XP themes. This article will cover the basics of enabling theme support
in your applications and custom controls.
Delphi developer Mike Lischke did the majority
of the basic theme support, and has some freeware
theme code for other versions of Delphi available
on his Web site at http://www.delphi-gems.com/
ThemeManager.html. I had a hand in some of
the development; I fixed some bugs, created the
TXPManifest component, and incorporated theme
support into the IDE itself.
Greater Delphi
procedure TMyButton.Paint;
var
TextVert, TextHorz: Integer;
ElementDetails: TThemedElementDetails;
begin
TextVert :=
(ClientHeight - Canvas.TextHeight('X')) div 2;
TextHorz :=
(ClientWidth - Canvas.TextWidth(Caption)) div 2;
if ThemeServices.ThemesEnabled then
begin
{ Draw the themed "button" look by getting the
correct element details for a button element.
FMouseInUs will be True when the mouse is in
the control. }
if not Enabled then
ElementDetails := ThemeServices.
GetElementDetails(tbPushButtonDisabled)
else if MouseCapture and FMouseInUs then
begin
ElementDetails := ThemeServices.
GetElementDetails(tbPushButtonPressed);
Inc(TextVert);
Inc(TextHorz);
end
else if FMouseInUs then
ElementDetails := ThemeServices.GetElementDetails(
tbPushButtonHot)
else
ElementDetails := ThemeServices.GetElementDetails(
tbPushButtonNormal);
{ Use the ThemServices to draw the details. }
ThemeServices.DrawElement(Canvas.Handle,
ElementDetails, ClientRect);
{ Draw text, setting the Brush.Style to bsClear so we
can see the theme elements behind the text. }
Canvas.Brush.Style := bsClear;
Canvas.TextOut(TextHorz, TextVert, Caption);
end
else
begin
{ Non-themed: no disabled look for simplicity,
and no "hot tracking". }
if MouseCapture and FMouseInUs then
begin
DrawFrameControl(Canvas.Handle, ClientRect,
DFC_BUTTON, DFCS_BUTTONPUSH or DFCS_PUSHED);
Inc(TextVert);
Inc(TextHorz);
end
else
DrawFrameControl(Canvas.Handle, ClientRect,
DFC_BUTTON, DFCS_BUTTONPUSH);
Canvas.Brush.Color := Color;
Canvas.TextOut(TextHorz, TextVert, Caption);
end;
end;
{$R WindowsXP.res}
Greater Delphi
Add or remove csParentBackground in the
ControlStyle by using the ParentBackground
property. By default, the property is protected
because it isnt applicable to all TWinControls.
Any component in which youd want to turn
on or off this transparent ability should publish
the ParentBackground property. At Borland, we
published it for controls such as TPanel and
TCustomFrame, in which one might want them
to paint with their assigned Color, and not their
Parents background.
Conclusion
In the themed version (Figure 3), the TSimplePanel on the top left
of the TPageControl appears to have transparent portions, but the
bottom-right one does not. The top left simply has csParentBackground
added to its ControlStyle, and the bottom-right one does not.
Whenever a TWinControl processes a WM_ERASEBKGND message, it will paint with its Parents background if csParentBackground
is in its ControlStyle. This gives the illusion that portions of the
control are transparent.
For most applications, simply adding a manifest will enable theme support on Windows XP.
For others that have a lot of custom drawing
and controls, you will have to do a little work
to enable theme support. Dont forget to download the sample source code to see the complete
source for TMyButton and TSimplePanel.
Corbin Dunn is a research and development software engineer for Borland Software
Corporation. When he isnt hacking new features into the IDE, he can be found
scaling steep rocks in the Santa Cruz mountains or hanging out in his tree house
(http://www.corbinstreehouse.com). Readers may reach Corbin at cdunn@borland.com.
Dynamic Delphi
Windows XP Themes / Open Tools API / Wizards / Delphi 6, 7
By Fernando Vicaria
An XP Application Wizard
Extend Delphi 6, 7 IDEs to Support Windows XP Themes
elphi is an extensible development tool, not only when it comes to creating and
using your own components, but also with respect to its IDE. Delphis Open Tools
API (or OTA) enables you to create your own tools that work closely with the IDE. This
article will address two seemingly disparate topics: Windows XP themes support and
wizards. In it, I will show you how to extend the IDE to create a wizard that helps you
create an XP application project.
The OTA is a set of interfaces that allows you to
extend the Delphi IDE in many different ways.
One well-known way is to create a custom component and add it to the Component palette. Other
ways include creating a property and component
editors, a version control manager, or a wizard.
Although each of these is used differently, each
uses the same mechanism to attach to the IDE.
Note that the OTA is available only with the
Enterprise and Professional editions of Delphi. You
can add and use the wizard in this article if you
have the Standard edition, but you will not be able
to modify it or recompile it.
What Is a Wizard?
A wizard (previously known as an expert) is just a
tool to help you accomplish a particular task. It might
Interface
Description
IOTAFormWizard
IOTAMenuWizard
IOTAProjectWizard
IOTAWizard
Dynamic Delphi
Borland is working hard on new documentation that covers the
OTA, and you should see the results in Delphi 7 Studio, which has
a new help file dedicated to this issue. Its still hard to find accurate
OTA sample code on the Internet. I hope this article will help to
spread some of what the folks at Borland are preaching. At the end
of this article youll find a list of good references and information
on how to download the files that accompany this article.
{ TXPAppProjectWizard }
TXPAppProjectWizard = class(TNotifierObject, IOTAWizard,
IOTARepositoryWizard, IOTAProjectWizard)
public
{ IOTAWizard }
procedure Execute;
function GetIDString: string;
function GetName: string;
function GetState: TWizardState;
{ IOTARepositoryWizard }
function GetAuthor: string;
function GetComment: string;
function GetPage: string;
function GetGlyph: Cardinal;
end;
sure the chosen name doesnt clash with that of an existing project
(see Figure 4).
Another class necessary for this wizard is TXPAppModuleCreator
(shown in Figure 5), which takes care of generating a new module for
your project in this case, the default main form for your application. It will implement the IOTAModuleCreator interface. Delphi uses
IOTAModuleCreator to add new forms and units to the current project.
Implementing TXPAppModuleCreator will also be very simple.
The interesting methods this time will be CreateModule and
NewProjectSource. CreateModule will generate a new module by
calling GetNewModuleAndClassName, which will create a unique
module name and class name, given a class prefix such as Form:
constructor TXPAppModuleCreator.CreateModule;
begin
inherited Create;
(BorlandIDEServices as IOTAModuleServices).
GetNewModuleAndClassName('Form', FModuleName,
FFormName, FFileName);
end;
NewImplSource provides the source code for the module. The source for the
default module (and for the project) is hard-coded into a constant string:
function TXPAppModuleCreator.NewImplSource(const
ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
begin
Result := TXPSourceFile.CreateNamedFile('', Format(
XPModuleSource, [ModuleIdent, FormIdent,
AncestorIdent]));
end;
Dynamic Delphi
{ TXPAppProjectCreator }
TXPAppProjectCreator = class(TInterfacedObject,
IOTACreator, IOTAProjectCreator)
public
{ IOTACreator }
function GetCreatorType: string;
function GetExisting: Boolean;
function GetFileSystem: string;
function GetOwner: IOTAModule;
function GetUnnamed: Boolean;
{ IOTAProjectCreator }
function GetFileName: string;
function GetOptionFileName: string;
function GetShowSource: Boolean;
procedure NewDefaultModule;
function NewOptionSource(const ProjectName: string):
IOTAFile;
procedure NewProjectResource(const Project: IOTAProject);
function NewProjectSource(const ProjectName: string):
IOTAFile;
end;
{ TXPAppModule }
TXPAppModuleCreator = class(TInterfacedObject, IOTACreator,
IOTAModuleCreator)
private
FFileName: string;
FFormName: string;
FModuleName: string;
public
constructor CreateModule;
{ IOTACreator }
function GetCreatorType: string;
function GetExisting: Boolean;
function GetFileSystem: string;
function GetOwner: IOTAModule;
function GetUnnamed: Boolean;
{ IOTAModuleCreator }
function GetAncestorName: string;
function GetImplFileName: string;
function GetIntfFileName: string;
function GetFormName: string;
function GetMainForm: Boolean;
function GetShowForm: Boolean;
function GetShowSource: Boolean;
function NewFormFile(const FormIdent,
AncestorIdent: string): IOTAFile;
function NewImplSource(const ModuleIdent, FormIdent,
AncestorIdent: string): IOTAFile;
function NewIntfSource(const ModuleIdent, FormIdent,
AncestorIdent: string): IOTAFile;
procedure FormCreated(const FormEditor: IOTAFormEditor);
end;
XP Themes
By now, you might have noticed that all that the main project
source does differently from a conventional Visual Component
Library (VCL) application is to add the following line of code:
{$R DelphiXP.res}
This resource file, however, includes the manifest for your application, which is mandatory for XP applications. Windows XP has
a theme manager that changes the look and feel for most of the
standard Windows controls.
The actual manifest is the file DelphiXP.manifest. You can edit this
file to fit the requirements of your company. The file is basically an
XML document containing the name, version, author, and dependencies information as well as other information related to your
executable (or assembly, in the .NET world). The manifest is also
responsible for telling Windows which version of the comctl32
library its supposed to use with your application: the older version
(5.8) thats compatible with all flavors of Windows, or the newer
version (6.0) thats compatible only with Windows XP.
The main idea behind version 6.0 was to clean up the code contained within the DLL. The downside is that now there are two
versions of the same control to maintain: one that is backwardcompatible with all previous versions, and one that is not.
Apart from the classes described so far, youll also need a couple
of general-purpose functions to identify the current active project
and project group, if either exist. Youll also define two string
constants to hold the source code for the project file, and the
By default, all programs written under Windows XP will use version 5.8, maintaining the same look and feel as the legacy Windows
applications. To use version 6.0, you must include a manifest in
Dynamic Delphi
{ Register the wizard. }
procedure Register;
var
S: TResourceStream;
Services: IOTAServices;
TargetFile: string;
begin
RegisterPackageWizard(
TXPAppProjectWizard.Create as IOTAProjectWizard);
S:= TResourceStream.Create(
HInstance, 'DELPHIXP', RT_RCDATA);
try
if Supports(BorlandIDEServices,
IOTAServices, Services) then
begin
TargetFile:=
Services.GetBinDirectory + 'DelphiXP.res';
if not FileExists(TargetFile) then
S.SaveToFile(TargetFile);
end;
finally
S.Free;
end;
end;
your application that Windows will read to find out which version
it should load. If it cant find one, either built into the application
as a resource or as a standalone file, Windows will load the old
version. If you alter the manifest file, you will have to recompile the
resource file, using Delphis resource compiler (brcc32.exe).
Note that the Windows XP theme manager wont do anything
to your owner-drawn controls. For these controls, you will have
to ask uxtheme.dll to draw them. Delphi 7 will include its own
implementation for a theme manager and a translation for the
uxtheme DLL.
Registration
To complete your wizard and make sure it has been added to the
IDE properly, you need to include a Register procedure, much
the same way you do when adding your custom components to
Delphis Component palette (Figure 6).
As you can see, the Register procedure delegates the responsibility
of registering the wizard with the IDE to RegisterPackageWizard.
Then, the procedure retrieves the resource file that will be added
to the applications your wizard is going to create. The resource
file is placed inside the wizards resource. This is done to guarantee that your wizard can always find the resource file.
Figure 8: The New Items dialog box and the new XP application wizard.
Warnings
Microsoft has eliminated a lot of the support code in the comctl32
library. Consequently, some of the standard controls might not
behave exactly as they did with older versions, and, in some
cases, they can even crash applications compiled for the previous
versions. One typical example is Windows new ImageList control,
which is incompatible with the old ones. This incompatibility
could crash old executables compiled with Delphi 6 or earlier,
for example, when you decide to give a manifest to it. Eddie
Churchill, a research and development engineer at Borland, has a
very interesting article in which he exposes a bit of his frustration
and Borlands ongoing battle to maintain compatibility with
comctl32. You can find his article at Borlands community site at
http://community.borland.com/article/0,1410,28423,00.html.
Conclusion
In this article, I tried to expose a relatively unknown and often
misused part of Delphi, the OTA. You saw how to create a
simple project wizard for creating an application that would
Dynamic Delphi
take part in the new Windows XP themes feature. The main
difference between this wizard and the already popular File | New
| Application is that you included a manifest file into the project
as a resource. This manifest will tell Windows, at the time your
application is loaded into memory, whether Windows should use
the new version of Microsofts comctl32 DLL.
Further Reading
The following is a list of OTA-related samples, tutorials, and
resources available on the Internet:
Eriks Open Tools API FAQ and Resources
http://www.gexperts.org/opentools
DelphiOTA http://www.xs4all.nl/%7Erappido/delphi/
delphi.html
Ray Lischners Open Tools API
http://www.tempest-sw.com/opentools
Borlands Open Tools API Newsgroups
news://newsgroups.borland.com/borland.public.
delphi.opentoolsapi
On XP and themes, try these:
The Microsoft Developer Network
http://msdn.microsoft.com/library/default.asp?url=/library/
en-us/dnwxp/html/winxpintro.asp
Abouts Windows XP Manifest in Delphi
http://delphi.about.com/sitesearch.htm?terms=Windows%20
XP%20Manifest%20in%20Delphi%20&SUName=delphi&T
opNode=3042&type=1
Mike Lischkes Windows XP Theme Manager
http://www.delphi-gems.com
All files referenced in this article (manifest, resource, package, etc.)
are available on the Delphi Informant Magazine Complete Works
CD located in INFORM\2002\NOV\DI200211FV.
Fernando Vicaria is a quality-assurance engineer at Borland Software Corporation in Scotts Valley, CA. He is also a freelance technical author who writes
about Delphi and C++Builder issues. Fernando is specialized in VCL and CLX
frameworks. When hes not at work, hes probably surfing at some secret spot in
Northern California. He can be reached via e-mail at fvicaria@borland.com.
Delphi at Work
XML / DOMs / Interfaces / Delphi 6
By Keith Wood
n the Part I and Part II of this three-part series, you learned that the concept of XML
building blocks is built around two interfaces: one for producing XML documents as
Document Object Model (DOM) objects and another for accepting a DOM object with
which to work. Components that implement one or both of these interfaces can be
linked to form chains of processing for an XML document. Because the properties of
these components are published, much of the work can be done at design time, leaving only a single call to the first producer to get the sequence going.
In this article, Ill develop several consumer building blocks that interact with GUI controls. By
using these new building blocks, you can create
and modify your DOM easily before displaying
the results to the user. The options Ill cover for
presenting a DOM are TreeView, StringGrid, and
Memo components, and a Web browser.
TreeView
XML documents have an inherent hierarchical
structure, which makes the TreeView an ideal way
of presenting the documents contents. Each node
in the DOM becomes a node in the tree with corresponding parents and children.
The TXBBTreeView class populates a TreeView from
the DOM it is given (see Listing One at the end
of this article). A new property, TreeView, lets you
associate a TreeView component with this building block. Remember to override the Notification
method to clear this reference if the TreeView
control should be deleted.
Delphi at Work
nodes depends on the DOM nodes type:
Document nodes are hard-coded, text-based
nodes use their nodeValue, and all others use
their nodeName.
The ShowNodes property is the set of node types
from the DOM to include in the TreeView.
Once a node is rejected because of this filter,
all of its children are also ignored. You should
always include ntDocument in the set. You wont
see much without having ntElement there, as
well. The ShowNodes property is published so it
can be set at design time.
To make working with the underlying DOM
easier, it would be useful to have access to the
actual DOM nodes corresponding to each tree
node. Unfortunately, you cannot save a direct
reference to an interface in the Data property
of a tree node. Instead, you need a simple
wrapper class that maintains that reference.
Figure 2: A single-node string-grid display.
So, as each node is added to the tree, a new
TXBBNodePointer is created around the DOM
node and is set as the object associated with that node. Then, you can
{ Display a DOM within a Memo. The XML text corresponding
to the DOM is displayed in the attached Memo
retrieve the original DOM node through the following code:
DOMNode := TXBBNodePointer(trvXML.Selected.Data).Node;
StringGrid
For XML documents with a degree of repeated sub-structure, a
StringGrid offers an alternative and more compact way of presenting
the contained data. The document should have a main element that
contains multiple copies of a single type of sub-element, which has
just text content or only one further layer of child elements. Then,
each of the multiple elements becomes a row in the grid, with its
contents forming the columns.
(Memo property). }
TXBBMemo = class(TXMLBuildingBlock)
private
FMemo: TMemo;
protected
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
function ProcessDocument(const Document: IDOMDocument):
IDOMDocument; override;
public
constructor Create(AOwner: TComponent;
const Memo: TMemo = nil); reintroduce; overload;
published
property Consumer;
property Memo: TMemo read FMemo write FMemo;
end;
{ Copy the DOM as text into the Memo. }
function TXBBMemo.ProcessDocument(
const Document: IDOMDocument): IDOMDocument;
var
Stream: TMemoryStream;
begin
if not Assigned(Memo) then
Exit;
Memo.Lines.Clear;
Stream := TMemoryStream.Create;
try
(Document as IDOMPersist).SaveToStream(Stream);
Stream.Position := 0;
Memo.Lines.LoadFromStream(Stream);
finally
Stream.Free;
end;
Result := Document;
end;
The ProcessDocument method is overridden to populate the StringGrid with the documents content. If no StringGrid has been
connected to it, an error occurs. Otherwise, the StringGrid is sized
appropriately based on the format desired and the number of child
nodes the document has. Then, the cells of the grid are filled. For the
Delphi at Work
TXBBMemo has a property named Memo that
identifies the Memo control to update, and
that promotes the visibility of the Consumer
property to allow for extending the processing
chain (see Figure 3). If the attached Memo is
deleted, the class removes any references to it
through the Notification method.
In the ProcessDocument code, the
component saves the contents of the
DOM passed in to a stream in memory
and then loads the Memos Lines property
from that stream. See Figure 4 for an
example of using this component. An XML
document generated from a database query
is amended by including a time-stamp
element at its start, before sending the text
version of that DOM to the Memo.
Web Browser
{ Display a DOM within a Web browser. }
TXBBWebBrowser = class(TXMLBuildingBlock)
private
FTempFileName: TFileName;
FWebBrowser: TWebBrowser;
protected
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
function ProcessDocument(const Document: IDOMDocument):
IDOMDocument; override;
public
constructor Create(AOwner: TComponent); overload;
override;
constructor Create(AOwner: TComponent;
const WebBrowser: TWebBrowser); reintroduce; overload;
published
property Consumer;
property TempFileName: TFileName
read FTempFileName write FTempFileName;
property WebBrowser: TWebBrowser
read FWebBrowser write FWebBrowser;
end;
{ Copy the DOM contents into the Web browser. }
function TXBBWebBrowser.ProcessDocument(
const Document: IDOMDocument): IDOMDocument;
begin
if not Assigned(WebBrowser) then
Exit;
{ Unfortunately it must be saved to a file first. }
(Document as IDOMPersist).Save(TempFileName);
WebBrowser.Navigate(TempFileName);
Result := Document;
end;
single-node format, the cells just contain the name and text value of
the child nodes. The text value is retrieved by the GetText function,
which combines text from the current node and one level down to
handle simple sub-elements. For the multiple-node format, first
the component must determine which column to use, based on the
nodes name, before inserting the text. New columns are added as
necessary. Figure 1 shows the StringGrid in its multiple-node format,
and Figure 2 shows the single-node version.
Memo
Often, you wish to view the XML source for a DOM. A simple
building block that writes to a TMemo field provides the answer.
19 November 2002 Delphi Informant Magazine
The TWebBrowser component in Delphi is a wrapper around Microsofts Internet Explorer control. As such, it knows about HTML and
XML documents and can display either. You can incorporate this
ability easily by creating another building block that transfers the
contents of a DOM to the browser.
Extending TXMLBuildingBlock is the TXBBWebBrowser component
(see Figure 5). It exposes the Consumer property, adds a WebBrowser
property to link to a browser, and adds a TempFileName property to
use when loading the browser. Because the Web browser cannot be
filled directly, its necessary to save the DOM contents to a file first
and then read that in. This process has the added benefit of identifying the type of document to load HTML or XML based on
the files extension.
As before, you override the ProcessDocument method to accept the
DOM, write it out to the specified temporary file, and then read it
back in to the Web browser. Recall that you also should override the
Notification method to tidy up, if the attached Web browser component is deleted from the form.
Figure 6 shows the results of using this component. As you can see,
the parser loads in a document (movie-watcher.xml), applies an XSL
transformation to it (movies-html.xsl), and directs the results to
the Web browser. Because this particular transformation generates
HTML (although its formatted as an XML document), the temporary file name for the TXBBWebBrowser component is set to
c:\temp\xbbtemp.html. When loaded into the browser, the html
extension determines how the document is handled.
Demonstration
The demonstration program that accompanies this article lets you
experiment with the components Ive presented in this three-part series
(see the end of the article for details on downloading files). Each component is associated with a button or label on the left side of the form,
with the lines indicating possible connections between them. Select the
check box next to each one to include it in a run (the merge and fork
components automatically are used when necessary).
Components at the top of the panel represent the producers, creating
DOMs from existing documents, SQL databases, text files, or even
Delphi components. Those components in the middle alter the DOM
as it passes through, and those at the bottom are the final consumers of
Delphi at Work
ing can be added as needed just by implementing the interfaces.
To start things off, several DOM producers
were developed. These components created
DOMs from existing XML documents (either
in a file, in a stream, or on the Web), from a
query submitted to a SQL database, or from
wrapping the contents of a text file. Other
components modified these DOMs by merging several documents into one, by adding
a time-stamp element to the DOM, or by
applying an XSL transformation to it.
Conclusion
The XML building-block approach provides a suite of components
that work with XML documents expressed as DOMs. They can be
linked together easily to create chains of processing for XML. By creating simple, generic components, they can be combined in numerous
ways to generate the handling your application requires. New process-
Keith Wood hails from Brisbane, Australia. He is a consultant using Delphi and
Java. He started using Borlands products with Turbo Pascal on a CP/M machine.
His book, Delphi Developers Guide to XML, covers many aspects of XML from a
Delphi point of view. You can reach him via e-mail at kbwood@compuserve.com.
Delphi at Work
for Index := 0 to Node.ChildNodes.Length - 1 do
PopulateTree(Node.ChildNodes.Item[Index], NewNode);
end;
begin
if not Assigned(TreeView) then
Exit;
TreeView.Items.BeginUpdate;
ClearTree;
PopulateTree(Document, nil);
TreeView.Items.EndUpdate;
Result := Document;
end;
begin
with StringGrid do begin
Element
:= Document.DocumentElement;
ColCount
:= 2;
RowCount
:= Element.ChildNodes.Length + 1;
FixedCols
:= 0;
FixedRows
:= 1;
Cells[0, 0] := 'Element';
Cells[1, 0] := 'Value';
for Index := 0 to Element.ChildNodes.Length - 1 do
begin
Node := Element.ChildNodes.Item[Index];
Cells[0, Index + 1] := Node.NodeName;
Cells[1, Index + 1] := GetText(Node);
end;
end;
end;
{ Present the DOM, i.e. the nodes beneath the document element,
in multiple columns. This assumes that the document element
contains multiple instances of the same type of element.
Each row is then one of these elements, and each column is
one of its sub-elements. }
procedure DoMultipleNodes;
var
Element: IDOMElement;
Node, Node2: IDOMNode;
Index, Index2, Column: Integer;
Text: string;
begin
with StringGrid do
begin
Element
:= Document.DocumentElement;
ColCount
:= 2;
RowCount
:= Max(2, Element.ChildNodes.Length+1);
FixedCols
:= 1;
FixedRows
:= 1;
Cells[0, 0] := '#';
Cells[1, 0] := '#text';
Cells[0, 1] := '';
Cells[1, 1] := '';
ColWidths[0] := 20;
ColWidths[1] := 20;
for Index := 0 to Element.ChildNodes.Length - 1 do
begin
Node := Element.ChildNodes.Item[Index];
Rows[Index + 1].Text := '';
Cells[0, Index + 1] := IntToStr(Index + 1);
for Index2 := 0 to Node.ChildNodes.Length - 1 do
begin
Node2 := Node.ChildNodes.Item[Index2];
Text := GetText(Node2);
for Column := 1 to ColCount - 1 do
if Node2.NodeName = Cells[Column, 0] then
Break;
ColCount
:= Max(ColCount, Column + 1);
Cells[Column, 0]
:= Node2.NodeName;
Cells[Column, Index + 1] := Text;
ColWidths[Column]
:=
Max(20, Min(ColWidths[Column], Canvas.TextWidth(Text)));
end;
end;
end;
end;
begin
if not Assigned(StringGrid) then
Exit;
if SingleNode then
DoSingleNode
else
DoMultipleNodes;
Result := Document;
end;
OP Tech
Run-time Packages / Delphi 5, 6
By Rick Spence
Run-time Packages
Adding Functionality and Flexibility to Your Apps
his article shows you how you can divide your application into packages, which you
can then deploy separately from the core application. The core application can offer
more or less functionality according to the presence or absence of the packages.
This is ideal in situations where certain parts of an
application are only available to users purchasing
them separately, or after registering. An accounting
package, for example, may have an optional payroll
module which is only available for an additional
fee. You can deploy the payroll functions in a separate package, and have the main application detect
its presence or absence and react accordingly. The
main application can function with or without the
package, and doesnt need to change.
We start with an overview of the two types of
packages: design-time and run-time. Most of you
OP Tech
Recognizing this, Borland ships Delphi with a number of run-time
packages already built for the VCL, and that allow you to build
your application using them. To do this, open the Project Options
dialog box and select the Packages tab (see Figure 1). You will see
a check box labeled Build with runtime packages. If you check this,
you can then select which packages you want to use. If youre using
Delphi 5, youll see packages with names such as Vcl50, Vclx50,
VclSmp50, Vcldb50, etc.
DPK
DCP
DCU
With Delphi 6 the packages have been renamed, and youll see names
such as VCL, RTL, VCLDB, etc. In both versions of Delphi, the file
extensions of these files when using run-time packages is .DCP, and
youll find them located in your \Delphi\Lib directory. These are the
run-time packages supplied by Borland, each of which contains a
portion of the VCL. You can opt to link with all these run-time packages, or just choose the ones you want.
BPL
If your package contains units that require the VCL, the Package
editor will automatically include the required VCL run-time packages. In this case, you should also build your main application using
the VCL run-time packages; otherwise, youll be distributing the
VCL twice once as part of the executable, and once as a run-time
package required by your own run-time package. If youre creating a
package that contains only functions and does not require the VCL,
remove vcl50.dcp from the Requires list.
When you save the package (using File | Save As), Delphi will create
a file with a DPK extension the package source code. When you
compile the package, it will create the DCP, DCU, and BPL files.
OP Tech
implements some sort of interface between the main application
and the package, but does nothing. However, this will not work
either. Another problem with static linking is that if you change
the contents of the package, or replace it with another package
entirely, you must relink the main application. Static linking,
then, wont work for us, so lets look at dynamic linking.
Dynamic linking of packages is pretty much identical to dynamic
linking of DLLs packages are a special type of DLL after all.
If youve worked with DLLs, then youll be right at home with
dynamic packages. Lets start by writing a simple main application
that will call a routine from a dynamically-linked package.
Well assume our package contains a procedure named PackageRoutine
that takes no parameters. If you just make a call to PackageRoutine,
the linker will fail with Undeclared identifier: PackageRoutine
because we have not declared it anywhere. If we had the routine already
written, and part of a package, we could add the Pascal file to the uses
clause and add the package to the list of required run-time packages,
but then that would be linked statically. We want the package to be
linked to the main application when the main application is loaded.
To do this, we must tell the compiler that PackageRoutine is external to
our application, and tell it where it can find it. You use the same syntax
as when telling the compiler that PackageRoutine is part of a DLL:
procedure PackageRoutine; external 'PackageTest.bpl';
procedure PackageRoutine;
begin
MessageBox(0, 'PackageTest', 'In PackageRoutine',
MB_OK + MB_ICONINFORMATION);
end;
Note that we used the MessageBox API call rather than a VCL function.
This relieves us from having to use VCL run-time packages (although in
practice you will probably need to).
You must now tell the compiler that this function should be exported;
that is, it should be visible to other programs that want to call it:
exports PackageRoutine;
Place this exports statement inside the implementation section, after the
last procedure, but before the final end keyword. The entire Pascal file is
shown in Figure 4.
As you saw, when you call a routine from a package, the caller must
indicate that the called routine is external. You saw how to do this in the
previous section. You list the name of the routine and the package in
which it is declared, as in:
procedure PackageRoutine; external 'PackageTest.bpl';
What youre actually doing here is telling the compiler that this routine
does indeed exist, and in which run-time package it is contained. In
this case, we have a very simple routine. Its a procedure, rather than a
function, so doesnt return a value. Furthermore, the procedure doesnt
accept any parameters. If the routine youre calling is a function, you
must tell the compiler, as part of this external declaration, what the
functions return type is. And if the routine accepts parameters, you
must also specify those types as part of the external declaration. This is
so the compiler can generate correct code. Note that the compiler has
no way of verifying that the routine actually accepts the parameters you
tell it; be careful with these declarations, theyre often a source of error.
For examples of writing these external declarations look at the VCLs
Windows.Pas unit file. It contains declarations for routines declared in
the Windows API.
In summary, then, to dynamically link to routines declared in a package,
take the following steps:
1) Create a package, and set its output directory to the same place as
the other BPL files on your computer (usually \WINNT\system32
for Windows 2000).
2) Add Pascal files to this package, and declare any routines you want
to be called as external.
OP Tech
3) In the Pascal file that calls the routine from the package, declare the
called routine as external. Be sure to specify the name of the BPL file
in quotes, and include the .BPL extension. You must also specify any
parameters, and if the routine you are calling is a function its
return type.
4) Add the directory containing the DCP file (the compiled version of
the package) to the calling projects directory.
try
packModule := LoadPackage('PackageTest.bpl');
try
ShowMessage('Loaded OK');
finally
UnloadPackage(packModule);
end;
except
ShowMessage('Not found');
end;
To proceed to call the function, you must tell the compiler that procAddr
is actually a pointer to a procedure (a procedural type) using a typecast.
In this simple case we can define a new type, ProcPtr, as a pointer to a
procedure which does not accept any parameters:
type
ProcPtr = Procedure;
try
LoadPackage('PackageTest.bpl');
except
ShowMessage('Not found');
end;
To call this routine, you typecast the return result of getProcAddress to this
type, then pass the string:
OP Tech
Summary
function PackageExists(packageName: string): Boolean;
var
packModule : HModule;
begin
try
packModule := LoadPackage(packageName);
try
result := True;
finally
UnloadPackage(packModule);
end;
except
result := False;
end;
end;
Sound+Vision
DirectShow / DirectX Media Objects / Delphi 5, 6
By Ianier Munoz
Sound+Vision
Prerequisites
To understand this article, you should
be familiar with DirectX concepts, such
as filters and filter graphs. I recommend
reading Jon Webbs series of articles named
Delphi Does DirectShow in the January
and March 2002 issues of Delphi Informant.
You also should be familiar with COM
programming concepts, such as aggregation.
Aggregation is an object-reuse mechanism
in which an outer object exposes
interfaces from inner objects as if they
were implemented on the outer object
itself. The outer and inner objects are said
to form an aggregate. You may want to
search for the topic COM aggregation
in the MSDN Library for more details.
Setting up a Framework
type
IVolumeDMO =
interface['{748A4D54-FE90-4459-973D-92E175DBAFCF}']
function GetVolume: Single; stdcall;
procedure SetVolume(aVolume: Single); stdcall;
property Volume: Single read GetVolume write SetVolume;
end;
Sound+Vision
A more complex implementation would interpolate the volume
for each sample to avoid the audible clicks caused by sudden
volume changes between consecutive blocks of audio data. This
phenomenon is known as zipper noise.
At this point, were done with our volume effect. We also would
need to override InternalFlush, InternalAllocateStreamingResources,
and InternalFreeStreamingResources, if we were coding effects
involving any kind of buffering (but thats not the case here).
Sound+Vision
Also, note that plug-ins typically implement a callback mechanism to notify the property page whenever
parameters change, so the user interface can refresh itself
automatically. The sample plug-in does not implement
such a mechanism. I leave this as an exercise for you.
Conclusion
This article demonstrates how to create DirectShow
filters in Delphi by wrapping DirectX Media Objects
using a custom COM class factory automatically. The
resulting filters can be used by any sound-processing
application capable of hosting DirectX plug-ins.
Figure 4: Our plug-in at run time.
Thats all there is to it! Just register the resulting DLL through the
Run | Register ActiveX Server menu command on the Delphi IDE
(or use the regsrv32.exe utility), and youre ready to test the plugin with your favorite host. Figure 4 shows our plug-in in action.
Supporting Presets
DirectX plug-in presets are handled through the standard COM
persistence mechanism. All we have to do is implement the
IPersistStream interface in our object, and the host application
will take care of the rest. The only gotcha here is that the CLSID
returned by IPersistStream.GetClassID should be the generated
CLSID of the fake filter.
Resources
DirectX binaries: http://www.microsoft.com/windows/
directx/downloads.
DirectX SDK: http://msdn.microsoft.com/directx.
JEDI DirectX headers: http://www.delphi-jedi.org/
delphigraphics.
Adapt-X, a free DirectX plug-in host for Winamp:
http://perso.worldonline.fr/jobsearch.
Ianier Munoz lives in France and works as a senior consultant and analyst for
Dokumenta, an international consulting firm based in Luxembourg. His specialty is in
multimedia applications, and he has authored some popular software, such as American
DJs Pro Mix, Adapt-X, and Chronotron. Readers may reach him at ianier@hotmail.com.
Pascal Analyzer
Evaluates Your Code for Problems, Fat, etc.
here are a number of memory-leak detection and profiling tools for Delphi on the
market. When it comes to code-analyzing tools, however, theres somewhat of a
dearth. Fortunately for Delphi developers, theres PAL, short for Pascal Analyzer, from
Peganza. PAL provides an automated way to review and inspect your code.
Peganza describes its tool in this way: Pascal
Analyzer ... is a unique development tool that
measures, checks, and documents your Delphi or
Borland Pascal source code. It makes software projects of any size easier to understand and enables
developers to produce more reliable code. PAL
contains numerous optimization, validation, and
PALs Reports
Specifically, what does PAL bring to the table? How
can it help you make better programs and fine-tune
your coding skills? There are 32 reports available in
PAL, separated into five categories: General, Reference, Metrics, Classes, and Controls. You can see
them by selecting Options | Properties | Reports. The
Class Field Access Report is shown in Figure 1, and
the Code Reduction Report in Figure 2. For information on the specifics of these and all other reports,
consult Peganzas documentation.
PALs reports can be generated in either text
or HTML format (this review shows them in
HTML). In the text reports, the same font size
is used throughout and it makes the reports hard
to read. In the HTML reports, this problem is
addressed via the use of various font sizes. This
is the only default setting that I recommend
changing at Options | Properties | Format | Report
Format (see Figure 3).
Additional Details
You can imagine all the ways a code analyzer, such as PAL, can
help you with your Delphi and Turbo Pascal programs. You can
set PAL to parse your Pascal 7 programs in addition to all versions
of Delphi through version 6. To do so, select Options | Properties |
Parsers to open the Properties dialog box and make the appropriate
changes (see Figure 4). You might also want to add some paths to
the Exclude identifiers from these folders in reports edit box to reduce
information overload about potential problems in the third-party
component code used by your project. You can do this by copying
and pasting your Delphi projects search path string found at
Project | Options | Directories/Conditionals | Search Path.
By default, PAL is installed to \Program Files\Peganza\Pascal Analyzer.
Support is available via Peganzas Web site, and by e-mail. Peganza
provides a well-written and comprehensive help file in both .hlp and .pdf
formats, as well as a readme.txt for a quick start. I agree with Peganzas
self-assessment: PAL quickly pays for itself through easier maintenance,
fewer errors, improved code quality, and easier migration of projects
between programmers.
PAL is a standalone executable, but it can be added to your Tools menu.
Instructions are provided in the help file. It can be used as shown in this
review that is, as a conventional GUI app or as a command-line
tool. By using PAL from the command line, you can integrate it into
your production and quality assurance process.
An evaluation version of this valuable tool can be downloaded from
Peganzas Web site. The evaluation version contains all of the functionality of the registered version, but the reports are truncated (only the first
few instances of each potential problem are shown). Although the evaluation version is limited in the length of its reports, youll get the idea of
what the product does. You can also order a full-featured registered version from their site. If you purchase PAL, make sure to always download
the latest patch from http://www.peganza.com/patch. Copy the updated
version of Pal.exe over the existing one.
Conclusion
PAL is a well-thought-out tool that installs smoothly. Its comprehensive,
intuitive, and visually-pleasing to boot. I recommend that all Delphi
programmers interested in improving the quality of their applications
and coding skills use PAL. The benefits are worth the modest investment
of time and money.
NitroSort
By default the input files are opened for exclusive use. Add the Access command to allow
other users to access the files:
InFiles "C:\IMPORT\20020601.DAT",
"C:\IMPORT\20020602.DAT";
FileType Fixed 100;
Access ShareRead;
InFiles "C:\IMPORT\20020601.DAT",
"C:\IMPORT\20020602.DAT";
FileType specifies the input file type. The following example identifies the file type as fixed-length
records with a length of 100 bytes:
InFiles "C:\IMPORT\20020601.DAT",
"C:\IMPORT\20020602.DAT";
FileType Fixed 100
The following example uses the OutFile command to identify the output file:
InFiles "C:\IMPORT\20020601.DAT",
"C:\IMPORT\20020602.DAT";
OutFile "C:\OUTPUT\SORTED.DAT";
FileType Fixed 100;
Access ShareRead;
To change the layout of the records in the output file, use the OutRec
command. Field specifications take the form [Starting Position,
Size]. You can also include string constants, hex numbers, the record
number in the input file, or the record address (offset) in the input
file in the output record. In this example, the output record contains
the 10 bytes starting in column 20 of the input file, the 19 bytes staring in column 1, the letters XXX, the 20 bytes starting in column 40,
and a byte containing the hexadecimal value FF:
Figure 1: The NitroSort standalone utility.
If NitroSort cannot sort the data in memory, it will create a temporary sort work file on the drive that hosts the output file. To place the
work file somewhere else, use the WorkArea command:
InFiles "C:\IMPORT\20020601.DAT", "C:\IMPORT\20020602.DAT";
OutFile "C:\OUTPUT\SORTED.DAT";
Key [10, 8, char, ascend], [1, 4, int, ascend],
[20, 8, IEEEFloat, descend];
FileType Fixed 100;
Access ShareRead;
Header 80 Retain;
MaxMem 100;
WorkArea "D:\TEMP\SORTWORK.TMP";
NitroSort provides two ways to select the records that will be written
to the output file. Use the Range command to specify a starting and
ending record number, or a starting record number and number of
records. For example, Range 1000, 2000 will select records 1000
36 November 2002 Delphi Informant Magazine
through 2000 from the input file. Range 1000, +1200 will sort the
1,200 records starting with record 1000 in the input file.
Use the Qualifier command to select records based on their data
values. Field values in a Qualifier expression have the form [Starting Position, Size, Data Type]. For example:
Qualifier [1,4,int] = 200 and
([7,3,char]='ABC' or
[7,3,char]='abc');
indicates that a record will be output if the four-byte integer starting in position 1 equals 200, and the three-byte Char starting in
position 7 is equal to either ABC or abc. Qualifier expressions
can also include hexadecimal constants. Hex values begin with a
dollar sign. For example, instead of 255 you can use $FF.
Options is the last command in the NitroSort data manipulation language. Use it to add an EOF (end-of-file) character to
the output file, append the sorted records to an existing output
file, use the input file as the work file to save disk space, and have
NitroSort make progress callbacks to your application.
Using NitroSort
To use NitroSort, simply add the NITRODLL.PAS unit to your
project, and to the uses clause in the unit where you want to call
the Sort function. Figure 4 shows the code from the OnClick event
handler of the Sort button in the sample application that accompa-
Conclusion
NitroSort is fast, easy to learn, and easy to use. If you need to sort,
reformat, and select data from flat files, NitroSort may be just the tool
you need. Sort performance can only be described as stunning. Sorting one million 100-byte records took only 33 seconds on my 1 gHz
notebook. The accompanying documentation is excellent, and includes
both a help file and a user manual in Word format. The options are
clearly described and numerous examples show you how to use each of
the options in complete sort commands.
The sample application referenced in this article is available on
the Delphi Informant Magazine Complete Works CD located in
INFORM\2002\NOV\DI200211BT.
File | New
Directions / Commentary
ts been a long time since I wrote about Project JEDI (Joint Endeavor of Delphi Innovators). Too long. I first wrote
about the Project in the December, 1997 Delphi Informant, just 10 days after the Project had begun. That column
reflects my initial excitement an excitement that continues to this day.
When I wrote about the Project next, in June 1999, I emphasized an
emerging partnership between the Project and Borland. This partnership
has matured, expanded, and benefited the entire Delphi/Kylix community. My role in the Project has also changed over the years.
The history. Project JEDI has an interesting, albeit humble, history. It
was a Friday evening toward the end of September, 1997. On a Delphi
Internet discussion group sponsored by the former COBB Group someone posted a complaint about the disparity between new technologies
available to C/C++ developers and those available to Delphi developers.
Why couldnt Borland convert more of these APIs for our use? Early
in the discussion someone suggested that this was an area in which we
could actually help ourselves. Thus, Project JEDI was born.
The Project began as a very loosely structured organization that benefited
from a small, energetic cadre of developers who produced initial results
rather quickly. Word began to spread. An early supporter, Bob Swart,
promoted the Project on his Web site. As time passed, third-party vendors offered invaluable tools and support: HREF, producers of WebHub
(http://www.href.com), donated space on their Web site; Toolsfactory
donated its popular source code documentation tool, Doc-O-Matic
(http://www.doc-o-matic.com) for use by the Projects help file writers;
and a series of newsgroups was provided through the generosity of Rene
Tschagelaar (http://www.talkto.net).
The Projects early days were characterized by ups and downs. During
one early down period it appeared the Project might die. But Tom
Guarino, an active Project member, contacted several of us to form an
Admin Group to help steer the Project uphill. It worked; Project activity
and communication picked up and we forged a successful partnership with Borland. As the Project grew, a Steering Team formed that
included many team leaders, as well as our first Borland representative,
Charlie Calvert. Calvert helped solidify the partnership with Borland,
and Project JEDI was able to contribute to the companion CDs that are
distributed with each new version of Delphi.
But nothing lasts forever. As the Steering Team took charge of more of
the Projects decision making, the Admin Group appeared mysterious
and aloof to some. During one period of conflict, Tom made the difficult
decision to disband the Admin Group. This important move provided
clearer organizational structure, wider representation to JEDI teams, and
greater diversity of opinions and ideas.
Under Toms leadership and with a burst of new energy from the Steering
Team, the Project continued to grow, moving into new territory of open
38 November 2002 Delphi Informant Magazine
File | New
Component Library (JVCL) consists of over 300 components. A team is
currently creating help files for these components, but the many example
programs that accompany them demonstrate their use and make these
popular components very usable. Several new projects have emerged this
year, including the JEDI Version Control System (JVCS) that is aimed
at becoming a replacement for the FreeVCS client, and the JEDI-Math
Project, which we intend to develop as an open source math library for
Delphi and potentially Kylix.
Of course, API conversions remain one of the major activities of the
Project and we continue to update and add those. But these days there
is hardly an area of Delphi programming in which Project JEDI is not
involved, from business applications to games. There is a JEDI Business
Application Framework on one extreme and the JEDI-SDL project on
the other. In the area of multimedia, the JEDI-QuickTime project provides support for playing QuickTime movies. Most JEDI projects now
live on SourceForge. You can get an overview of the ones Ive mentioned
(and many more) by visiting http://projectjedi.sourceforge.net.
The future. Project JEDI is undergoing another structural change
one more evolutionary than revolutionary. Were restructuring the Steering Team to consist of the most active people in the
Project. We are also establishing an Advisory Group of leaders from
the Delphi community who will provide advice and support. We
want the Projects structure to be both effective and transparent to
everyone in the Delphi community.
Alan Moore is a professor at Kentucky State University, where he teaches music theory and
humanities. He was named Distinguished Professor for 2001-2002. He has been named
the Project JEDI Director for 2002-2003. He has developed education-related applications
with the Borland languages for more than 15 years. Hes the author of The Tomes of Delphi:
Win32 Multimedia API (Wordware Publishing, 2000) and co-author (with John Penman)
of an upcoming book in the Tomes series on Communications APIs. He also has published
a number of articles in various technical journals. Using Delphi, he specializes in writing