Pascal Newsletter #49 - 29-SEP-2003
Contents
1. A few words from the editor
2. Class Attributes - The Delphi Way
3. Creating a Delphi Expert
The simplest way of creating a Delphi Expert
4. Inside Delphi's Classes and Interfaces (I)
5. Forums / mailing lists
6. Delphi on the Net
- Components, Libraries and Utilities
· Shareware/Commercial
· Freeware
· Delphi and Borland Product Updates
- Articles, Tips and Tricks
- Tutorials and Training
- Other Links
- News
________________________________________________________________________
1. A few words from the editor
I'm happy to announce the newsletter has reached 10,000 subscribers.
Special thanks to all the subscribers who made it possible by referring
the newsletter to their colleagues, and also to all the webmasters who
exchanged links with us, allowing the web site to be known in the Delphi
community.
In this issue we have an article by Demian Lessa showing a way to
implement class attributes in Object Pascal, an article by Daniel
Wischnewski explaining how to create a simple Delphi Expert, and an
article by Ezra Hoch revealing the inner workings of classes and
interfaces. Thanks to the authors for contributing their articles for
this issue, and the prizes available for this issue go to:
* Demian Lessa ("Class Attributes - The Delphi Way")
· NTTools 7 For Delphi - by i-tivity (US$ 49.95)
Stop battling the Windows NT Security API! Get your copy of NTTools 7
for Delphi 4/5/6/7 now and save countless hours with this collection
of 40 VCL components written specifically to deal with the Windows NT
Security functions. Full source code is included.
http://www.i-tivity.biz/nttools.htm
* Daniel Wischnewski ("Creating a Delphi Expert")
· LMD SearchPack 2.0 - by LMD Innovative (EUR 39)
LMD SearchPack includes 3 controls for integrating advanced text
search capabilities into your projects including support of AND, OR,
NEAR and NOT operators. Full source code and extensive demo projects
included. http://www.lmdinnovative.com/products/vcl/lmdsearchpack/
For the next issue, we have available the following prizes for two of
our contributors:
* EurekaLog v4.1.1 - by Fabio Dell'Aria (Std $24, Pro $49, Ent $99)
EurekaLog gives your application (GUI, Console, Web, etc.) the ability
to catch every exception, generate a detailed log (with unit, class,
method and line #) and send it via email. Fully integrated into the
IDE, you only need a single rebuild to add EurekaLog to your apps.
Does not decrease performance and increases compiled file size by just
0.5% - 4%. Compatible with Delphi 3 - 7 and all Windows platforms.
http://www.eurekalog.com/bannerclick.php?id=15
* SMExport v4.30 - by Scalabium Software ($20 standard, $35 with source)
Native VCL suite for exporting data from different sources (dataset,
grids, decision cube, memory, DevExp trees, etc). Supports export
into MS Excel, MS Access, MS Word, PDF, Text/CSV, HTML, XML, dBase,
RTF, SQL, Lotus 1-2-3, QuattroPro and more.
http://www.scalabium.com/
The link to the updated Kylix 3 fixes published in the last issue was
incomplete. Thanks to Chris Nye for letting us know the correct link is
http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=20136
After the publication of my article "Playing sounds with the PC speaker"
in the last issue, many people asked me about generating sounds thru the
PC speaker under Windows NT/2000/XP. Under these operating systems, the
Windows API Beep accepts as arguments the frequency of the sound (in
hertz) and duration (in milliseconds), which are ignored under Windows
95/98/Me.
Well, this is it. I hope you enjoy this issue.
Regards,
Ernesto De Spirito
eds2008 @ latiumsoftware.com
__________________
Collaborated in this issue: Dave Murray
________________________________________________________________________
Help & Manual 3, by EC Software - Shareware ($ 279) - Help & Manual is a
WYSIWYG help authoring tool that will aid you in creating standard
WinHelp files (.HLP), Adobe PDF files, HTML pages and the new HTML HELP
(.CHM) files introduced in Windows 98, as well as other file formats and
printed documentation, everything from a single source. This is a must-
have for any software developer. http://www.helpandmanual.com/hmpage.htm
________________________________________________________________________
2. Class Attributes - The Delphi Way
By Demian Lessa <demian @ knowhow-online.com.br>
On a recent discussion about class attributes on the delphi-br forum on
Yahoo! Groups, I had the chance to learn a new technique that allows the
practical implementation of class attributes in Delphi. But, what are
class attributes anyway?
Class attributes are values associated with a class itself and not its
instances. In other words, the class attribute value is the same across
all class instances. And how are class attributes useful? I can suggest
two very obvious utilities: class instance counting, and association of
an object instance to the class as a whole (for management purposes).
When you need to keep track of the number of instances of a given class
you may do so by using a global unit variable on the implementation
section- this guarantees that the variable doesn't get changed by code
outside the unit. Yet, other portions of code inside the unit (even
outside the class) can still change the value of that variable. By
encapsulating this value in a class attribute the problem is solved and
the instance count can only be changed through proper calls to methods
of the class.
Another important use of class attributes relates to the use of manager
or helper objects. Imagine, for instance, that instead of counting the
instances of a class we wish to keep a list of the running instances of
our class. All we have to do is define a class attribute to keep a list
of the class instances. This list object can be instantiated when needed
and destroyed, for example, in the finalization of the unit. This can
even be used as the basis for a simple garbage collection mechanism!
The implementation of class attributes in Delphi is presented below. The
values of the class attributes are hidden inside the class and can only
be changed through calls to the proper setter methods. The trick on how
to encapsulate the value was presented to me by Marcelo Almeida, one of
the moderators of the delphi-br forum on Yahoo! Groups.
type
TMyClass = class
private
class function Attribute: PInteger;
class function InstanceList: Pointer;
class procedure DestroyInstanceList;
public
constructor Create;
class function GetAttribute: Integer;
class function GetInstanceList: TObjectList;
class procedure SetAttribute(Value: Integer);
end;
class function TMyClass.Attribute: PInteger;
{$J+}
const
placeholder: Integer = 0;
{$J-}
begin
Result := @placeholder;
end;
class function TMyClass.InstanceList: Pointer;
{$J+}
const
placeholder: TObjectList = nil;
{$J-}
begin
if (TObjectList(Pointer(@placeholder)^) = nil) then
// let us destroy our objects
placeholder := TObjectList.Create(false);
Result := @placeholder;
end;
class procedure TMyClass.DestroyInstanceList;
begin
if (GetInstanceList <> nil) then
begin
GetInstanceList.Free;
TObjectList(InstanceList^) := nil;
end;
end;
class function TMyClass.GetAttribute: Integer;
begin
Result := Attribute^;
end;
class function TMyClass.GetInstanceList: TObjectList;
begin
Result := TObjectList(InstanceList^);
end;
class procedure TMyClass.SetAttribute(Value: Integer);
begin
Attribute^ := Value;
end;
constructor TMyClass.Create;
begin
inherited Create;
SetAttribute(GetAttribute + 1);
GetInstanceList.Add(Self);
end;
destructor TMyClass.Destroy;
begin
SetAttribute(GetAttribute - 1);
GetInstanceList.Remove(Self);
if (GetInstanceList.Count = 0) then
DestroyInstanceList;
inherited Destroy;
end;
In TMyClass, the class methods Attribute and InstanceList are
responsible for encapsulating the values of the class attributes. In
these methods, local typed constants ($J+ directive) are used as
placeholders for the class attributes. Typed constants can have their
values changed in runtime the same way as variables. But the constants
we use are local- so, how can they store global values for the class?
The answer is pretty simple: we don't use the values of the constants.
The constants are declared so the compiler reserves the proper memory
for their value types. And, though declared as local, the memory space
that the compiler reserves for them (represented by a simple pointer)
isn't changed throughout program execution and, therefore, we can use
this memory space to implement our class attributes. Clever, huh? The
methods Attribute and InstanceList return pointers to the memory
reserved by the compiler for the local typed constants. This is the big
trick!
On the attached code you will find the full source for TMyClass and a
small application showing the use of the class attributes of TMyClass.
________________________________________________________________________
Support us! Vote for the Pascal Newsletter in The Programming Top 100!
http://top100borland.com/in.php?who=20
________________________________________________________________________
3. Creating a Delphi Expert
The simplest way of creating a Delphi Expert
Copyright © 2003 Daniel Wischnewski.
Visit my company
http://www.gatenetwork.com
German Version of this article available at
http://www.delphipraxis.net/referenzen.php
Introduction
============
Sometimes you want to define some routines to make your life easier
while using Delphi. A simple way to do this is creating an Expert.
This first article shows you the basics.
This article introduces you to the world of Delphi Experts. Delphi
Experts are DLLs that will be loaded during the startup sequence of
Delphi. This article first appeared on Delphi-PRAXiS in German:
http://www.delphipraxis.net/viewtopic.php?t=5300
NOTE: The techniques shown in this article are valid starting with
Delphi 3 or 4 and since Delphi 7 they are deprecated, however,
still fully supported by the Delphi IDE.
Installation of a Delphi-IDE-Expert
===================================
Every Delphi Expert has to be registered in the Windows Registry. For
each Delphi version installed on a machine, as well as for each user
using the machine, the Delphi Expert has to be registered separately.
In the Registry, the Delphi Expert has to be registered under the
following key:
HKCU\Software\Borland\Delphi\X.0\Experts
where the X has to be replaced by the appropriate Delphi version
supported. It may happen that the Experts key is not installed, in
such case you are required to create it.
Underneath the Experts key you have to create a string value for the
Delphi Expert. The name must be unique and the value must point to the
expert's DLL, including both complete path and file name of the Delphi
Expert. Next time Delphi starts, the Expert will be loaded
automatically.
The interface of the Delphi Expert
==================================
In order for the Delphi Expert to interact with the Delphi IDE it has
to export a function with the name ExpertEntryPoint, using the following
parameters:
function InitExpert(
ToolServices: TIToolServices;
RegisterProc: TExpertRegisterProc;
var Terminate: TExpertTerminateProc):
Boolean; export; stdcall;
The first parameter ToolServices offers all "documented" interfaces to
the Delphi IDE. The second parameter RegisterProc is used to load the
expert into the Delphi IDE. The last parameter Terminate is used to
notify the Expert DLL when it is about to be unloaded by the Delphi IDE.
The InitExpert method returns True if the Expert has loaded
successfully, otherwise it can either return False or raise an exception
to unload the DLL from the Delphi IDE (see code sample for solution).
The PlugIn class TIExpert
=========================
Any Delphi Expert must be derived from the class TIExpert, which is
declared in the unit ExptIntf. This class defines some abstract methods
which must be implemented by each PlugIn: GetName, GetAuthor,
GetComment, GetPage, GetGlyph (different for Windows and Linux),
GetStyle, GetState, GetIDString, GetMenuText and Execute. The purpose of
each method is explained in the source code below.
The simplest Delphi Expert
==========================
This Delphi Expert won't do much good, however it shows you the basic
way of getting the job done. It will show an entry in the Help menu
(default behavior). Once the user clicks the menu item, the method
Execute from the Expert will be called. The following points must be
respected in order to get the expert working:
* The method GetState must return [esEnabled]
* The method GetStyle must return esStandard
* The method GetMenuText returns the text to be shown in the Help menu
* The method Execute defines the expert action upon activation
The full source code of this simple expert can be found attached.
________________________________________________________________________
Delphi-PRAXiS · Community for German-speaking Delphi programmers. We
are not just (one of) the fastest growing German Delphi-forums, but we
also offer some unique services like our "Delphi-PRAXiS Expert" (a
Delphi add-on which allows access to our libraries directly from within
the IDE). In the "code library" you can find several tips, tricks and
snippets ready to use. Our database contains more than 50,000 articles
for searches of any kind. >>>>>>>> http://www.delphipraxis.net <<<<<<<<
________________________________________________________________________
4. Inside Delphi's Classes and Interfaces (I)
By Ezra Hoch
A few words before we start:
- First, I want to start this article by saying that all of the
knowledge in this paper is derived from viewing the disassembler of
Delphi 5. Hence everything written here is valid only for Delphi 5 and
might change by any upgrade or different version.
- Second, in order to fully understand what is written in this article,
you'll have to dive into some assembler code. I'll explain what the
assembler code does, but be prepared, it might get messy.
And now to the real stuff. In Delphi, a class' instance is a simple
pointer. That might seem odd to some people, since you've used instances
in Delphi many times and never had to treat them like pointers. That is
correct, but only because Borland was kind enough to wrap these pointers
nicely up. These pointers actually point to a complicated structure in
memory, which we'll try to understand. First, we'll look at a simple
class definition:
TBoo1 = class
FDataA, FDataB : Integer;
end;
var
Boo1 : TBoo1;
begin
Boo1 := TBoo1.Create;
end;
Now let's look at what Boo1 points to (Boo1 is a pointer, remember?).
Boo1 points to the following values, each 4 bytes long:
a Pointer to TBoo1's VMT
FDataA
FDataB
Now let's examine a descendant of TBoo1:
TBoo2 = class(TBoo1)
FDataC, FDataD : Integer;
end;
var
Boo2 : TBoo2;
begin
Boo2 := TBoo2.Create;
end;
Boo2 will point to the following values in memory:
a Pointer to TBoo2's VMT
FDataA
FDataB
FDataC
FDataD
Notice that the values that Boo2 points to include some of the values
that Boo1 points to. That's very easy to explain - TBoo2 inherits from
TBoo1, therefore it must include all of the fields that TBoo1 has.
As a general rule, we can state that each class instance points to the
following values:
a pointer to the Class' VMT
a list of the fields of the parent class
a list of the fields of the class
Now it's time to investigate interfaces. Before we can fully understand
interfaces we must understand the way Delphi makes a method call to a
class instance. What Delphi actually does, is call a function with one
more parameter than was declared, and that parameter is the instance
itself. Let's look at an example:
TMoo = class
FData: Integer;
procedure Act(Value: Integer);
end;
procedure TMoo.Act(Value: Integer);
begin
if Self.FData = Value then Self.FData := FData + 1
else Self.FData := Value;
end;
var
Moo: TMoo;
begin
Moo := TMoo.Create;
Moo.Act(15);
end;
How does Delphi implement this? Simple, 'TMoo.Act' is actually compiled
into a procedure that accepts two(!) parameters. One is the defined
parameter -'Value' of type integer. The other is an instance of class
TMoo. Every time Delphi calls 'Moo.Act' it does some preprocessing
beforehand, that is, it passes the instance of TMoo that is making the
call. Basically you could say that any call to a method of an object is
translated to a regular call to a function / procedure that accepts the
object making the call as a parameter.
In the previous example, 'TMoo.Act' is actually compiled to something
like this:
procedure TMoo_Act(Self: TMoo; Value: Integer);
begin
if Self.FData = Value then Self.FData := FData + 1
else Self.FData := Value;
end;
It's time to go back to interfaces. Consider the following code:
IKoo = interface
function Calculate(Value: Integer): Double;
end;
function Evaluate(Koo: IKoo; Value: Integer): Double;
begin
Result := Koo.Calculate(Value);
end;
TKooA = class(TInterfacedObject, IKoo)
function Calculate(Value: Integer) : Double;
end;
TKooB = class(TInterfacedObject, IKoo)
procedure DoNothing;
function Calculate(Value: Integer): Double;
end;
Any class that supports IKoo can be passed as a variable to the function
'Evaluate'. When we pass an instance of TKooA to 'Evaluate' we need to
call the first method of TKooA, but when we pass an instance of TKooB,
we need to call the second method of TKooB! How will Delphi know which
function to call at each time?!
In order to understand the answer, we must review what an interface
really is (and how it is implemented in Delphi). An interface is simply
a list of methods that a class declares that it implements. That is,
each method in the interface is implemented in the class. The way Delphi
implements this is as follows:
Each interface a class supports is actually a list of pointers to
methods. Therefore, each time a method call is made to an interface,
the interface actually diverts that call to one of its pointers to
method, thus giving the object that really implements it the chance to
act. I'll explain that via the 'Koo' example above:
Each time the function 'Evaluate' gets a parameter of type IKoo, it
really gets a list (with 4 items - IKoo inherits from IUnknown) of
pointers to methods. If it got an IKoo interface that was implemented
by TKooA, then the 4th item in the pointer-to-method list would point
to 'TKooA.Calcualte'. Otherwise it would point to 'TKooB.Calcualte'.
Therefore, when a call is made to 'IKoo.Calculate' what actually is
called is what 'IKoo.Calcualte' points to (either 'TKooA.Calculate' or
'TKooB.Calculate'). This is how Delphi implements interfaces.
And now to how Delphi stores interfaces in memory. For each instance of
a class that supports 'N' interfaces, we need 'N' different lists of
pointer-to-method (one for each interface). But these lists are the same
in the scope of a single class, therefore, in order to save memory, we
only hold 'N' pointers to these lists for each instance (instead of the
lists themselves).
Consider the following code:
ILooA = interface
end;
ILooB = interface
end;
TLoo = class(TInterfacedObject, ILooA, ILooB)
FLooA, FLooB: Integer;
end;
This is how an instance of TLoo would look in memory:
a pointer to TLoo's VMT
FRefcount
IUnknown
FLooA
FLooB
ILooB
ILooA
In general, any class instance would look like this:
a pointer to the class' VMT
the parent's class' structure (except for the pointer to the VMT)
first data member of the class
.
.
last data member of the class
last interface in the class' interface list
.
.
first interface in the class' interface list
As I said at the beginning of this article, in order to really grasp the
way Delphi implements classes and interfaces we must look at the
assembler code Delphi produces. First we'll learn a bit of assembler
in order to understand the code that will follow. In assembler there is
a thing called 'Register'. A register is a place in the CPU that can
hold a 32 bit value. On a Pentium CPU there are 8 main registers (EAX,
EBX, ECX, EDX, ESI, EDI, EBP, ESP). Most actions that are done in
assembler are done on registers. Here are a few commands in assembler:
(Moves the value into the register)
Mov Register, Value
(Moves the value in Register2 into Register1)
Mov Register1, Register2
(Moves the value that Register2 points to into Register1.
This is the same as the following code: "Register1 := Register2^;")
Mov Register1, [Register2]
(Moves the value that Register2 + Value points to into Register1.
The same as: "Register1 := Pointer(Integer(Register2) + Value)^;")
Mov Register1, [Register2 + Value]
Examples:
MOV EAX, 10
MOV EBX, EAX
MOV EAX, [EBX + 6]
EBX will hold the value 10 and EAX will hold the value that is in the
address $10.
Just in order to make sure that you understood this part, I'll give an
example of how Delphi assigns a value to an instance's data member.
TGoo = class
FDataA, FDataB: Integer;
end;
var
Goo: TGoo;
begin
Goo := TGoo.Create;
Goo.FDataA := 5;
Goo.FDataB := 7;
end;
If you'd open Delphi's disassembler you'd see the following code:
// Goo.FDataA := 5;
mov eax, [ebp-$08]
mov [eax + $04], $00000005
// Goo.FDataB := 7;
mov eax, [ebp-$08]
mov [eax + $08], $00000007
Why move the value pointed by "ebp-$08"? Simple, that's where the
variable Goo is stored. Notice that accessing FDataA is the same as
accessing the address at "eax+$04" and that accessing FDataB is the
same as accessing the address at "eax+$08". That's because the address
"eax" points to is the pointer to the VMT of TGoo, and (as I mentioned
before) the following values in memory are the data members of TGoo.
Let's go back to interfaces. Look at the following code:
IRoo = interface
end;
TRoo = class(TInterfacedObject, IRoo)
end;
var
Roo: TRoo;
RooIntf: IRoo;
begin
Roo := TRoo.Create;
RooIntf := Roo;
RooIntf._AddRef;
end;
The following assembler code isn't exactly what Delphi produces but it
does the same and serves the purpose:
// RooIntf := Roo;
// eax holds the value returned by TRoo.Create, i.e. the variable Roo
// ecx holds the value that should later be assigned to RooIntf
mov ecx, eax
// This is the same as: "ecx := ecx + $0C;"
add ecx, $0C
// RooIntf._AddRef
// Push "ecx" onto the CPU's stack
push ecx
mov ecx, [ecx]
// "call ecx" tells the CPU to jump to the address stored as a value
// in "ecx"
call ecx
Let's look at the code that "call ecx" brought us to:
// POP the value we pushed onto the stack into "ecx"
pop ecx
// Same as: "ecx := ecx - $0c;"
sub ecx, $0C
// Call the method "_AddRef" with "ecx" as a variable.
call TInterfacedObject._AddRef(ecx)
A little explanation is due. Why did Delphi add "$0C" to "ecx"?
Remember how Roo is stored in memory (a pointer to VMT, FRefCount (of
InterfacedObject), IUnknown (of TInterfacedObject), IRoo). IRoo is the
fourth value in the list that "ecx" points to. Each value is 4 bytes
long, so IRoo is 12 (4*4) bytes after "ecx", and "$0C" is 12 in
hexadecimal notation. So, basically, adding "$0C" to "ecx" just made
"ecx" point to the right value, that is, to point to IRoo of Roo (an
instance of TRoo).
Why do we push ecx into the stack? That's because we'll need to use it
later, when calling the real "_AddRef" method. Remember, "ecx" is the
value pointing to Roo + 12.
After that, we move into "ecx" the value that "ecx" pointed to. Remember
when I said that instead of holding the lists of pointer-to-method,
Delphi stores only the pointers to them (to save memory)? That's why
"ecx" was actually a pointer, but now it holds the value it pointed to
before.
The next command, is to call the method that "ecx" holds. Now we'll look
at that method. It's very short. The only thing it does is modify the
value of "ecx" (after popping it from the stack) so it is equal to the
value of Roo (that is, it points to the variable Roo). Then the method
'TInterfacedObject._AddRef' is called with "ecx" (Roo) as a parameter.
This is the same as when I've written that Delphi actually compiles a
class' method into a regular function / procedure that accepts one extra
parameter - the instance of the class.
What was that good for? We added a value from a pointer, then did this
jump around in memory, then subtracted the same value from the pointer
and called the function the pointer points to! Why bother? We could
simply call the function without adding and subtracting values!
This is where the power of indirection comes into the game. Notice that
the call to 'RooIntf._AddRef' didn't know that RooIntf was actually of
an instance of TRoo. It just called the method that was there to call.
The implementation of this method is where the reassigning of the value
of the pointer was made. That is, only the implementation that RooIntf
points to (IRoo of TRoo) knew how much was added or subtracted from the
pointer pushed to the stack. If we had another variable of type TRoo2,
that also implemented IRoo, and we would have made the following
assignment 'RooIntf := variable of type TRoo2', and would have called
the method 'RooIntf._AddRef', then a different value would be subtracted
from the value in the stack, thus making the method call go to the right
place in the TRoo2 class.
__________________
The author can be reached at ezra.hoch@saad.org.il
________________________________________________________________________
Vote for the Pascal Newsletter in The Programming Pages!
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal&Language=29
________________________________________________________________________
Delphi BUGS?
Catch & Log every BUG showing Unit, Class, Method, Line #.
Now with support for IntraWeb applications and Anti-Freeze feature.
http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________
5. 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 (intermediate level): If you know a lot about Delphi but you
are still far (or not so far) from being a guru, then 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
* Delphi (all levels): A Delphi group open to all levels.
http://groups.yahoo.com/group/delphi-all/
Subscription:
http://groups.yahoo.com/group/delphi-all/join
delphi-all-subscribe@yahoogroups.com
* Delphi-PRAXiS Forum, for GERMAN-speaking Delphi programmers.
http://www.delphipraxis.net/
* 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://tech.groups.yahoo.com/group/software-developers/
Subscription:
http://tech.groups.yahoo.com/group/software-developers/join
software-developers-subscribe@yahoogroups.com
________________________________________________________________________
Merlin's Delphi Forge
Delphi and Kylix news, FAQ, downloads, links, forums and more.
Accepting uploads and submissions.
http://www.delphifaq.net/
________________________________________________________________________
6. Delphi on the Net
By Dave Murray <irongut @ vodafone.net>
Components, Libraries and Utilities
===================================
Shareware / Commercial
----------------------
* LMD SearchPack 2.0 - by LMD Innovative (EUR 39)
LMD SearchPack includes 3 controls for integrating advanced text
search capabilities into your projects including support of AND, OR,
NEAR and NOT operators. Full source code and extensive demo projects
included. http://www.lmdinnovative.com/products/vcl/lmdsearchpack/
* EurekaLog v4.2 - by Fabio Dell'Aria (Std $24, Pro $49, Ent $99)
Gives your application the ability to catch every exception, generate
a detailed log and send it via email. Integrated with Delphi 3 - 7, a
single rebuild adds EurekaLog to your app. NEW: save modified files on
exception; detailed Log when the application freezes; customizable
email for every exception; speed and stability improvements.
http://www.eurekalog.com/bannerclick.php?id=15
Freeware
--------
* WinDowse v5.1 - by Greatis Software (free for non-commercial use)
Unique windows analyzer, best Borland's WinSight replacement. Greatis
WinDowse is an extremely convenient tool for obtaining necessary
technical information about any window. Place a mouse cursor on a
window, and WinDowse will show all parameters of the window and window
class. Full Delphi 3-7 source code available after 100 Euro donation.
http://www.greatis.com/windowse.htm
* Inno Setup v4.0.8 - by JR Software (with source)
A free installer for Windows that rivals commercial installers in
features and stability. Features include: all 32-bit Windows versions;
create a single EXE or disk spanning; standard interface; customizable
setup types; complete uninstall capabilities; zip / bzip2 compression;
create shortcuts, registry + .INI entries; silent install / uninstall;
register DLL, OCX and type libraries; install fonts; Pascal Script.
http://www.jrsoftware.org/isinfo.php
* TPages v1.2 - by Angus Johnson (with source)
Visual component for simple, non-data-aware reports. Features include:
text wrapped between margins, in columns or at specific offsets;
multiple alignment options; multi-line page headers, footers and
column headers; angled text; bitmaps, lines, boxes and arrows; page
numbering; prevent blocks of text spanning across pages.
http://www.users.on.net/johnson/delphi/
Delphi and Borland Product Updates
----------------------------------
* Fixes for Kylix 3 Issues on Newer Distros (updated) - Andrés Colubri
Kylix 3 (particularly C++) on newer Linux distros (eg. RedHat 8+,
Madrake 9+, SuSE 8.2) has a number of bugs: compilation errors with
STL, unresolved references when linking, installer and IDE hangs, etc.
This package contains a collection of fixes to address these issues.
http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=20136
Articles, Tips and Tricks
=========================
* Come learn about Octane! Sneak peeks around the world! - by A Ohlsson
First Octane sighting at Entwickler Konferenz in Frankfurt, Germany.
http://bdn.borland.com/article/0,1410,30387,00.html
* Using D7 to Consume Web Services and Transform XML - by Anders Ohlsson
In this BDNtv episode, Anders shows how you can consume web services
that return XML data. Anders uses Delphi 7 Enterprise to create a
simple application that consumes an XML web service, transforms the
result and displays custom picked data in a regular DBGrid.
Format(s): Flash, Duration: 9:34.
http://community.borland.com/article/0,1410,30379,00.html
* Customizing the DBNavigator
Enhancing the TDBNavigator component with modified graphics (glyphs),
custom button captions, and more. Exposing the OnMouseUp/Down event
for every button.
http://delphi.about.com/library/weekly/aa090203a.htm
* Accessing and managing MS Excel sheets with Delphi - by Zarko Gajic
How to retrieve, display and edit Microsoft Excel spreadsheets with
ADO (dbGO) and Delphi. This step-by-step article describes how to
connect to Excel, retrieve sheet data, and enable editing of data
(using the DBGrid). You'll also find a list of most common errors (and
how to deal with them) that might pop up in the process.
http://delphi.about.com/library/weekly/aa090903a.htm
* Delphi History: from Pascal to Octane - by Zarko Gajic
Concise descriptions of Delphi's versions and its history, along with
a brief list of features and notes. Find out how Delphi evolved from
Pascal to a RAD tool that can help you solve development problems not
only for Windows but also for Linux and .NET.
http://delphi.about.com/cs/azindex/a/dhistory.htm
* Drop Down List Inside a DBGrid: Part 1 - by Zarko Gajic
Here's how to place a drop down pick list into a DBGrid. Create
visually more attractive user interfaces for editing lookup fields
inside a DBGrid - using the PickList property of a DBGrid column.
http://delphi.about.com/library/weekly/aa092703a.htm
* How to Darken or Lighten TColor?
http://www.swissdelphicenter.ch/en/showcode.php?id=1411
* How to execute a Javascript function in a Webbrowser / IE Document?
http://www.swissdelphicenter.ch/en/showcode.php?id=1732
* How to display the items in a listview control as a group? (WinXP)
http://www.swissdelphicenter.ch/en/showcode.php?id=1782
* How to detect if an Application is running within VMware?
http://www.swissdelphicenter.ch/en/showcode.php?id=1819
* How to mix two colors using transparency coefficient?
http://www.swissdelphicenter.ch/en/showcode.php?id=1832
* THvHQuery for exporting query to CSV file - by Henk van Hoek
Export a query to a Comma Separated CSV File.
http://www.delphi3000.com/articles/article_3763.asp
* TEdit and EConvertError - by Andrew Kennaugh
Checking TEdit for StrToFloat using OnKeyPress not OnChange.
http://www.delphi3000.com/articles/article_3765.asp
* Inline Assembler in Delphi (I): Introduction - by Ernesto De Spirito
Reprinted from this newsletter, Ernesto's Assembler tutorial.
http://www.delphi3000.com/articles/article_3766.asp
* Inline Assembler in Delphi (II): ANSI strings - by Ernesto De Spirito
http://www.delphi3000.com/articles/article_3767.asp
* Inline Assembler in Delphi (III): Static Arrays - Ernesto De Spirito
http://www.delphi3000.com/articles/article_3768.asp
* Inline Assembler in Delphi (IV): Records - by Ernesto De Spirito
http://www.delphi3000.com/articles/article_3769.asp
* Inline Assembler in Delphi (V): Objects - by Ernesto De Spirito
http://www.delphi3000.com/articles/article_3770.asp
* Inline Assembler in Delphi (VI): Calling External Procedures
- by Ernesto De Spirito
http://www.delphi3000.com/articles/article_3771.asp
* Inline Assembler in Delphi (VII): 128-bit Integer Arithmetic
- by Ernesto De Spirito
http://www.delphi3000.com/articles/article_3772.asp
* Playing Sounds Thru The Built-In PC Speaker - by Ernesto De Spirito
Using inline assembler to play sounds with the built-in PC speaker.
http://www.delphi3000.com/article.asp?id=3773
* Determining if a Logical Drive Exists - by Ernesto De Spirito
How to know if there is a drive assigned to a letter.
http://www.delphi3000.com/articles/article_3774.asp
* Using TList's and Pointers in delphi (Part II) - by Stewart Moss
Demonstration of how to create records on a TList object.
http://www.delphi3000.com/articles/article_3775.asp
* Adding HTML Resources to DLL/EXE that IE can Reference - Matt Harrison
Creating an RC file to store HTML and Images as resources that works
with IE's res:// format.
http://www.delphi3000.com/articles/article_3776.asp
* Horizontal Modularization - by Hang Liu
This article introduces a modular approach to building large
applications.
http://www.delphi3000.com/articles/article_3777.asp
* Borland DataSnap vs Microsof ADO.NET - by Pablo Reyes
A comparison between the tools provided by these technologies for
building data aware applications.
http://www.delphi3000.com/articles/article_3778.asp
* Simple Winsock Component for Console App - by J3N7iL Jones
How can I create a TCP/IP internet connection in a console application
using winsock?
http://www.delphi3000.com/articles/article_3779.asp
* PageControl Without Border - by Tommy Andersen
http://www.delphi3000.com/articles/article_3783.asp
* Adding new Standard Actions - by Andreas Schmidt
http://www.delphi3000.com/articles/article_3784.asp
* Create a Sizeable Dialog - by Terrance Hui
How to create a sizable dialog (with sizegrip) without using any 3rd
party components.
http://www.delphi3000.com/articles/article_3785.asp
* Selecting Files - by Teun Spaans
In which ways can you let your user choose a file or directory?
http://www.delphi3000.com/articles/article_3786.asp
* Debugging Tricks - by Andreas Schmidt
How to read the content of a TStrings in the integrated debugger.
http://www.delphi3000.com/articles/article_3787.asp
Tutorials and Training
======================
* BorCon 2003 to be be held in San Jose, California November 1-5, 2003
http://info.borland.com/conf2003/
Other Links
===========
* Public Beta: QualityCentral Java Client - by John Kaster
Use a smart client for Borland QualityCentral from wherever you can
run JDK 1.4.x.
http://community.borland.com/article/0,1410,30348,00.html
* San Francisco East Bay Delphi User Group
Our goal is to connect the Delphi developers in the Bay Area. We meet
the 1st Wednesday of every month and have great speakers and sessions.
We organize Delphi events with the help of eBig - the East Bay IT
Group (www.ebig.org). The group will explore Delphi and how Borland's
Delphi 7-8 Studio provides a migration path to Microsoft .NET for
developers as well as Delphi and Linux (Kylix).
http://www.ebig.org/sig/sig.aspx?SIGid=20
News
====
* Altova XMLSPY to be Included in Borland Development Tools
Special Edition of Altova XMLSPY Available in Borland Delphi Studio,
C++ Builder, and C# Builder for the Microsoft .NET Framework.
http://www.altova.com/press/2003-08-28_borland.pdf
________________________________________________________________________
Vote for the Pascal Newsletter in The Delphi Top 200!
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________
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=p49
________________________________________________________________________
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.
________________________________________________________________________
Main page: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Main page: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Group home page: http://groups.yahoo.com/group/pascal-newsletter/
Subscribe/join: pascal-newsletter-subscribe@yahoogroups.com
Unsubscribe/leave: pascal-newsletter-unsubscribe@yahoogroups.com
Problems with your subscription? eds2008 @ latiumsoftware.com
________________________________________________________________________
Latium Software http://www.latiumsoftware.com/en/index.php
Copyright (c) 2003 by Ernesto De Spirito. All rights reserved.
________________________________________________________________________
|