Pascal Newsletter #39 - 13-SEP-2002
Contents
1. A few words from the editor
2. In the news
- Delphi 7 is here!
- Delphi for .NET compiler preview
- Kylix 3 gets 5 stars from LinuxPlanet
- Upcoming Borland Events
- Delphi Fireworks Component Contest
3. Understanding VisualCLX - What are hook-objects in a Qt application?
4. Creating High Performance Middleware Applications with Indy
5. Inline Assembler in Delphi (III) - Static Arrays
6. Forums / mailing lists
7. Delphi on the Net
- Components, Libraries and Utilities
. Freeware
- Articles, Tips and Tricks
- Tutorials
- Other links
________________________________________________________________________
1. A few words from the editor
First of all, I'd like to apologize for the delay in publishing this
issue, but I've been buried in work these past weeks. I hope #40 gets
published in three weeks.
In this issue, I'd like to thank Max Kleiner for contributing another
article to the newsletter, and I'm glad to award him a license of
AnyShape Transpack v2.0 for Kylix, the cross-platform component, that
eases the creation of transparent, weirdly shaped windows with WYSIWYG
editing, design-time preview, automatic dragging, REAL stay-on-top
forms, and the ability to combine regions, provided by MindBlast
Software: http://www.mindblastsoftware.com/?page=transpack&ref=PascalNL
By the way, the author of the next Kylix article we publish will also
receive a license of AnyShape Transpack v2.0 for Kylix.
I'd also like to thank Romeo Lefter for his article about Indy, and
I'm happy to award him a Delphi Information Library CD (DIL CD), a
great information resource with articles, tips, tricks, components,
javascripts, images, update packs, and much more, provided by the UK
Borland User Group: http://www.richplum.co.uk/dil/index.asp
For the next issue, we have available the following prizes for our
contributors:
* llPDFLib v1.1 - by llionsoft, Shareware ($70, $280 with source)
llPDFLib is pure Object Pascal library for creating PDF documents.
Does not use any DLL and external third-party software to generate PDF
files. Library consists of TPDFDocument component with properties and
methods like Delphi's TPrinter but designed to generate a PDF file.
http://www.llion.net/
* Greatis Form Designer v3.4 - by Greatis Software, Shareware ($49.95)
It's a runtime form designer that allows you to move and resize any
control on your form. You don't need to prepare your form to use
Form Designer. Just drop TFormDesigner component onto any form, set
Active property to True and enjoy! For Delphi 4-7 and BCB 3-6.
http://www.greatis.com/formdes.htm
* Developer Information Library (DIL) CD - by UK Borland User Group
Over 17,000 Tips, Tricks, FAQs and Technical Articles ˇ Patches and
Updates for Borland Tools ˇ Over 4000 Components & Tools ˇ Over 4000
Bitmaps ready to use with another 20000 zipped ˇ Over 350 ready to use
JavaScripts ˇ Complete Set of Linux How-tos ˇ and much much more...
http://www.richplum.co.uk/dil/index.asp
Ernesto De Spirito
eds2008 @ latiumsoftware.com
__________________
Collaborated in this issue: Dave Murray
________________________________________________________________________
JfControls Library. Multi-language. Multi-appearance. Skins. Privileges.
More than 40 integrated and customizable components. Impressive GUI.
Centralized resources administration. Multiple programming problems
solved. For Delphi 3-2006 & C++ Builder 3-6. http://www.jfactivesoft.com
________________________________________________________________________
2. In the news
Delphi 7 is here!
=================
Delphi 7 is among us, called Delphi 7 Studio, and it comes in four
editions:
* Delphi 7 Studio Architect ($3,499 - Upgrade from Enterprise: $2,399)
http://www.borland.com/delphi/architect/index.html
* Delphi 7 Studio Enterprise ($2,999 - Upgrade: $1,899)
http://www.borland.com/delphi/delphi_enterprise/index.html
* Delphi 7 Studio Professional ($999 - Upgrade: $399)
http://www.borland.com/delphi/delphi_professional/index.html
* Delphi 7 Studio Personal ($99 - available for free download)
http://www.borland.com/delphi/delphi_personal/index.html
The new Architect edition is very much like the Enterprise edition, but
it comes with additional tools, including the new Bold for Delphi from
BoldSoft, which allows developers to maintain less code with true MDA,
plus it comes with UML technology, integrated support for Rational Rose,
ModelMaker, import/export model information from/to Bold Model Editor,
and automatic database schema generation using SQL. DataSnap (formerly
known as MIDAS) is royalty free in both the Enterprise and the Architect
edition, and is also included in the Professional Edition.
Except for the Personal edition, all Delphi 7 Studio editions include
Kylix 3 for Delphi environment (allowing developers to use one code
base to leverage the power of cross-platform development for Linux)
and the Delphi 7 Studio Migration Kit (to migrate applications to
Microsoft .NET).
Delphi 7 links:
* Main page
http://www.borland.com/delphi/architect/index.html
* System requirements
http://www.borland.com/delphi/pdf/del7_sysreqs.pdf
* FAQ
http://www.borland.com/delphi/pdf/del7_faq.pdf
* Feature Matrix
http://www.borland.com/delphi/pdf/del7_feamatrix.pdf
* Delphi 7/.NET User Group Tour 2002 - US / Canada
Borland is taking Delphi 7 and the Delphi Preview for Microsoft .Net
on the road in the US and Canada.
http://bdn.borland.com/article/0,1410,29089,00.html
Delphi for .NET compiler preview
================================
Included with Delphi 7, you can find a preview of the Delphi for .NET
compiler, a command-line utility named "dccil.exe", which produces
Common Intermediate Language (CIL) applications that can run anywhere
the .NET run-time is available as fully managed applications. This
means that Delphi applications can now move beyond their traditional
Windows/Intel platform to any other platform that has a .NET runtime,
such as the .NET compact framework available for tablet PCs, phones,
and PDAs.
* Delphi for .NET compiler preview - By John Kaster
A first look at the Delphi for .NET compiler features and Delphi's
new language syntax
http://bdn.borland.com/article/0,1410,28972,00.html
* Delphi for .NET Preview: Samples
This web site provides sample applications for the Delphi for .NET
preview compiler. These sample applications are produced by members
of the Borland community, and Borland staff.
http://dotnet.borland.com
* Using Delphi as a script language for ASP.NET - by John Kaster
A preview of Delphi for .NET support inside ASP.NET
http://bdn.borland.com/article/0,1410,28974,00.html
Kylix 3 gets 5 stars from LinuxPlanet
=====================================
* Kylix 3: Borland's Linux Delphi and C++ RAD is a Winner - By Steven J.
Vaughan-Nichols
Now, however, Kylix answers the needs of most Linux programmers by
fully supporting C++ with the same development environment. The result
is a RAD that should quickly become Linux's most popular integrated
development environment (IDE).
http://www.linuxplanet.com/linuxplanet/reviews/4427/1/
* Taking Kylix 3 for a test drive - By Joe Barr
In short, Kylix 3 has allowed me to develop this simple C++ GUI app
for X in just a few days. Given how little C++ and X development
experience I have, and the fact that I've never worked with pipes
except from the command line, that's pretty good time. Kylix has
demonstrated to me it deserves its RAD label.
http://linux.sys-con.com/read/32782.htm
Upcoming Borland Events
=======================
* Entwickler Konferenz (EKON6), Morfeldfen/Frankfurt Germany, September
22-27, 2002
Deutsch - http://www.entwicklerkonferenz.de/
English - http://www.entwicklerkonferenz.com/
* BorCon Europe, London UK, October 28-29, 2002
http://www.borconeurope2002.com/
* BorCon Japan, Tokyo Japan, November 19-20, 2002
http://www.borland.com/jp/
* BorCon France, Paris France, November 21-22, 2002
http://info.borland.fr/conference/2002/
Delphi Fireworks Component Contest
==================================
The webmaster of http://chuckr.freeshell.org/index.php has started a
Fireworks Component Contest. The prize? Awe and recognition from your
peers, just for entering. Also it makes a great resume entry.
Here are the rules:
- You must create a Delphi component which shows fireworks.
- The component must be a visual component, installable on the palette,
and contained in one .PAS file.
- You must submit all source and the EXE file to the contest.
- The component must use only standard Delphi objects. No DirectX.
OpenGL will be allowed since quite a few graphics cards and Windows
versions support it. You may use graphics accelleration libraries.
- Submissions must be received by Oct 5, 2002. Judging will then begin.
- Submissions will be judged on elegance of implementation, appearance,
features (see next), and speed.
- Some suggested, but optional features: user can change number of
explosions on screen at the same time, user can change color of
fireworks, user can select different explosion shapes, different
explosion types (some real fireworks have a second stage explosion),
etc.
- Sound is optional.
Entries should be submitted to <chuckr69 @ fastmail.fm>.
________________________________________________________________________
IBAdmin 3.2 - Complete Interbase SQL tool - A powerful DBA/Development
tool for managing Interbase servers and databases. IBAdmin provides many
capabilities to help with your DB design and management. You can use the
Database Designer to visually design the database structure, the Grant
Manager to manage users, or the SQL Debugger which can be used to debug
stored procedures and triggers. Comfortable SQL code editing with Code-
Insight and Code Completion. >>>>>>>>> http://www.sqlly.com/
________________________________________________________________________
3. Understanding VisualCLX - What are hook-objects in a Qt application?
By Max Kleiner <max @ kleiner.com>
Kleiner Kommunikation http://max.kleiner.com/
VisualCLX is the part of CLX that represents the Visual Components that
would normally reside in the TWinControl hierarchy in the VCL.
VisualCLX framework is a set of classes that represent Visual Controls
but have to work (if possible) on both MS Windows and X in Linux.
The controls represented by the VisualCLX components are implemented by
a C++ class library called Qt and widgets, from the Norwegian
development company called Trolltech. Qt is also available on Windows.
- The VCL TWinControl class is called TWidgetControl
Qt is a C++ class library, cause of differences in C++ and OP (Object
Pascal) details, an OP program cannot directly manipulate Qt widgets.
Instead, VisualCLX makes use of an additional library, called the Qt
interface library (written in C++ as libqtintf.so) which exports all the
Qt functionality in a manner that is accessible to OP code.
The import unit for this interface library is called Qt.pas but this
means that rather than being declared as classes, the Qt widget methods
are all imported as flat methods or strictly speaking functions.
We define a flat method as a method of a class that is declared as a
standalone subroutine or function.
However, since at the C++ side they are indeed classes, almost every
flat method takes one extra parameter, which is the reference to the Qt
widget. You think this might slow applications but most of the time you
won't measure any difference in run-time behavior.
So what's the difference in a architectural manner? In a known OP
application, you call methods via object references, e.g.:
myButton.setBounds(15, 15, 65, 35);
Turning the method into a flat method, the object reference is passed as
the first parameter so the method code knows which instance it should be
invoking. Here is a "it goes almost like this" example flat method,
which is equivalent to the method just used:
QButton_SetBounds(myButton, 15, 15, 65, 35);
or in a Kylix Qt-manipulation:
uses Qt, QTypes;
var Btn: QButtonH;
Btn := QButton_create(Handle, PChar('Btn'));
QButton_setGeometry(Btn, 15, 15, 65, 35);
Of course you would normally have no need to write code like this as a
QButton does it all for you, but it serves as a simplified example of
how CLX components do their thing by using the CLXDisplayAPI.
What's the CLXDisplayAPI
------------------------
The CLXDisplay API is the official name for the Qt.pas unit that ships
with Kylix and also with Delphi6 or later. It acts as an import unit for
the Qt widget library used by VisualCLX.
So things in life are a bit more complicated than this. Qt is a C++
class library, and OP cannot direct manipulate C++ classes. Because of
this, Borland wrote an additional library to lay between a CLX
application and the Qt library. This extra library is called
libqtintf.so (the Qt interface library), and Qt.pas is actually the
import unit for this interface library.
TWidgetControl--->Qt.pas->libintf.so--->Qt_Widget_Classes
Understanding Signal/Slot mechanism
-----------------------------------
A hook object is a simple C++ object that exists in the Qt interface
library as an intermediary. So you want to customize the reaction of a
widget like in windows with event handlers, signal/slot play this role:
- A signal (event) from a widget
- A slot (event handler) responds to a signal
So we've learnt, it's not possible to have the slot written directly in
OP, means the Qt interface library defines a hook class for each widget
class. The hook class implements a simple slot for each available widget
signal, whose sole job is to call some code in our Kylix application.
More on signal / slot and the Way Kylix does events
---------------------------------------------------
So it seems that messages (callback functions) are not the CLX way of
doing things, it doesn't mean that CLX provides no support of messages,
but it's not the Kylix way of doing things. We suggest, e.g. mouse
movements, that you let CLX respond to the mouse and simply override the
methods that CLX uses for those events.
Creating a component and need to catch the mouse messages, you can use
the following method:
procedure MouseMove(shift: TShiftState; X, Y: integer); override;
The way we have to think is that in Qt, developers do not respond
directly to messages. Instead they work with a signal / slot mechanism
and the connect function like:
QObject::connect(timer, SIGNAL(timeout)), SLOT(timerSlot()));
timer -> start(1000);
or another example to get accustomed to:
QObject::connect(myslider, SIGNAL(sliderMoved(in)),
mylcdNumber, SLOT(display(in)));
There is nothing special about the SliderMoved and Display methods. Just
ordinary C++ methods that are marked as signals and slots, just as some
Kylix methods are marked as being virtual.
QObject is the base class in Qt, just as TObject is the base class in OP
(Object Pascal). QObject has a class or static method named connect. An
OP class method is the same thing as a C++ or Java static method. In
particular, you can call a class or static method without first creating
an instance of the object to which it belongs.
And where's the event-loop in Kylix? Here is the event loop that lies at
the center of CLX applications:
procedure TApplication.HandleMessage;
Hooks again and Overview
------------------------
Fact: So you learned that Qt uses a signal and slot mechanism, and CLX
uses an event mechanism. It's not so important how the two are
connected, it might be valuable some time later, but here is an
overview: Qt has a signal and slot mechanism. CLX has an event
mechanism.
To translate Qt signals and slots into CLX events, the Kylix team
created a mechanism known as hooks. Each CLX object type has a hook
object. This hook object converts the signals and slot events associated
with a particular object into CLX events. It then sends these events to
the appropriate CLX control.
In particular, there is a CLX method of TWidgetControl named EventFilter
that receives the majority of these events. You can find more on this
topic on the Kylix2 CompanionTool CD: sams_publishing/kdgch07.pdf
chapter 7 "CLX architecture & Visual Development" or Borland Code
Central Entry ID #1679. Here an impressive extract:
If you feel the urge to go beyond the usual CLX API, then here is one of
the methods that you want to override:
function TWidgetControl.EventFilter(Sender: QObjectH; Event: QEventH):
Boolean;
This one is the big Kahuna. EventFilter gets most of the events that Qt
and the OS throws at it. Just opening up QControls and looking at the
500+ lines that form the implementation of this method is enough to send
any sane programmer running for the safety of the standard CLX APIs.
However, some people like to live on the edge. They claim that the air
is thinner but cleaner out there.
function TWidgetControl.MainEventFilter(Sender: QObjectH;
Event: QEventH): Boolean; cdecl;
var
Form: TCustmForm;
begin
try
if csDesigning in ComponentState then begin
Form := GetParentForm(Self);
if (Form <> nil) and (Form.DesignerHook <> nil) and
Form.DesignerHook.IsDesignEvent(Self, Sender, Event) then
begin
Result := True;
Exit;
end;
end;
Result := EventFilter(Sender, Event);
except
Application.HandleException(Self);
Result := False;
end;
end;
__________________
Reference: http://www.delphi3000.com/article.asp?ID=3311
________________________________________________________________________
Support us! Vote for the Pascal Newsletter in The Programming Top 100!
http://top100borland.com/in.php?who=20
________________________________________________________________________
4. Creating High Performance Middleware Applications with Indy
By Romeo Lefter <rombest @ hotmail.com>
Rombest Software http://www.vreau.com
Middleware is one of the coolest technologies that are now on the
market. Unfortunately, ready to use tools for this technology costs
much. This technology is associated with databases because it is
intensely used in this field, but it is not limited with databases.
Using this technology, you can create a plethora of applications that
use "thin" clients.
Typically, a middleware framework looks like below:
+-------+ +----------+ +--------+
|Clients| <<-Connection1->> |Middleware| <<-Connection2->> |Database|
| | | server | | server |
+-------+ +----------+ +--------+
In the image, the [Clients] represents your thin clients, the
[Middleware server] is your application server and [Database Server] is
the database. Conforming to this model, clients, the middleware server
and the database server runs on different machines(the database server
and middleware server can run on the same machine). Connection1 and
Connection2 are the connections between our parts.
The middleware architecture is the best way to make serious economies.
In example, the MS SQL Server need suplimentary license for each client.
Also, it needs something named "Client Access License" (I think). All of
this costs money. With a single client license (+ Client Access License)
you can build a middleware server and then work with many clients,
without paying additional licenses. And this solution works fine!
Related to middleware I want to say here that I don't like Midas, COM,
DCOM, COM+ etc. There are many middleware solutions on the market. A
little part of them represents cool solutions, but expensive. There are
solutions that are easy to use but, unfortunately, slower.
The problem that I will discuss here is about how to create a free
middleware application. This is possible and, believe me, superior in
performance than other competitors. First, let's review the tools we
need for this job.
1. Indy http://www.indyproject.org
You need Indy. Because it is simple to use and very fast. There are
other commercial packages on the market that are faster than Indy,
but working with them is not so easy. For me, Indy is one of the best
network packages on the market.
2. KbmMemTable: http://www.onelist.com/community/memtable
This is the best Memory Table that is now on the market. It is thread
safe, it's content (records and structure) can be save on to disk or
stream, supports transactions, compressed blobs and much more. Best
of all, it is free with source code.
=> A short description of TKbmMemTableFeatures
As I have said, the kbmMemTable threading model is one of the best.
You have to set up just few properties and your table can safely work
in a multithreading environment. First property is AttachedMaxCount.
It is an integer property and it stores the maximum number of
memtables that can be attached to this table. Attaching process is
cool. When you attach a memory table (let's name it A) to another
table (B) all the data contained in B table are available for the A
table. More than simply view, the A table can add or update records
and the results are reflected in the B table. In a multi threaded
environment, this is the best model. Another characteristic of
KbmMemTable is it's possibility to save it's data to streams or
files. This is very good for what we want to do. In the last version,
TKbmMemTable has two helper components: kbmBinaryStreamFormat and
TkbmCsvStreamFormat that help us to establish a common "stream
language" for the server and for the client. As you will see,
SavetoStreamviaFormat and LoadFromStreamviaFormat are the most used
methods in our environment.
It's time now to discuss the protocol. First, for security reasons, you
need a authentication part. So, we have to implements 2 commands: Login
and Logoff. The login command is sent to the server with 2 parameters:
the user name and the password, like below:
login user pass
If the pair (user pass) corresponds to the data that are stored on the
server, the user is able to work, else it is disconnected. When the user
wants to terminate it's session, it sends to the server the Logoff
command, without any parameter. In this moment, the server will
disconnect the client.
In order to make this example simple and portable, I will work here with
paradox tables, that will emulate our database server. Also, for easy
portability, I will use queries. In this application I will use the
country.db table, that is in your DBDEMOS alias.
The clients that will connect to our middleware server will be able to:
- add records to this table
- get entire table
For adding records to table, we will implement an command (Add) with
five parameters: Name, Capital, Continent, Area, Population. So, the
command will look like bellow:
Add p1 p2 p3 p4 p5
For getting the table we need just a command without parameters (Get).
It's work time, so let's start. Open a new project, put a Memory table
and a TIdTcpServer on it. The memory table will be used for the login
process, so you have to create 2 string fields for it:user and password.
You have to implement some procedures for adding, deleting and updating
users. Also, on the FormCreate and FormClose events you have to
load/save persistent data for this table(Using LoadFromBinaryFile/
LoadFromCsvFile and SaveToBinaryFile/SaveToCsvFile methods). I have
decided to use a memory table for handling user authentication because
it is the best in speed and because it's thread-safe mechanism works
perfectly. I have decided to have the following architecture:
On the MainForm:
usrs: A KbmMemTable used for authentication (users table)
Server: A TIdTcpServer component, our server
MThread: A TIdThreadMgrPool component (I'll use for this example a
pool threaded with 100 pool size)
For easy understand, I'll use CommandHandlers Enabled in this
projects, so we have to define 4 commands:
-Login
-Logoff
-Get
-Add
Because our pool size is 100, the AttachedMaxCount property of the
AuthTable has to be 100. Also, for easy understanding we have to put all
"database interface" components in a DataModule. So, create a datamodule
and put some components on it, like below:
Query1: A TQuery component that will interface with the
database, in our case database is DBDEMOS
Session1: A TSession component used for safe transactions
logintable: A memTable that will be attached to AuthTable in order
to verify if the pair (user,password) is correct
buffertable: another memTable used for data exchange
Turn the AutoCreateForm to off for datamodule (in Project|Option).
Now we will look in depth on the server model. As I have said, the user
has to login on the server. When the user send the LOGIN command the
server will do the following steps:
1. Creates the datamodule;
2. Attach the logintable (from the datasource) to AuthTable (that is
on the MainForm);
3. Verify if the pair (user,password) is valid;
4. Sends back to the user the authentication Result:
- If the number of parameters is lower than 2 (i.e. the command
looks like login myName), the server sends ('101 - Wrong number
of params! Good bye!') and disconnects the user;
- If the pair (user, password) is valid, the server sends a message
like ('201 - Ok, you are now in the system, man!') and the client
will remain connected;
- If the pair (user, password) is not valid, the server sends a
message like ('102 - Sorry, invalid user or password. Good bye!')
and disconnect the user.
A little code will be more explicit if you haven't understand what I
have said. So, look below:
procedure TForm1.serverCommandHandlers0Command(ASender: TIdCommand);
var
ClientDataModule:TDatas;
loginFlag:boolean;
begin
// Login command
// Format login <<user>> <<password>>
if ASender.Params.Count<2 then
begin
ASender.Thread.Connection.WriteLn(
'101 - Wrong number of params! Good bye!');
ASender.Thread.Connection.Disconnect;
end;
// Create the dataModule.. Its owner is the actual Connection!
ClientDataModule:=TDatas.Create(ASender.Thread.Connection);
// Assign for the session component an unique name
ClientDataModule.Session1.SessionName := 'ClientSession' +
Inttostr(ASender.Thread.ThreadID);
ClientDataModule.logintable.AttachedTo := usrs;
ClientDataModule.logintable.Active := True;
ClientDataModule.Query1.SessionName :=
ClientDataModule.Session1.SessionName;
// Ok, now we will verify if the (user,password) is valid
if not ClientDataModule.logintable.Locate('User',
ASender.Params[0],[]) then
loginflag:=false
else
if ClientDataModule.logintable.FieldByName('Password').AsString
= Asender.Params[1] then
loginFlag:=true
else
loginFlag:=false;
if loginFlag then
Asender.Thread.Connection.WriteLn(
'201 - Ok, you are now in the system, man!')
else
begin
Asender.Thread.Connection.WriteLn(
'102 - Sorry, invalid user or password. Good bye!');
ASender.Thread.Connection.Disconnect;
end;
end;
At first view, it is little "strange" for you the mode we have created
the DataModule (in my project it's name is Datas). As you have observed,
I have created it using a local variable. The problem is "how we will
access it in other procedures". And here is my little innovation. Using
a global variable is really hard because we don't know how many
connections we have in a moment. Don't forget that the owner of the
DataModule is the Connection. For each active connection we have a
DataModule created. Of course, it is created only if the user is logged
on. If the user is not logged on, the DataModule does not exist. For
easy understanding look at the below scenario:
The client connects to the server, using the connect method of
TIdTcpClient. In this moment, the client can send any command to the
server. We need to know that it is logged on when it sends to the server
a command like Get or Add. Using the model I have described, the user
verification is really easy, because if for a client connection a
DataModule exists, that means that the client is logged on, if not, the
client is not logged on.
It's time now to implement a "finder" function. This function is useful
to find if a datamodule exists for a connection. If the DataModule
exists, the function will return a reference to the DataModule. Else, it
will return nil.
function TForm1.FindModule(connection:TIdTCPServerConnection):TDatas;
var
i: integer;
begin
Result := nil;
for i := 0 to Connection.ComponentCount-1 do
if Connection.Components[i] is TDatas then
Result := (Connection.Components[i] as TDatas);
end;
As I have said, we are using a "pool thread model" for our server. That
means that the thread is not destroyed when the user disconnects from
the server. So, we have to manually destroy the DataModule, each time
when a user is disconnected from our server:
procedure TForm1.serverDisconnect(AThread: TIdPeerThread);
var
AData:TDatas;
begin
AData := FindModule(AThread.Connection);
if AData <> nil then
AData.Free;
end;
That means that for Logoff command we have to do something like below:
procedure TForm1.serverCommandHandlers1Command(ASender: TIdCommand);
begin
ASender.Thread.Connection.Disconnect;
end;
We are now in the moment of the real implementation. We have to exchange
data between our client and server, so we will implement first the Get
command. In order to make this example easy to understand this command
will not have any parameters. But, you can add parameters that can be
used for filtering or for any other action. Bellow, you have the command
implementation:
procedure TmainFrm.serverTIdCommandHandler2Command(ASender: TIdCommand);
var
AData:TDatas;
AStream:TStream;
begin
AData:=FindModule(ASender.Thread.Connection);
if Adata=nil then
begin
ASender.Thread.Connection.WriteLn(
'103 - You are not logged in! Good bye!');
Asender.Thread.Connection.Disconnect;
end;
// Create the stream
AStream:=TMemoryStream.Create;
// Start the interrogation
AData.Query1.sql.Clear;
AData.Query1.sql.Add('select * from country');
AData.Query1.Active:=true;
// Load the Query's data to buffertable
Adata.buffertable.LoadFromDataSet(Adata.Query1,[mtcpostructure]);
// Save BufferTable to Astream
AData.buffertable.SaveToStreamViaFormat(Astream,
adata.kbmBinaryStreamFormat1);
// Move Stream to first position
Astream.Seek(0, soFromBeginning);
ASender.Thread.Connection.WriteLn(
'202 - Ok! The stream is comming!');
// Send the Stream to client Application
ASender.Thread.Connection.WriteStream(AStream,true,true);
// Free the stream
AStream.Free;
end;
For this command, the client will receive a stream containing all table
data. This stream can be loaded into a TKbmMemTable and the entire table
on the server will be visible on the client. Without BDE or any other
third party "connectivity".
Because the Add command is the same in implementation (you have to read
the params and create a query that inserts params into the table) I will
not elaborate further on this aspect. Also, because the client
implementation is really easy I will not describe it.
This is the entire "technology". It is simple to implement, superior in
performance and it costs nothing. There are, of course many other
aspects you have to think about. For example you can use compressed
streams in order to reduce the traffic between server and clients.
There are some things you have to know before you start in your next
"big middleware server" creation. Before you start, you have to build
your protocol and this, in my opinion, is the most important part of the
project. A good protocol will help you in the development process. Let's
see the above code fragment. First, you have to see that before each
string that is sent to the client is a number. In the example protocol I
have used a numeric protocol combined to a string protocol. Before a
text that is send to the client, I have a numeric code: 1XX represents
the error actions and 2XX represents the success actions. This will help
you in developing client applications. You can create, on the client
side, a helper function that extracts this numeric code and, for each
string that is received by your client you will know if an error has
occurred or "all is OK". Another interesting part is the
synchronization. When a server sends a stream, you have to read a stream
on the client side. The same with strings. If you wait for a string and
a stream is sent, your client application will be blocked. This is why I
have inserted the message '202 - Ok! The stream is comming!'. At first
view, it is unnecessary, but just look at the beginning of the
procedure. If the client is not logged, the server sends the '103 - You
are not logged in! Good bye!' message. When our client sends the get
command to the server it first reads a string because it has to know if
the server returns an error.
Another interesting part is about how streams are sent. The WriteStream
procedure has 3 parameters. First is the stream that will be sent. The
second parameter is a boolean. If is true, the stream will be sent from
the start, else the stream will be sent from the current position. The
third parameter is also a boolean. If is true, the size of the stream
will be sent to the client, if it is false, this value will not be sent.
If this last parameter is true, the size is sent as a integer value,
before the stream. So the below fragments of code are the same:
1. => WriteStream with last parameter false
....
i := MyStream.Size;
ASender.Thread.Connection.WriteInteger(i);
ASender.Thread.connection.WriteStream(MyStream, true, false);
....
is the same with
2. => WriteStream with last parameter true
....
ASender.Thread.Connection.WriteStream(MyStream, true, true);
....
A demo project is attached to this article. It contains a full client
and a server implementation. Enjoy it!
__________________
Reference: http://www.delphi3000.com/member.asp?ID=806
________________________________________________________________________
5. Inline Assembler in Delphi (III) - Static Arrays
By Ernesto De Spirito <eds2008 @ latiumsoftware.com>
Passing static arrays as parameters
===================================
Static arrays parameters are passed as pointers to the first element of
the array, independently of whether the parameter is passed by value or
by reference (either as "var" or as "const").
Given the following declarations...
const
ARRAY_MAX = 5;
type
TArrayOfInt = packed array [0..ARRAY_MAX] of longint;
var
a, b: TArrayOfInt;
procedure InitializeArray(var a: TArrayOfInt);
var
i: integer;
begin
for i := 0 to ARRAY_MAX do
a[i] := i;
end;
...the call to the procedure InitializeArray in assembler would be like
this:
// In Object Pascal:
// InitializeArray(a);
// In Inline Assembler:
asm
mov eax, offset a // EAX := @a;
call InitializeArray // InitializeArray;
end;
OFFSET is an assembler unitary operator that returns the address of a
symbol. OFFSET is not applicable to local symbols. You should use the
LEA opcode (see below), which is more "universal".
Static arrays passed by value
-----------------------------
If the array is passed by value, it is responsibility of the called
function to preserve the array. When a function needs to change the
values of one or more elements of an array passed by value, normally
it creates a local copy and works on the copy. The compiler creates a
copy for us in the "begin" of Pascal procedures and functions, but in
full assembler procedures and functions we have to do it by ourselves.
One way of doing it is like this:
procedure OperateOnArrayPassedByValue(a: TArrayOfInt);
var
_a: TArrayOfInt;
asm
// Copy the elements of "a" (parameter) in "_a" (local copy)
push esi // Saves ESI on the stack
push edi // Saves EDI on the stack
mov esi, eax // ESI := EAX; // @a
lea edi, _a // EDI := @_a;
mov eax, edi // EAX := EDI; // @_a
mov ecx, type TArrayOfInt // ECX := sizeof(TArrayOfInt);
rep movsb // Move(ESI^, EDI^, ECX);
pop edi // Restores EDI from the stack
pop esi // Restores ESI from the stack
// Here goes the rest of the function. We'll work on "_a" (the
// local copy), whose first element is now pointed by EAX.
end;
The new things here are the LEA and MOVSB opcodes, the REP prefix, and
the TYPE operator, described below:
LEA (Load Effective Address)
-----------------------------
Moves to the first operand the address of the second. Here we compare
LEA with MOV:
Instruction Translated as Effect
-------------------------------------------------------------------
lea eax, localvar lea eax, [ebp-$04] EAX := @localvar;
EAX := EBP - $04;
mov eax, localvar mov eax, [ebp-$04] EAX := localvar;
EAX := (EBP - $04)^;
MOVSB (MOVe String Byte)
------------------------
Copies the byte pointed by ESI to the location pointed by EDI, and
increments ESI and EDI so they point to the next byte. The work of
MOVSB can be described as follows:
ESI^ := EDI^; // Assume ESI and EDI are of type PChar
Inc(ESI);
Inc(EDI);
Notes:
* MOVSW and MOVSD are the Word (16-bit) and DWord (32-bit) versions
respectively (ESI and EDI are incremented by 2 and 4 respectively).
* The registers are decremented if the Direction Flag is set.
REP
---
The REP prefix is used in string operations to repeat the operation
decrementing ECX until ECX is zero. The work of REP could be described
as follows:
// rep string_instruction
@@rep:
string_instruction
loop @@rep
Notes:
* REP is not a shorthand for a code like the above. It works a lot
faster.
* The value of ECX is not checked at the beginning of the loop (if ECX
is zero, the instruction would be repeated 2^32 times, but will
generate an AV long before that, as soon as ESI or EDI point to an
invalid memory location).
TYPE
----
The TYPE operator is a unary operator evaluated at compile time, and it
returns the size in bytes of the operand, which must be a data type. For
example, TYPE WORD will return 2 and TYPE INTEGER will return 4.
Accessing the elements of an array
==================================
To access an element a[i] we need the values "@a[0]" and "i" in
registers (like EDX and ECX, for example), and then we can use
memory addressing as follows:
lea edx, a // EDX := @a;
mov ecx, i // ECX := i;
mov ax, [edx+ecx*type integer] // AX := EDX[ECX]; // a[i];
// PWord(EDX + ECX * SizeOf(integer))^
In the example, we assumed that the elements have 2 bytes (we moved the
value of a[i] to AX, a 16-bit register), that the array is not a packed
one (each element actually occupies 4 bytes, the size of an integer, so
this value was used to compute the position of the element), and that
the array is zero-based. For example:
var a: array [0..N] of word = (1, 2, 3, 6, ...);
+------ EDX = @a
|
v
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--
| 1 | 0 | | | 2 | 0 | | | 3 | 0 | | | 6 | 0 | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--
a[0] a[1] a[2] a[3]
[edx] [edx+04] [edx+08] [edx+12]
If the array is not zero-based, we have to adjust the value of the
index to make it zero-based before addressing the element. Examples:
// a[1..100]
:
mov ecx, i // ECX := i;
dec ecx // Dec(ECX); // Adjust ECX
:
// a[-10..10]
:
mov ecx, i // ECX := i;
add ecx, 10 // Inc(ECX, 10); // Adjust ECX
:
The procedure InitializeArray (introduced above) can be implemented in
assembler like this:
procedure InitializeArray(var a: TArrayOfInt);
asm // EAX = PByte(@a[0]);
xor ecx, ecx // ECX := 0;
@@loop:
mov [eax+ecx*type integer], ecx // PInteger(EAX+ECX*4)^ := ECX;
// ...or EAX[ECX] := ECX;
inc ecx // ECX := ECX + 1;
cmp ecx, ARRAY_MAX // if ECX <= ARRAY_MAX then
jle @@loop // goto @@loop;
end;
Or like this:
procedure InitializeArray(var a: TArrayOfInt);
asm // EAX = @a[0];
xor ecx, ecx // ECX := 0;
@@loop:
mov [eax], ecx // EAX^ := ECX;
inc ecx // Inc(ECX);
add eax, type integer // Inc(EAX); // Point to the next element
cmp ecx, ARRAY_MAX // if ECX <= ARRAY_MAX then
jle @@loop // goto @@loop;
end;
Returning array values
======================
Functions returning arrays receive an additional last parameter which
is the pointer to the memory location where they should place their
return value (memory is allocated and freed if necessary by the caller).
For example, let's consider the following function:
function ReverseArray(const a: TArrayOfInt): TArrayOfInt;
var
i: integer;
begin
for i := 0 to ARRAY_MAX do
Result[i] := a[ARRAY_MAX-i];
end;
The function receives two parameters:
1) EAX = the address of the first element of the array "a"
2) EDX = the address of the first element of Result
The function can be rewritten in assembler as follows:
function ReverseArray(const a: TArrayOfInt): TArrayOfInt;
asm // EAX = @a[0]; EDX = @Result[0];
push ebx // Save EBX
mov ebx, eax // EBX := EAX;
xor ecx, ecx // ECX := 0;
@@loop:
mov eax, ARRAY_MAX
sub eax, ecx // EAX := ARRAY_MAX-ECX;
mov eax, [ebx+eax*type integer] // EAX := EBX[EAX];
mov [edx+ecx*type integer], eax // EDX[ECX] := EAX;
inc ecx // ECX := ECX + 1;
cmp ecx, ARRAY_MAX // if ECX <= ARRAY_MAX then
jle @@loop // goto @@loop;
pop ebx // Restore EBX
end;
Well, this is it for now. In the next issue we'll see how to work with
records.
________________________________________________________________________
6. Forums / mailing lists
To join any of our forums, the best way is to subscribe from the web,
since that way you'll be able to access the features available at the
web site (like changing your subscription options, viewing the past
messages, accessing the files section, etc.). A Yahoo! ID is required
for that, and you can get yours free by registering as a Yahoo! user,
but if you don't want to register or if you don't have full Internet
access, you can also subscribe by email (you'll only have email access).
* Delphi: If you know a lot about Delphi but you are still far from
being a guru this forum is for you. This is the only forum for
intermediate-level Delphi programmers on the Web (Delphi experts are
also welcome :-)
http://groups.yahoo.com/group/delphi-en/
Subscription:
http://groups.yahoo.com/group/delphi-en/join
delphi-en-subscribe@yahoogroups.com
* Kylix: Kylix programming.
http://groups.yahoo.com/group/KylixGroup/
Subscription:
http://groups.yahoo.com/group/KylixGroup/join
KylixGroup-subscribe@yahoogroups.com
* Components: This is a forum for searching/recommending software
components (VCL and CLX components, ActiveX objects, DLL libraries,
shared objects, etc.), as well as utilities, tutorials, information,
etc.
http://tech.groups.yahoo.com/group/components/
Subscription:
http://tech.groups.yahoo.com/group/components/join
components-subscribe@yahoogroups.com
* Software Developers: This is a forum for discussions about software
development and to share experience in the work, professional or
commercial environments. It is not a programming forum, matters
treated here are supposed to be more general or language independent.
http://groups.yahoo.com/group/software-developers/
Subscription:
http://groups.yahoo.com/group/software-developers/join
software-developers-subscribe@yahoogroups.com
________________________________________________________________________
7. Delphi on the Net
By Dave Murray <irongut @ vodafone.net>
Components, Libraries and Utilities
===================================
Freeware
--------
* Kylix 3 Open Edition available for download
It's a whopping 300+ MB download, but worth every nibble!
http://community.borland.com/article/0,1410,29010,00.html
* Explorer Drop v1.1, FREEWARE with source - by Simon Grossenbacher
TExplorerDrop component enables Drag&Drop with the Windows Explorer
for all controls inherited from TWinControl.
http://www.torry.net/vcl/system/draganddrop/swissexplorerdrop.zip
* KACDO Proffesional v1.0, FREEWARE - by Kiril Antonov
Delphi implementation of Microsoft's CDO for Win2k -a set of functions
for composing and sending mail. Works only on Win2k/XP machines. Set
of 3 powerful components: Message - Message, SMTP, NNTP, Encoding +
Decoding Component; Manager - manages IIS SMTP Folders; TreeView -
displays + modifies structure of complex messages.
http://www.torry.net/vcl/internet/email/kacdo30.zip
* TAdvFTP, FREEWARE with source - by Vadim Winebrand (KYLIX)
An advanced FTP client component which supports resumes and gives the
download rate every few seconds. Includes socks server support.
http://www.torry.net/kylix/clx/internet/itools.zip
Articles, tips and tricks
=========================
* TJpegImage lets you transform BMPs to JPEGs - by Bob Swart
Dr Bob shares a trick for transforming BMPs to JPEGs and vice versa.
Thanks to a hidden component, it's not as hard as you might think.
http://builder.com.com/article.jhtml?id=u00220020913swa01.htm
* Using Delphi objects to store config information - by Sebastián Mayorá
This article explains how to use objects as a substitute for INI files
(and other similar techniques) to store configuration information.
http://delphi.about.com/library/bluc/text/uc090302a.htm
* Back to School with more Delphi knowledge - by Zarko Gajic
Whether you're parent, student or teacher here are the topics you need
to enhance your knowledge of Delphi programming. Go back to school in
style with the right tutorials, code samples and Delphi quizzes.
http://delphi.about.com/library/weekly/aa082702a.htm
* ModelMaker tutorials - by Anders Ohlsson
ModelMaker is included in D7 Enterprise & Architect - here are some
tutorials to get you started.
http://bdn.borland.com/article/0,1410,29006,00.html
* How to install and uninstall fonts
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=169
* How to check if a string is a number
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=170
* How to get second title bar color
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=171
* BDE error list
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=173
* How to get the CPU speed
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=174
* How to write a correct date in SQL
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=175
* How to get around TQuery.Refresh if it doesn't work - by m3Rlin
Sometimes TQuery.Refresh will not refresh as it's supposed to...
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=176
* How to read the serial number of an Audio CD - by m3Rlin
Audio CDs, like almost every computer drive/media have a serial number
too. Some programs use this number to recognize CDs.
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=177
* How to check is a character is a letter - by m3Rlin
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=178
* How to export a StringGrid to an Excel-File?
http://www.swissdelphicenter.ch/en/showcode.php?id=379
* How to turn on/off Caps/Num/Scroll Lock?
http://www.swissdelphicenter.ch/en/showcode.php?id=926
* How to synchronize DBGrid title alignments with field alignments?
http://www.swissdelphicenter.ch/en/showcode.php?id=1074
* How to save memory with duplicate strings?
http://www.swissdelphicenter.ch/en/showcode.php?id=1110
* How to draw a gradient on a canvas with an arbitrary number of colors?
http://www.swissdelphicenter.ch/en/showcode.php?id=1162
* How to retrieve information about the TWebBrowser control?
http://www.swissdelphicenter.ch/en/showcode.php?id=1191
* How to retrieve the network card addresses?
http://www.swissdelphicenter.ch/en/showcode.php?id=1206
* How to convert C Types to Object Pascal Types?
http://www.swissdelphicenter.ch/en/showcode.php?id=1217
* How to get an inverse color value to a color?
http://www.swissdelphicenter.ch/en/showcode.php?id=1222
* How to show values in a hexadecimal representation?
http://www.swissdelphicenter.ch/en/showcode.php?id=1312
* How to show values in binary representation?
http://www.swissdelphicenter.ch/en/showcode.php?id=1313
* How to get the start command for a installed Mail-Client?
http://www.swissdelphicenter.ch/en/showcode.php?id=1320
* How to execute a document and wait for it to finish?
http://www.swissdelphicenter.ch/en/showcode.php?id=1333
* How to do bit-wise manipulation?
http://www.swissdelphicenter.ch/en/showcode.php?id=1341
* How to Draw on a Form's Caption bar?
http://www.swissdelphicenter.ch/en/showcode.php?id=1345
* How to access Paradox tables on CD or read-only drives?
http://www.swissdelphicenter.ch/en/showcode.php?id=1351
* How to define BDE aliases in code?
http://www.swissdelphicenter.ch/en/showcode.php?id=1353
* How to multiply big integer values?
http://www.swissdelphicenter.ch/en/showcode.php?id=1363
* How to calculate the logarithm for a variable base?
http://www.swissdelphicenter.ch/en/showcode.php?id=1371
* How to auto hide IDE windows when coding/designing?
http://www.swissdelphicenter.ch/en/showcode.php?id=1382
* How to get the length of wav file (in second)?
http://www.swissdelphicenter.ch/en/showcode.php?id=1383
* How to Clone the Controls Properties?
http://www.swissdelphicenter.ch/en/showcode.php?id=1392
* How to set system evrionment variable?
http://www.swissdelphicenter.ch/en/showcode.php?id=1394
* How to Set a new Index to TToolButton of a TToolbar?
http://www.swissdelphicenter.ch/en/showcode.php?id=1395
* How to include the mouse-cursor in a screen shot?
http://www.swissdelphicenter.ch/en/showcode.php?id=1396
* How to send data to another program by auto-drag&drop?
http://www.swissdelphicenter.ch/en/showcode.php?id=1398
* How to empty all StringGrid cells?
http://www.swissdelphicenter.ch/en/showcode.php?id=1399
* How to get the width and height of a Gif-File?
http://www.swissdelphicenter.ch/en/showcode.php?id=1400
* How to transition the system to the standby/ hibernate state?
http://www.swissdelphicenter.ch/en/showcode.php?id=1401
* How to know if the form is modal?
http://www.swissdelphicenter.ch/en/showcode.php?id=1402
* How to prevent copy/paste/cut in TEdit?
http://www.swissdelphicenter.ch/en/showcode.php?id=1403
* How to use regular expressions in Delphi?
http://www.swissdelphicenter.ch/en/showcode.php?id=1406
* How to save a QuickReport to stream?
http://www.swissdelphicenter.ch/en/showcode.php?id=1410
* How to build a Multi Screen Emulator?
http://www.swissdelphicenter.ch/en/showcode.php?id=1418
* How to use the DrawAnimatedRects API?
http://www.swissdelphicenter.ch/en/showcode.php?id=1419
* How to get the caret-position systemwide?
http://www.swissdelphicenter.ch/en/showcode.php?id=1420
* How to invoke the 'find' dialog in a TWebBrowser?
http://www.swissdelphicenter.ch/en/showcode.php?id=1421
* How to determine if the current session is remotely controlled?
http://www.swissdelphicenter.ch/en/showcode.php?id=1424
* How to translate a virtual-key to ASCII code?
http://www.swissdelphicenter.ch/en/showcode.php?id=1425
* How to convert a bitmap to RTF code?
http://www.swissdelphicenter.ch/en/showcode.php?id=1426
* How to export a TDBGrid to excel without OLE?
http://www.swissdelphicenter.ch/en/showcode.php?id=1427
* How to read a REG_MULTI_SZ value From the Registry?
http://www.swissdelphicenter.ch/en/showcode.php?id=1431
* How to restore the default positions of the IDE Toolbars?
http://www.swissdelphicenter.ch/en/showcode.php?id=1432
* How to retrieve all database tables with ADO?
http://www.swissdelphicenter.ch/en/showcode.php?id=1433
* How to add items to the Application's Windows System Menu?
http://www.swissdelphicenter.ch/en/showcode.php?id=1435
* How to get the number of Files in the Recycle Bin + their total size?
http://www.swissdelphicenter.ch/en/showcode.php?id=1436
* How to change Background Color in TRichEdit for selected characters?
http://www.swissdelphicenter.ch/en/showcode.php?id=1438
* How to show/hide the ActiveDesktop?
http://www.swissdelphicenter.ch/en/showcode.php?id=1439
* How to copy formated Rtf-Text from one TRichedit to an other?
http://www.swissdelphicenter.ch/en/showcode.php?id=1440
* How to use different underline styles for Text in TRichEdit?
http://www.swissdelphicenter.ch/en/showcode.php?id=1441
* How to put the TWebbrowser into Edit Mode?
http://www.swissdelphicenter.ch/en/showcode.php?id=1442
* How to set the paragraph line spacing in a TRichedit?
http://www.swissdelphicenter.ch/en/showcode.php?id=1444
* Speed up connection to Oracle 8i - by Mark Halter
http://www.delphi3000.com/articles/article_3344.asp
* How do we store Graphics/Shapes like an Object? - max kleiner
Designing a diagram editor or a graphic-tool raises the problem of
storing all the painted shapes in a file without get lost in too much
overhead.
http://www.delphi3000.com/articles/article_3348.asp
* Simulate a Web Form POST Request - by Clever Components
Discusses the automation of the upload process via HTTP protocol by
the POST method using the components from Clever Internet Suite.
http://www.delphi3000.com/articles/article_3351.asp
* Threaded Brute Forcing Class - by Stewart Moss
http://www.delphi3000.com/articles/article_3352.asp
* Simple useful Irc routines - by Stewart Moss
http://www.delphi3000.com/articles/article_3353.asp
* Generic File Importer Base Class - by Stewart Moss
Here is a useful base class to create derived classes to import data
from any flat file format you can think of.
http://www.delphi3000.com/articles/article_3354.asp
* ADO Dataset -> CSV file
How to export a ADO Dataset to a Comma Separated Values file with a
few lines of code.
http://www.delphi3000.com/articles/article_3355.asp
* Send E-Mails with Indy Components (Easy)
http://www.delphi3000.com/articles/article_3356.asp
* Show message in OnEnter event
Do you ever needed to display a message using the OnEnter event?
This example shows how to correctly display a message by using the
ShowMessage (or an equivalent function) in OnEnter event.
http://www.delphi3000.com/articles/article_3357.asp
* EventLog change notification in real-time
I needed a way to be notified in real-time when someone acceded my
computer inside an intranet. After doing some research, the solution
would pass by using the Security event log that is used when you
activate any audit option.
http://www.delphi3000.com/articles/article_3358.asp
* SQL-DMO part 1: The SQL-DMO API
This is the first part of a serie of articles about the SQL
Distributed Management Objects known as SQL-DMO API. In this first
article I'll talk about SQL-DMO, whats the purpose of it and what
you'll gain if you use it. I will also show how to install it, so
you can use it within our Delphi projects
http://www.delphi3000.com/articles/article_3359.asp
* Multi Column ListBox with Column Sorting and Resizing
This is a VCL that allows multiple columns in a list box. The columns
may be sorted (if the AllowSorting property is set to true) by
clicking on the column header title. The column headers are set up in
the Sections property. They are of type THeaderSections from the
THeader component and thus may also display images from an associated
image list. The items in the ListBox are semi-colon delimited fields.
The fields are lined up in accordance to the Section headers and may
be resized by the user at run-time.
http://www.delphi3000.com/articles/article_3360.asp
* Capture Output of a Console Application - Revised
How do you start a DOS or Console Application and capture the output
while it is running ? For example, how do you capture the output of
the FileCompare (FC) Command ?
http://www.delphi3000.com/articles/article_3361.asp
* Retrieve Multiple Recordsets from ORACLE 8i Stored Procedure
A faster and more resource efficient way to get data from the
Database server (in this case - Oracle)
http://www.delphi3000.com/articles/article_3363.asp
Tutorials
=========
* Defining a ClientDataSet's Structure Using TFields - by Cary Jensen
This article demonstrates how to define a ClientDataSet's structure at
both design-time and runtime using TFields. How to create virtual and
nested dataset fields is also demonstrated.
http://community.borland.com/article/0,1410,29001,00.html
* Understanding ClientDataSet Indexes - by Cary Jensen
A ClientDataSet does not obtain its indexes from the data it loads.
Indexes, if you want them, must be explicitly defined. This article
shows you how to do this at design-time or runtime.
http://community.borland.com/article/0,1410,29056,00.html
* Improve application design with Prototyping, Modeling, + Storyboarding
- by Ronald Anthony Lewis
Meeting client expectations is the number-one goal of application
development. Here's how one developer uses three approaches to handle
different aspects of this critical objective.
http://builder.com.com/article.jhtml?id=u00320020909RAL01.htm
* An introduction to XML grammar - by Philip Page
Document Type Definitions (DTDs) are an optional but useful part of
XML. This article shows you how to declare a grammar in a DTD.
http://builder.com.com/article.jhtml?id=u00320020906ppg01.htm
* Unified Modeling Language simplifies software design - by Shelley Doll
UML is the industry standard for modeling software architecture. It
combines best practices, platform independence, and extensibility into
a common language for describing solutions. This overview of UML
describes why it's useful and outlines the major concepts.
http://builder.com.com/article.jhtml?id=u00420020903dol01.htm
* To be or not to be normal: That is the database question - Eric Roland
There are advantages + disadvantages to normalizing database schemas.
This article provides specific examples of when and why you should
normalize or denormalize your final database design based on
performance requirements.
http://builder.com.com/article.jhtml?id=u00320020819ero01.htm
* Transition from Logical to Physical Data Model - S Harkins + A Fuller
Moving from a logical to physical design is not as straightforward as
it appears. Use these tips to make the process as smooth as possible.
http://articles.techrepublic.com.com/5100-10878_11-1050841.html
Other Links
===========
* Delphi Fireworks Component Contest
Basically, you have to make a self-contained Delphi visual component.
There are no prizes, but you will receive awe and recognition from
your peers, just for entering. Also it makes a great resume entry.
http://chuckr.freeshell.org/index.php
* ModelMaker is available for Delphi 7 Professional - by John Kaster
Borland provides a license to ModelMaker for Delphi 7 Professional.
http://community.borland.com/article/0,1410,29090,00.html
* Borland to wield tools against Microsoft - by Wylie Wong
After nearly being knocked out for good by Microsoft, software maker
Borland is back on its feet and eager for a rematch.
http://news.cnet.com/2100-1001-954958.html
* Borland has a bead on Visual Studio - By Mark Driver (from Gartner)
Borland plans to offer an alternative to Microsoft's Visual Studio
.NET development environment. Such a product could suit application
developers that want to leverage .NET and the best applications from
many vendors.
techupdate.zdnet.com/techupdate/stories/main/0,14179,2879601,00.html
* Now all we need are celebrity endorsements - by Lamont Adams
Humourous article about the possibility of celebrity endorsements in
programming. Use the official IDE of the World Cup!
http://articles.techrepublic.com.com/5100-10878_11-1050148.html
* SharpDevelop lets you jump into C# Programming for FREE! - Tony Patton
You're dying to start programming in C#, but Visual Studio .NET is
just too expensive. Help is on the way with this free .NET IDE.
http://articles.techrepublic.com.com/5100-10878_11-1050213.html
________________________________________________________________________
YOU CAN HELP US
We need your help to keep this newsletter going and growing. You can
help by referring the newsletter to your colleagues:
http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Or you can help by voting for us in some or all of these rankings to
give more visibility to our web site and thus increase the number of
subscriptions to this newsletter:
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
It's just a few seconds for you that REALLY mean a lot to us.
Don't forget we also need articles for this newsletter and there is a
prize for one of the authors in each issue. All articles will be
considered but we are particularly interested in articles about Kylix
because there is so little available online to help Kylix developers.
Send articles to <eds2008 @ latiumsoftware.com>.
We are also looking for shareware authors who would like to offer their
components or applications as prizes for articles in the newsletter. In
return you will be promoted in this newsletter and the Latium Software
web site. For more information contact Dave <irongut @ vodafone.net>.
________________________________________________________________________
If you haven't received the full source code examples for this issue,
you can get them from http://www.latiumsoftware.com/en/file.php?id=p39
________________________________________________________________________
This newsletter is provided "AS IS" without warranty of any kind. Its
use implies the acceptance of our licensing terms and disclaimer of
warranty you can read at http://www.latiumsoftware.com/en/legal.php
where you will also find a note about legal trademarks. Articles are
copyright of their respective authors and they are reproduced here with
their permission. You can redistribute this newsletter as long as you do
it in full (including copyright notices), without changes, and gratis.
________________________________________________________________________
Group home page: http://groups.yahoo.com/group/pascal-newsletter/
Subscribe/join: pascal-newsletter-subscribe@yahoogroups.com
Unsubscribe/leave: pascal-newsletter-unsubscribe@yahoogroups.com
Report spam/abuse: abuse@yahoogroups.com
Problems with your subscription? eds2008 @ latiumsoftware.com
________________________________________________________________________
Latium Software http://www.latiumsoftware.com/en/index.php
Copyright (c) 2002 by Ernesto De Spirito. All rights reserved.
________________________________________________________________________
|