Pascal Newsletter #45
The full source code examples of this issue are available for download.
![]() |
![]() |
Pascal Newsletter #45 - 11-MAR-2003 Contents 1. A few words from the editor 2. Advanced debug manager (exception handler) How to implement a Debug class that shows unit name, function name and line number of an exception. 3. Intercepting Windows messages in non-visual components How a non-windowed component can receive messages from Windows 4. Associate your program with file extensions How to make file associations to your executable 5. Inline Assembler in Delphi (VII) - 128-bit integer arithmetic (1) 6. Forums / mailing lists 7. Delphi on the Net - Components, Libraries and Utilities · Shareware/Commercial · Freeware · Delphi updates - Articles, Tips and Tricks · Kylix, CLX and Linux - Tutorials - Other Links - News ________________________________________________________________________ 1. A few words from the editor I'd like to thank Olivier Rogier, Peter Johnson, and Igor Siticov for contributing articles for this issue, and I'm glad to give the prizes for this issue to the first two: * Olivier Rogier (Advanced debug manager (exception handler)) · SDL Component Suite 7.0 - by Software Development Lohninger ($99) The SDL Component Suite provides a wide range of components for science and engineering, e.g. math, statistics, chemistry, charts, data visualization, Fourier transform (FFT), 3D plots, geographic maps, curve fitting, etc. Available for Delphi 3-7 and BCB 4-6. http://www.lohninger.com/sdlindex.html * Peter Johnson (Intercepting Windows messages in non-visual components) · LMD DesignPack - by LMD Innovative - Shareware (EUR 59) Five components for adding design features to your applications (an Object Inspector clone, a form designer and diagram based controls), with full source code and extensive demo projects demonstrating advanced features - even a report designer is basically included! http://www.ceberus.com/lmd/products/index.php3#P4 For the next issue, we have available the following prizes for two of 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/ * LMD StoragePack - by LMD Innovative - Shareware (EUR 59) Eight components for saving/restoring of configuration data (e.g. at design time, via extended Property Selection dialog) to/from the Windows Eegistry or Ini-, XML- and binary files, being easy to switch between these formats. Full source code and demo projects included. http://www.ceberus.com/lmd/products/index.php3#P9 If you use Delphi 6 or 7, don't forget to check the Delphi Updates in the Delphi on the Net section of this newsletter. By the way, Borland is conducting the Delphi Developer Survey 2003 and the BDN Survey 2003. You'll find the links under the title Other Links in the Delphi on the Net section. I hope you enjoy this issue. Regards, Ernesto De Spirito eds2004 @ latiumsoftware.com __________________ Collaborated in this issue: Dave Murray ________________________________________________________________________ Greatis Runtime Fusion includes Form Designer Pro ($ 49.95) and Object Inspector Pro ($ 49.95), two flagship Delphi-related products of Greatis Software, and costs $89.90 - Save $10 and get additional demos. Let the user design forms at runtime. >>>>>>> http://www.greatis.com/runtime.htm ________________________________________________________________________ 2. Advanced debug manager (exception handler) How to implement a Debug class that shows unit name, function name and line number of an exception. By Olivier Rogier <software @ urimont.com> Software Engineering - Ingénierie Logicielle http://www.urimont.com Read the file file_id.diz in the XAM folder of the zip archive attached for instructions to install eXpress Application Manager (XAM) for Delphi 5-7. The requirement is to enable detailed map file generation in the Project Options' Linker tab. DEBUG_MODE is a boolean constant that indicates if the Debug object is activate by default at startup. It can be modified by the command-line parameters /debug and /nodebug. TObjectInfos is used for getting class instance information like name, parent(s), owner(s). TMapFile is used for getting exception information: unit name, procedure name and line number. IDebug is an interface implemented by TDebug. The function GetDebug returns an IDebug pointer referring to a TDebug instance created in the initialization section and destroyed in the finalization section of the unit. The user can't destroy it or create more instances. The user can set Before and After exception event callbacks and set the activation state. ShowException is used by the internal exception handler and can be used by the user. A beautiful exception form and a log file can be implemented. ________________________________________________________________________ How would you rate the newsletter? Rate the newsletter in the Top 200 Delphi ranking! http://top200.jazarsoft.com/delphi/rank.php3?id=latium ________________________________________________________________________ 3. Intercepting Windows messages in non-visual components How a non-windowed component can receive messages from Windows By Peter Johnson, Copyright (c) 2003 <delphidabbler @ contactbox.co.uk> - http://www.delphidabbler.com/ Sometimes we need a non-windowed component (i.e. one that isn't derived from TWinControl) to receive Windows messages - but non- windowed components don't have window handles. For example suppose we are developing a non-visual component that registers our application as a clipboard viewer so the application can respond to changes in the clipboard (see http://www.delphi3000.com/articles/article_575.asp for how to do this). To get information about clipboard changes our component needs to receive messages from Windows. The Delphi library function AllocateHWnd is used to create a hidden window for us and the related DeallocateHWnd disposes of the window when we've finished with it. The hidden window needs a window procedure. We can use a method of our component class to provide the window procedure. AllocateHWnd takes a reference to the method as parameter - it takes care of the problem of registering the method as a window procedure for us. In the method we handle the messages we are interested in and hand the rest off to Windows using the DefWindowProc API call. The following code gives the skeleton of how to use AllocateHWnd. First, here's the class declaration from the interface section of code: type // Our class derived from TComponent // (or another ancestor class) TMyClass = class(TComponent) private FHWnd: HWND; // Field to store the window handle ... protected procedure WndMethod(var Msg: TMessage); virtual; // The window proc - called by Windows to handle messages ... public constructor Create(AOwner: TComponent); override; // Here we create the window handle destructor Destroy; override; // Here we free the window handle ... end; And here are the implementation details: TMyClass.Create(AOwner: TComponent); begin inherited Create(AOwner); ... // Create the window FHWnd := AllocateHWnd(WndMethod); ... end; TMyClass.Destroy; begin ... // Destroy the window DeallocateHWnd(FHWnd); ... inherited Destroy; end; TMyClass.WndMethod(var Msg : TMessage); var Handled: Boolean; begin // Assume we handle the message Handled := True; case Msg.Msg of WM_SOMETHING: DoSomething; // Code to handle a message WM_SOMETHINGELSE: DoSomethingElse; // Code to handle another message ... else // We didn't handle the message Handled := False; end; if Handled then // We handled the message - record it in message result Msg.Result := 0 else // We didn't handle the message // pass to DefWindowProc and record the result Msg.Result := DefWindowProc(FHWnd, Msg.Msg, Msg.WParam, Msg.LParam); end; Of course, we could just use the Windows API to create a window the hard way and provide a window procedure. But it is more difficult to use a method (rather than a simple procedure) as a window procedure if we do it this way. The clever features about AllocateHWnd are that (a) it creates the hidden window for us and (b) it allows us to use a method, rather than a simple procedure as the window procedure -- and a method is more useful since it has access to the private data of the class. An example clipboard viewer component (cbview) is attached to this article. __________________ Peter Johnson is a hobbyist programmer living in West Wales (UK) who dabbles in Delphi. He maintains the DelphiDabbler website (http://www.delphidabbler.com/) where his articles and freeware Delphi applications and components are published. ________________________________________________________________________ When was the last time you voted for the Pascal Newsletter? Please support this initiative voting for us in The Programming Top 100! http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium ________________________________________________________________________ 4. Associate your program with file extensions How to make file associations to your executable By Igor Siticov SiComponents: http://www.sicomponents.com How can I associate my file extension to my application? For creating file associations you should make some registry changes and inform Windows Explorer about your changes. For launching your program as default for all unregistered file types just associate it to the "*" file type. The following unit includes the realization of a function for creating a file association. See the comments in the source code for details. unit utils; interface uses Registry, ShlObj, SysUtils, Windows; procedure RegisterFileType(cMyExt, cMyFileType, cMyDescription, ExeName: string; IcoIndex: integer; DoUpdate: boolean = false); implementation procedure RegisterFileType(cMyExt, cMyFileType, cMyDescription, ExeName: string; IcoIndex: integer; DoUpdate: boolean = false); var Reg: TRegistry; begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_CLASSES_ROOT; // 1) Assign the extension to the file type, // creating the extension if it doesn't exist // Open or create the key HKCR\<cMyExt> Reg.OpenKey(cMyExt, True); // HKCR\.<cMyExt>\(Default)="<cMyFileType>" Reg.WriteString('', cMyFileType); Reg.CloseKey; // 2) Assign the description of of the file type, // creating the file type if it doesn't exist // Open or create the key HKCR\<cMyFileType> Reg.OpenKey(cMyFileType, True); // HKCR\<cMyFileType>\(Default)="<cMyDescription>" Reg.WriteString('', cMyDescription); Reg.CloseKey; // Now write the default icon for my file type // 3) Assign the icon index for the file type, // creating the corresponding key if it doesn't exist // Open or create the key HKCR\<cMyFileType>\DefaultIcon Reg.OpenKey(cMyFileType + '\DefaultIcon', True); // HKCR\<cMyFileType>\DefaultIcon\ // (Default)="<cExeName>,<IcoIndex>" Reg.WriteString('', ExeName + ',' + IntToStr(IcoIndex)); Reg.CloseKey; // 4) Write the text for the a Open action in Windows Explorer, // creating the action if it doesn't exist // Open or create the key HKCR\<cMyFileType>\Shell\Open Reg.OpenKey(cMyFileType + '\Shell\Open', True); // HKCR\<cMyFileType>\Shell\Open\(Default)="&Open" Reg.WriteString('', '&Open'); Reg.CloseKey; // 5) Assign the application that will be used to execute the // action, creating the corresponding key if it doesn't exist // Open or create the key HKCR\<cMyFileType>\Shell\Open\Command Reg.OpenKey(cMyFileType + '\Shell\Open\Command', True); // HKCR\<cMyFileType>\Shell\Open\Command\ // (Default)=""<cExeName>" "%1"" // Your application must scan the command line parameters // to see what file was passed to it. Reg.WriteString('', '"' + ExeName + '" "%1"'); Reg.CloseKey; // Finally, if we want Windows Explorer to realize we added // our file type, we do it by using the SHChangeNotify API. if DoUpdate then SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil); finally Reg.Free; end; end; end. __________________ Igor Siticov is the author of TsiLang Components Suite (a full set of professional components for building elegant, useful and user friendly multilingual applications in two minutes) and Resource Builder (a full featured RC script visual editor that can be a cool replacement for the standard Borland Image Editor and Borland Resource WorkShop for creating and editing resource files), by SiComponents: www.sicomponents.com ________________________________________________________________________ Become a member of our Delphi forum/mailing list for intermediate-level Delphi programmers. It's free! · http://groups.yahoo.com/group/delphi-en ________________________________________________________________________ 5. Inline Assembler in Delphi (VII) - 128-bit integer arithmetic (1) By Ernesto De Spirito Introduction ============ With 32 bits we can represent 2^32 different numbers, i.e. 4294967296 (~4 billion) different numbers, like signed integers from -2147483648 to +2147483647 or unsigned integers from 0 to 4294967295 (types Longint and Longword respectively). That's enough for many purposes, like for example holding a position of a byte within a 4GB file, but sometimes we need more than that, and there we have TLargeInteger (Windows unit) and Int64 (since Delphi 4) to represent 64-bit integers that can have 2^64 different values, i.e. 18446744073709551616 (~18 sixtillons) values, from -9223372036854775808 to +9223372036854775807 (~9 sixtillons, 17-18 decimal digits). That number of digits is really more than enough for me, and right now I really can't figure any practical use for more than that. Hey, not even Bill Gates counts his money in sixtillons! ;) But from time to time I see someone in a forum asking for more digits than what the Int64 offers... Anyway, whether useful or completely useless for a practical purpose, we'll see the implementation of many procedures and functions designed to work with 128-bit integers, that will serve for the purpose of showing examples of the basic assembler instructions. These "large integers", "big integers" or "huge integers" can hold 2^128 different values (38-39 decimal digits). Representation of the huge integer ================================== I called the new type Hugeint, but for example Bigint (big integer) or Int128 could have been good names. Largeint (large integer) could be confused with the type in the Windows.pas unit which refers to a 64-bit integer. When it comes to the representation of the new type, there also many ways to do it. I decided the most simple is representing it as an array of four 32-bit integers: type Hugeint: packed array [0..3] of longword; I also decided to use the little-endian format since it's the standard in the Intel architecture, and this means that the first element of the array (lowest address) will hold the low-order (least-significant) 32 bits of the large integer, and the last element of the array (highest address) will hold the high-order (most-significant) 32 bits of the large integer. This is how the numbers 5 and 5000000000 ($12A05F200) would be represented: +---- Low-order 32 bits | v +-------------+-------------+-------------+-------------+ | $00000005 | $00000000 | $00000000 | $00000000 | = 5 +-------------+-------------+-------------+-------------+ 0 1 2 3 +-------------+-------------+-------------+-------------+ | $2A05F200 | $00000001 | $00000000 | $00000000 | = 5000000000 +-------------+-------------+-------------+-------------+ $12A05F200 ^ | High-order 32 bits ----+ Integers themselves are also stored in little-endian format (low-order byte first). If we see the byte representation of the numbers in a memory dump, it would look like this (byte values are represented in hexadecimal notation): $00000005 +-------------+-------------+-------------+-------------+ | 05 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | = 5 +-------------+-------------+-------------+-------------+ 0 1 2 3 +-------------+-------------+-------------+-------------+ | 00 F2 05 2A | 01 00 00 00 | 00 00 00 00 | 00 00 00 00 | = 5000000000 +-------------+-------------+-------------+-------------+ $12A05F200 $2A05F200 $00000001 However, for almost all operations we can make abstraction of the byte order and consider the 32-bit integers as atomic units, since the byte order is handled transparently. A few useful instructions ========================= Before we begin, let's see some useful instructions that we might use in this article (mainly in the continuation of this part), but first allow me to say that it isn't the purpose of this article to actually teach you assembler. All I can do in this limited space is just showing you examples of some instructions. For reference material, I recommend you these links: * Intel 80386 Reference Programmer's Manual An HTML version of this Intel manual. The pseudo-code helps explain the instructions and their effects on the flags. Excellent. http://people.freebsd.org/~jhb/386htm/toc.htm There are some broken links, but the pages are there. Try finding them in the directory index: http://people.freebsd.org/~jhb/386htm/ * iAPx86 - Norton Guide Not as much explicative as the above document, but contains all the instructions from 8086 to Pentium and Pentium Pro, with size and timing information not included in the above document. http://www.clipx.net/ng/iapx86/index.php * The IA-32 Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference PDF Manual describing the instructions for the IA-32 processors (Pentium, Pentium Pro, Pentium II, Pentium III, Pentium 4, and Xeon). Includes pseudo-code to explain the instructions and how they affect the flags in the flags register. http://www.intel.com/design/pentium4/manuals/245471.htm * Optimization - How to optimize for the Pentium family of microprocessors Excellent optimization guide written by Agner Fog http://fatphil.org/x86/pentopt/index.html - Optimizations for Intel's 32-Bit Processors Another excellent optimization guide. http://x86.ddj.com/ftp/manuals/686/optimgd.pdf OK, now let's get to the instructions. Reference: Z/ZF: Zero Flag S/SF: Sign Flag C/CF: Carry Flag P/PF: Parity Flag A/AF: Auxiliary Flag s: sign bit (high-order bit) o: odd bit (low-order bit) x: bit value 0: namely, the value 0 1: namely, the value 1 r: bit is reversed from previous value u: bit is unchanged from previous value XX: unknown value (register, immediate, or memory reference) In the examples it should be assumed the value of AL previous to each operation is sxxxxxxo (sign bit, 6 unknown bits, and odd bit). Here are some instructions to begin: SHL al,1 AL := xxxxxxo0 CF := s Shift left SAL al,1 AL := xxxxxxo0 CF := s Synonym for SHL SHR al,1 AL := 0sxxxxxx CF := o Shift right SAR al,1 AL := ssxxxxxx CF := o Shift arithmetic right SAR al,7 AL := ssssssss CF := x This extends the sign bit ROL al,1 AL := xxxxxxos CF := s Rotate left ROR al,1 AL := osxxxxxx CF := o Rotate right RCL al,1 AL := xxxxxxoC CF := s Rotate thru carry left RCR al,1 AL := Csxxxxxx CF := o Rotate thru carry right AND al,al AL := uuuuuuuu CF := 0 Sets flags (see below) AND al,-1 AL := uuuuuuuu CF := 0 -1 = $FF = 1111111 Sets flags (see below) AND al,$01 AL := 0000000u CF := 0 $01 = 00000001 AND al,$80 AL := u0000000 CF := 0 $80 = 10000000 AND al,$5A AL := 0u0uu0u0 CF := 0 $5A = 01011010 AND al,0 AL := 00000000 CF := 0 XOR AL,AL or MOV AL,0 are better TEST AL,XX AL := uuuuuuuu TEST is like AND, but the result doesn't get stored in the destination. The result is used to set flags (see below). TEST AL,-1 It's usually better than AND AL,-1 and OR AL,AL because it doesn't write to AL, which allows certain optimizations in some cases. OR al,al AL := uuuuuuuu CF := 0 Sets flags (see below) OR al,$01 AL := uuuuuuu1 CF := 0 $01 = 00000001 OR al,$80 AL := 1uuuuuuu CF := 0 $80 = 10000000 OR al,$5A AL := u1u11u1u CF := 0 $5A = 01011010 OR al,-1 AL := 11111111 CF := 0 Same as MOV AL,1 XOR al,al AL := 0 CF := 0 Use MOV AL,0 to preserve flags XOR al,$5A AL := ururruru CF := 0 $5A = 01011010 XOR al,-1 AL := rrrrrrrr CF := 0 Same as NOT AL Except for the rotation instructions (ROL, RCL, ROR, and RCR) all of the above set SF, ZF and PF based on the result of the operation: SF = value of the high-order bit of the result ZF = 1 ("set") if the result is zero, 0 ("cleared") otherwise PF = 1 ("set") if the low-order byte of the result contains an even number of 1 bits, 0 ("cleared") otherwise Let's see more instructions: STC CF := 1 Set Carry Flag CLC CF := 0 Clear Carry Flag CMC CF := r Complement Carry Flag LAHF AH := SZxAxPxC SAHF Assuming AH is SZxAxPxC: ZF := S; ZF := Z; AF := A; PF := P; CF := C SETc AL AL := CF Set if carry SETs AL AL := SF Set if sign SETz AL AL := ZF Set if zero SETe AL AL := ZF Set if equal (synonym of SETZ) SETp AL AL := PF Set if parity SETpe AL AL := PF Set if parity even (synonym of SETP) SETo AL AL := OF Set if overflow SETnc AL AL := NOT CF Set if not carry SETns AL AL := NOT SF Set if not sign SETnz AL AL := NOT ZF Set if not zero SETne AL AL := NOT ZF Set if not equal (synonym of SETNZ) SETnp AL AL := NOT PF Set if not parity SETpo AL AL := NOT PF Set if parity odd (synonym of SETNP) SETno AL AL := NOT OF Set if not overflow SETa (or SETNbe), SETae (or SETnb), SETb (or SETnae), SETbe (SETna), SETg (or SETNle), SETge (or SETnl), SETl (or SETnge), and SETle (SETng) set the destination byte to 1 or 0 depending on whether the specified condition is met or not. ADD AL,XX AL := AL+XX CF := 1 if operation generated a carry 0 otherwise SUB AL,XX AL := AL-XX CF := 1 if operation needed a borrow 0 otherwise SUB AL,0 AL := uuuuuuuu Set flags based on AL SUB AL,AL AL := 0 Same as XOR AL,AL or MOV AL,0 CMP AL,XX CMP is like SUB, but the result doesn't get stored in the destination. The operation simply set the flags ADC AL,XX AL := AL+XX+C CF := 1 if operation generated a carry 0 otherwise SBB AL,XX AL := AL-C-XX CF := 1 if operation needed a borrow 0 otherwise NEG AL AL := -AL CF := 1 if previous AL <> 0 NOT AL; INC AL is the same NOT AL AL := rrrrrrrr CF := u XOR AL,-1 is the same Conversion functions ==================== These functions will help us understand the representation of these huge integers. Longword to Hugeint ------------------- Let's start by converting a Longword into a huge integer. The lowest 32 bits of the result will be the 32 bits of the parameter and the higher 96 bits will be zero. function UToHugeint(const x: Longword): Hugeint; overload; // Result := Hugeint(x); // Parameters: EAX = x; EDX = @Result; asm xor ecx, ecx // ECX := 0; mov [edx+_0_], eax // Result[0] := x; mov [edx+_1_], ecx // Result[1] := 0; mov [edx+_2_], ecx // Result[2] := 0; mov [edx+_3_], ecx // Result[3] := 0; end; Comments: * "_0_", "_1_", "_2_", and "_3_"? What are these? They are constants that represent the offsets of the four elements of the array, allowing us to write cleaner code. const _0_ = 0; _1_ = 4; _2_ = 8; _3_ = 12; Longint to Hugeint ------------------ The lowest 32 bits of the result will be the 32 bits of the parameter. If the number is positive or zero, then the higher 96 bits will be 0, but if the number is negative, the higher 96 bits will be 1. It might seem like we need to make a comparison or test the sign and then to perform a conditional jump based on the result: function ToHugeint(const x: Longint): Hugeint; overload; // Result := Hugeint(x); // Parameters: EAX = x; EDX = @Result; asm or eax, eax // EAX := EAX or EAX; // EAX remains unchanged // Side effect: SF (Sign Flag) := EAX < 0; mov ecx, 0 // ECX := 0; jns @@not_negative // if not SF then goto @@not_negative; dec ecx // ECX := ECX - 1; // 0 - 1 = -1 = $FFFFFFFF @@not_negative: mov [edx+_0_], eax // Result[0] := x; mov [edx+_1_], ecx // Result[1] := ECX; // 0 or $FFFFFFFF mov [edx+_2_], ecx // Result[2] := ECX; // 0 or $FFFFFFFF mov [edx+_3_], ecx // Result[3] := ECX; // 0 or $FFFFFFFF end; Comments: * Notice the use of "MOV ECX, 0" instead of "XOR ECX, ECX" to avoid changing the state of the Sign Flag (SF) set in the preceding instruction (OR) and then used in the conditional jump that appears in the following instruction (JNS). Of course we could have changed the order of the operations for this to be unnecessary... * Instead of: or eax, eax jns @@not_negative the following pairs of instructions would achieve the same: * and eax, eax // EAX keeps the value, but SF gets the sign jns @@not_negative // if SF = 0 then goto @@not_negative * test eax, $80000000 // result will be zero only if sign bit is 0 jz @@not_negative // if ZF then goto @@not_negative * test eax, $87654321 // any value with bit 31 (sign bit) set jns @@not_negative // if SF = 0 then goto @@not_negative * cmp eax, 0 // compares eax with 0 jge @@not_negative // if greater or equal then goto @@not_negative * Notice the use of "DEC ECX" to turn the value of ECX from $00000000 to $FFFFFFFF (by decrementing the value of the register). "NOT ECX" would have accomplished the same thing (by inverting the bits), at the same speed, and taking the same number of bytes to code the instruction, but NOT isn't a pairable instruction while DEC is. For this reason NOT is usually avoided and substituted as follows: - If you know beforehand that the previous value is 0, use DEC Dest - If you know beforehand that the previous value is 1, use INC Dest - If you don't know what the previous value is, use XOR Dest, -1 * Also notice in the order of the instructions that we never used a register that was set in the immediately previous instruction. This is one of the conditions for pairing to occur. You'll find more information about instruction pairing in the documents about optimization that we recommended above. We can simplify the function thanks to the CDQ instruction which extends the sign of EAX into EDX. This is basically how CDQ works: if EAX >= 0 then EDX := $0 else EDX := $FFFFFFFF; Here's a smaller and simpler implementation using CDQ: function ToHugeint(const x: Longint): Hugeint; overload; // Result := Hugeint(x); // Parameters: EAX = x; EDX = @Result; asm mov ecx, edx // ECX := @Result; cdq // EDX := IIF(x>=0, 0, $FFFFFFFF); mov [ecx+_0_], eax // Result[0] := x; mov [ecx+_1_], edx // Result[1] := EDX; // 0 or $FFFFFFFF mov [ecx+_2_], edx // Result[2] := EDX; // 0 or $FFFFFFFF mov [ecx+_3_], edx // Result[3] := EDX; // 0 or $FFFFFFFF end; CDQ is usually replaced using MOV and SAR, which offer the advantage that the source doesn't have to be EAX and the destination doesn't have to be in EDX (plus they are pairable instructions). Let's see an example: function ToHugeint(const x: Longint): Hugeint; overload; // Result := Hugeint(x); // Parameters: EAX = x; EDX = @Result; asm mov ecx, eax // ECX := x; sar ecx, 31 // ECX := IIF(x>=0, 0, $FFFFFFFF); mov [edx+_0_], eax // Result[0] := x; mov [edx+_1_], ecx // Result[1] := EDX; // 0 or $FFFFFFFF mov [edx+_2_], ecx // Result[2] := EDX; // 0 or $FFFFFFFF mov [edx+_3_], ecx // Result[3] := EDX; // 0 or $FFFFFFFF end; Hugeint to Longint ------------------ A Hugeint can be converted to a Longint by simply taking the low-order 32 bits. The high-order 96 digits of the Hugeint should be all 0 or all 1 matching the sign bit of would be the result (bit 31) for the Hugeint value to be in the range of a Longint, but the function doesn't check for that and performs the conversion blindly (in the same way that a Longint is converted to a Shortint, for example). function ToLongint(const x: Hugeint): Longint; overload; // Result := Longint(x); // No exception is raised if the value is not within // range (high-order 96 bits are discarded). // Parameters: EAX = @x; asm mov eax, [eax+_0_] // Result := x[0]; end; Int64 to Hugeint ---------------- Int64 parameters are passed on the stack, so functions with an Int64 parameter will automatically create a stack frame. The lowest 64 bits of the result will be the 64 bits of the parameter, and the higher 64 bits of the result will extend the sign bit of the high-order integer that makes up the int64 value. {$IFDEF DELPHI4} function ToHugeint(const x: Int64): Hugeint; overload; // Result := Hugeint(x); // Parameters: x on the stack; EAX = @Result; asm mov edx, dword[x+_0_] // EDX := x[0]; mov ecx, dword[x+_1_] // ECX := x[1]; mov [eax+_0_], edx // Result[0] := x[0]; mov [eax+_1_], ecx // Result[1] := x[1]; sar ecx, 31 // ECX := IIF(x[1]>=0, 0, $FFFFFFFF); mov [eax+_2_], ecx // Result[2] := ECX; // 0 or $FFFFFFFF mov [eax+_3_], ecx // Result[3] := ECX; // 0 or $FFFFFFFF end; {$ENDIF} Int64 values are stored in little-endian format, so the low-order integer is the first, at offset 0 from the base address of the variable, and the high-order integer is the second, at offset 4 from the base address of the variable. In this case the base address of the variable is EBP+8 (see the first chapter of this series of articles), so the first element is at EBP+8 (EBP+8+0), and the second element is at EBP+12 (EBP+8+4). I could have used EBP+8 and EBP+12 to address the elements, but "x+_0_" and "x+_1_" refer to these addresses more transparently. The "DWORD" size specifier is mandatory since the assembler takes "x+_0_" and "x+_1_" as pointers to 64-bit data (because "x" is considered a pointer to 64-bit data) and doesn't allow to move the referenced value to a 32-bit register. Hugeint to Int64 ---------------- A Hugeint can be converted to an Int64 by simply taking the low-order 64 bits. The high-order 64 digits of the Hugeint should be all 0 or all 1 matching the sign bit of would be the result (bit 31) for the Hugeint value to be in the range of an Int64, but the function doesn't check for that and performs the conversion blindly: {$IFDEF DELPHI4} function ToInt64(const x: Hugeint): Int64; overload; // Result := Int64(x) // No exception is raised if the value is not within // range (high-order 64 bits are discarded). // Parameters: EAX = @x; asm mov edx, [eax+_1_] // EDX := x[1]; mov eax, [eax+_0_] // EAX := x[0]; // Result = EDX:EAX = x[1]:x[0] end; {$ENDIF} Comment: * Int64 return values should be placed in the EDX (high-order 32 bits) and EAX (low-order 32 bits). This is it for now. In future issues we'll see functions to perform logical and mathematical operations with these huge integers. ________________________________________________________________________ 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-7 and C++ Builder 3-6. http://www.jfactivesoft.com/ ________________________________________________________________________ 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://groups.yahoo.com/group/components/ Subscription: http://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 ________________________________________________________________________ Delphi BUGS? Chatch & Log every BUG showing Unit, Class, Method, Line #. http://www.eurekalog.com/bannerclick.php?id=15 ________________________________________________________________________ 7. Delphi on the Net By Dave Murray <irongut @ vodafone.net> Components, Libraries and Utilities =================================== Shareware/Commercial -------------------- * EurekaLog v4.0.4 - by Fabio Dell'Aria (Std $29, 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 Freeware -------- * eXpress Application Manager (XAM) for Delphi (with source code). Don't loose more time with error messages like "Access violation", "Division by zero" or "List index out of bounds"! Find quickly the line of code concerned with the advanced exception manager XAM for Delphi 5, 6 and 7. The XAM Debugger will help you to improve your test phase or your users bug reporting. http://www.urimont.com/index.php?page=delphi&subpage=delphi_xam * InterBase Performance Monitor 1.1 Released InterBase Performance Monitor provides a user-friendly interface for InterBase 7's performance monitoring and administration features. You can easily watch and control who is using resources on your server. http://community.borland.com/article/0,1410,29632,00.html * Audio Components Suite v2.0 - Andrei Borovsky (source) (DELPHI/KYLIX) Components designed to perform different sound-processing tasks. ACS can play sound via the sound card, acquire audio data from different sources such as soundcard, audio CD and so on. Can also read and store audio data in several file formats (including Ogg Vorbis). http://www.mtu-net.ru/aborovsky/ * IdCGIRunner v3.1 - by Serhiy Perevoznyk (with source) Execute CGI scripts using Indy TidHTTPServer. http://users.chello.be/ws36637/ * IdISAPIRunner v3.1 - by Serhiy Perevoznyk (with source) Execute ISAPI modules using Indy TidHTTPServer. http://users.chello.be/ws36637/ * Icarus - Uses List Analyzer for Delphi v1.4.1 - by Peganza Helps Delphi and Borland Pascal developers remove unnecessary units in uses lists. Can also tell which units can be moved from the interface to the implementation uses list. http://www.torry.net/tools/developers/other/icarus.zip * BDEChecker v1.0 - by Nick Moon Performs a number of tests on your machine to check various settings that are known/believed to cause problems with Paradox data tables. http://www.nixsoft.co.uk/bdechecker.html * LinLocalize v1.0 - by Jens Kuhner (with source) (KYLIX) Free translation-tool for multilingual Kylix applications. It extracts the Kylix-resources (resource strings and forms) of elf-files and writes the translated resources back. http://linlocalize.sourceforge.net/ * TurboPower Visual PlanIt v1.03 - by TurboPower (with source) A set of synchronized, data-aware components for adding time, task and contact management capabilities to applications written in Delphi and C++Builder. Get that Outlook look & feel without the hassle. https://sourceforge.net/projects/tpvplanit/ * TurboPower Abbrevia v3.04 - by TurboPower (with source) (DELPHI/KYLIX) A compression toolkit for Delphi, C++Builder and Kylix. It supports PKZIP 4, Microsoft CAB, TAR and gzip formats and the creation of self- extracting archives. It includes visual components that simplify the manipulation of ZIP files. https://sourceforge.net/projects/tpabbrevia/ Delphi Updates -------------- * Update: Bold for Delphi Architect Registered users of purchased versions of Delphi 7 Architect can download Bold for Delphi Architect R4.0-D7. http://community.borland.com/article/0,1410,29798,00.html * Update: IntraWeb and Rave for Delphi 7 Delphi 7 updates for AtoZed IntraWeb and Nevrona Rave Reports are now available to download for registered users of purchased versions of Delphi 7 Pro, Enterprise, and Architect. http://community.borland.com/article/0,1410,29792,00.html * Update: Delphi 6 Runtime Library Update 2 An update for Delphi 6 is now available to download for registered users of purchased versions of Delphi 6. http://community.borland.com/article/0,1410,29791,00.html * Borland Product Companion CDs are online Companion CD submissions are now available for download for: C++Builder 6 Companion CD; Delphi 7 Companion CD, disk 1; Delphi 7 Companion CD, disk 2; InterBase 7 Companion CD; JBuilder 8 Companion CD; Kylix 3 Companion CD. http://community.borland.com/article/0,1410,29797,00.html Articles, Tips and Tricks ========================= * Multi-threaded programming contest winners - by John Kaster Winners have been selected for the multi-threaded programming contest. http://community.borland.com/article/0,1410,29786,00.html * Building a stand-alone Web service with Indy in Delphi 7: Part I - by Serge Dosyukov and Mike Pham Shows how to build a stand-alone Web service using Indy and Delphi 7. http://community.borland.com/article/0,1410,29484,00.html * Building a stand-alone Web service with Indy in Delphi 7: Part II - by Serge Dosyukov and Mike Pham Part 2 demonstrates one technique for creating a single web service that contains more than one TSoapDataModule instance. http://community.borland.com/article/0,1410,29542,00.html * Known Causes of Corruption in InterBase Databases - by Craig Stuntz InterBase is, in general, a very stable database server and corruption is rare. When corruption does occur, then, it is important to determine the cause of the corruption. This article describes circumstances that can cause corruption. http://community.borland.com/article/0,1410,29515,00.html * Monitoring System Shell Changes - by Zarko Gajic Wanna get notified when a file gets created, renamed or deleted on the system? Need to know the exact folder and file name? Let's start monitoring system shell changes! http://delphi.about.com/library/weekly/aa030403a.htm * "Essential .NET" is not for the faint-of-heart - by Barb Seewer http://builder.com.com/article.jhtml?id=u00220030220swr01.htm * Tips for documenting an XML DTD - by William T. Kelly http://builder.com.com/article.jhtml?id=u00420030219WTK01.htm * An Overview of the new XPointer Specification - by Edmond Woychowsky What are the details about the XPointer XML proposal, and how does it compare to XPath? Learn more about this new standard and check out some examples on how to put it to use. http://builder.com.com/article.jhtml?id=u00320030220woy01.htm * How to get the Selected Objects in a TWebbrowser? http://www.swissdelphicenter.ch/en/showcode.php?id=1190 * How to Get Rid Of the Annoying SQL Wait Cursor? http://www.swissdelphicenter.ch/en/showcode.php?id=1305 * How to Explode a String? http://www.swissdelphicenter.ch/en/showcode.php?id=1326 * How to flash the modal window title when user clicks the parent form? http://www.swissdelphicenter.ch/en/showcode.php?id=1393 * How to search a TreeView Item through its Text property? http://www.swissdelphicenter.ch/en/showcode.php?id=1414 * How to hook a function (in your own application)? http://www.swissdelphicenter.ch/en/showcode.php?id=1422 * How to make deleting items in a TListView faster? http://www.swissdelphicenter.ch/en/showcode.php?id=1479 * How to implement flickerless animation of a sprite moving across a background image? http://www.swissdelphicenter.ch/en/showcode.php?id=1491 * How to jump to a certain key in Regedit? http://www.swissdelphicenter.ch/en/showcode.php?id=1542 * How to Draw a line without using the LineTo function? http://www.swissdelphicenter.ch/en/showcode.php?id=1569 * How to show balloon tooltips in my Delphi program? http://www.swissdelphicenter.ch/en/showcode.php?id=1587 * How to popup the system menu at a specified position? http://www.swissdelphicenter.ch/en/showcode.php?id=1594 * How to get paths of the folders in 'My Computer'? http://www.swissdelphicenter.ch/en/showcode.php?id=1598 * Get CPU Speed - by Amir Mosavian http://www.delphi3000.com/articles/article_3552.asp * FEEDBACK: D6+ADO+MS.SS => D6+ADO+Oracle - by Hans Pieters The results of a migration D6+ADO+MS.SS => D6+ADO+Oracle. http://www.delphi3000.com/articles/article_3553.asp * Auto LiveUpdate - by Xiao Smile Auto LiveUpdate your program from an FTP server. http://www.delphi3000.com/articles/article_3556.asp * OnOffBtn - by Pete Coe How to make a custom On/Off button with default Glyphs. http://www.delphi3000.com/articles/article_3557.asp * Event Chain Mechanism II - by Alex Wijoyo Attach and detach many event handlers to an event at runtime. http://www.delphi3000.com/articles/article_3560.asp * Extracting complete list of URL's from the web server - by Sergey S This article describes how to extract a list of all web resources (URL's) from a web server like http://www.borland.com using the Clever Internet Suite components. It can be implemented with any other internet library. http://www.delphi3000.com/articles/article_3561.asp * Using the Google web APIs with Delphi - by Herbert Poltnik http://www.delphi3000.com/articles/article_3563.asp * Writing MS SQL Server Extended Stored Procedures with Delphi - by Berend de Boer http://www.delphi3000.com/articles/article_3564.asp * Using the Affinity Mask in multi-CPU environments - by Kim Sandell When writing applications that are designated to run in multi-CPU environments, it is very useful to be able to control which CPU's the application executes on. By optimizing the CPU usage one can dramatically increase the performance of the application. http://www.delphi3000.com/articles/article_3565.asp * Quick Sort - by Sébastien Charest How to quick sort an array? http://www.delphi3000.com/articles/article_3566.asp * Convert numbers to words - by Abdulaziz Jasser http://www.delphi3000.com/articles/article_3567.asp * Using XML in Delphi applications: Part II - by Sergey Kucherov Implementing XML Parser using Microsoft SAX interface. http://www.delphi3000.com/articles/article_3571.asp * OpenGL I: Hello World - by Eber Irigoyen Base code for your OpenGL Delphi applications. http://www.delphi3000.com/articles/article_3572.asp * mIRC DLL basics - by Gareth Ablett Basic design use and layout of a Delphi DLL for mIRC. http://www.delphi3000.com/articles/article_3573.asp * Sort Order of Internet Explorer Favorites - by Daaron Dwyer You can easily get the list of favorites from the directory, but how can you emulate the same sort order showing in Internet Explorer? http://www.delphi3000.com/articles/article_3574.asp * Shell Programming with Delphi - by Marcel van Brakel Some tricks for using Delphi for shell programming on Windows. http://www.delphi-jedi.org/Jedi%3AVOY_SHELLPROG%3A372530 * ColorMask Lab Report The purpose of this project is to display only the selected bits of a 24-bit color image. Any or all of the 24-bits of each pixel can be masked for display. http://www.efg2.com/Lab/Graphics/Colors/ColorMask/index.htm * Active Directory programming - by Marcel van Brakel Active Directory programming isn't as hard as you thought, this article steps through what you need to do. http://www.delphi-jedi.org/Jedi%3AVOY_ACTIVEDIR%3A372530 * .Net Architecture - by Jon Shemitz Overview of the .Net architecture, presented at BorCon London, 2002. midnightbeach.com/jon/pubs/2002/BorCon.London/dotNetArchitecture.html * PNG Graphics with Delphi and Kylix - by Chris Rorden http://www.psychology.nottingham.ac.uk/staff/cr1/png.html * 3D Controls - by Chris Rorden This article is about controls that you can provide to allow a user to select a viewpoint for a 3D image. It includes source code that demonstrates the Euler Angles, Vector and Roll and ArcBall controls. http://www.psychology.nottingham.ac.uk/staff/cr1/3d.html * Scientific Mathematics - by Chris Rorden Explains the use and benefits of 'Single Instruction, Multiple Data' (SIMD) commands, ie. SSE, SSE2 and 3DNow!. Includes a Delphi app that measures the time to complete a large number of maths operations using either standard or SIMD commands. http://www.psychology.nottingham.ac.uk/staff/cr1/simd.html Kylix, CLX and Linux -------------------- * Kylix Deployment Notes for "Hello World" - by efg Just how hard can it be to deploy a simple CLX application in Linux? http://www.efg2.com/Lab/Library/Kylix/deployment.htm * PNG Graphics with Delphi and Kylix - by Chris Rorden http://www.psychology.nottingham.ac.uk/staff/cr1/png.html * Graphics with Kylix - by Chris Rorden http://www.psychology.nottingham.ac.uk/staff/cr1/kylix.html * CLX and Cursors - by Matthias Thoma CLX supports Bitmaps and Icons, as files and as resources, but misses support for cursors. This article will fill that gap and show how to create QCursors and how to load and use windows cursor resources. http://www.efg2.com/Lab/Library/Kylix/MatthiasThoma/wincur.html * KDE System Tray Applets - by Matthias Thoma An easy way to add common TForms to KDEs system tray area. http://www.efg2.com/Lab/Library/Kylix/MatthiasThoma/KDESystemTray.html * Kylix for Delphi programmers - by Jon Shemitz Presented at BorCon London, October 2002. http://www.midnightbeach.com/jon/pubs/2002/BorCon.London/ KylixForDelphiProgrammers.html Tutorials ========= * Speech Synthesis & Speech Recognition: Overview - by Brian Long Overview of adding speech synthesis and speech recognition capabilities into Delphi applications using the Microsoft Speech API. http://community.borland.com/article/0,1410,29580,00.html * Using SAPI 4 High Level Interfaces - by Brian Long Details of adding speech synthesis and speech recognition capabilities into Delphi applications using the high-level programming interfaces in Microsoft Speech API v4.0 (SAPI 4). http://community.borland.com/article/0,1410,29581,00.html * Using SAPI 4 Low Level Interfaces - by Brian Long Details of adding speech synthesis and speech recognition capabilities into Delphi applications using the low-level programming interfaces in Microsoft Speech API v4.0 (SAPI 4). http://community.borland.com/article/0,1410,29582,00.html * Speech Synthesis & Speech Recognition: Using SAPI 5.1 Details of adding speech synthesis and speech recognition capabilities into Delphi apps using the Microsoft Speech API v5.1 (SAPI 5.1). http://community.borland.com/article/0,1410,29583,00.html * Windows NT Privileges - by Marcel van Brakel This article describes how to discover and set Windows NT privileges from your applications, so you can make better use Windows built-in security capabilities. http://www.thedelphimagazine.com/Samples/1577/1577.htm * Creating an Internet Explorer-style User Interface Part 2 In the February 2003 issue of Hardcore Delphi, Fabio Lucarelli began demonstrating how to build and maintain a user interface that mimics the one in Internet Explorer and Outlook. In this article he continues that task by introducing toolbar customization and chevrons, by using two common controls: the toolbar and the Coolbar control. pinnaclepublishing.com/dd/DDMag.nsf/0/BFBE071686BC1F6A85256CD9007AD663 * NTFS Disk Quotas - by Marcel van Brakel Describes how to set and manage NTFS disk quotas programmatically. http://www.thedelphimagazine.com/samples/1488/1488.htm * File Sharing On Linux - by Primoz Gabrijelcic Explores file locking support on Linux and presents a cross-platform scheme for using the file system for interprocess synchronisation. http://www.thedelphimagazine.com/samples/1481/1481.htm * Interfaces: Off The Beaten Track - by Malcolm Groves Shows how to use interfaces to automatically destroy objects, restore objects to previous states, cut away swathes of try..finally blocks, and deal with memory leaks. http://www.thedelphimagazine.com/samples/1415/1415.htm * Introduction to Design Patterns - by Ader Gonzalez Introduces the concept of Design Patterns through the eyes of a Delphi programmer. http://www.delphi-jedi.org/Jedi%3AVOYPATTERNS * Delphi: Type Safe Programming - by Richard A. Morris A Run-Time Type Information tutorial from the 10th Borland Developer's Conference. Includes a component called the RTTI Explorer which allows us to delve into the innards of Delphi classes. http://www8.pair.com/rmorris/rtti.htm * Upcoming Borland WebEx events - by Anders Ohlsson Feeling lazy today? Want to sit down in your pajamas and learn about the technical details of software development utilizing some of the finest technologies available today? Register for these seminars and participate from the comfort of your own home to learn about: Delphi for .NET, IntraWeb in Delphi, WebServices in Delphi and more. Presented by Alain "Lino" Tadros. http://community.borland.com/article/0,1410,29784,00.html Other Links =========== * Borland Delphi Developer Survey 2003 - by John Kaster Let Borland know what you would like to see in future Delphi releases by taking this survey. Five winners will receive a free Borland RAD Enterprise/Architect software product of their choice. http://community.borland.com/article/0,1410,29822,00.html * 2003 Borland Developer Network (BDN) Survey - by David I Help make sure that Borland continues to provide products, services and support that you count on. Complete this comprehensive survey to help Borland better understand your priorities and better serve your needs going forward. As a small "thank you" for participation, you'll be entered in a drawing for copies of Borland products - each valued at up to $4000. http://whatever.borland.com/bdnsurvey.html * Public beta: Quality Central browser client The public beta of the browser interface to QualityCentral (QC) is now live. This beta of the web client (WC) is focused on functionality, browser compatibility, and ease of use. http://community.borland.com/article/0,1410,29803,00.html * The FirebirdSQL Foundation We are very pleased to announce the formation of "The FirebirdSQL Foundation", a non-profit association with the objectives of supporting and advancing the development of the open source FirebirdSQL relational database engine. http://www.swissdelphicenter.ch/en/shownews.php?id=349 News ==== * Blog with Delphi and Borland news http://svd.blogspot.com/ * Delphi / InterBase WebLog - by Craig Stuntz News of interest to Delphi and InterBase developers. http://delphi.weblogs.com/ * 28-FEB-2003: Update: Bold for Delphi Architect - by John Kaster An update to Bold for Delphi 7 Architect is now available. http://bdn.borland.com/article/0,1410,29798,00.html * 01-MAR-2003: Borland Fires "Sidewinder" at VS.NET - by Alan Zeichick Forthcoming C# IDE for Windows to support models, non-Microsoft databases. Bringing together its compiler and IDE expertise, newly acquired modeling software from TogetherSoft, and the .NET Framework SDK licensed from Microsoft Corp., Borland Software Corp. is preparing to release its own C# IDE for .NET. http://www.sdtimes.com/news/073/story4.htm * 01-MAR-2003: Borland Pulls Together Talk about hitting the ground running. Borland Software Corp. has already revamped its developer tools to incorporate key technologies from its TogetherSoft acquisition—and the deal closed only one month ago. http://www.sdtimes.com/opinions/opinion_073.htm * Borland Delphi .NET - Scheduled for April 2003 Borland's .NET tools lag behind Microsoft's, but the prospect of cross-platform integration and strong modelling features should ensure a significant share of the .NET market. http://www.pcpro.co.uk/?reviews/reviews_story.php?id=38828 ________________________________________________________________________ Vote for the Pascal Newsletter in The Programming Pages! http://www.programmingpages.com/?r=latiumsoftwarecomenpascal ________________________________________________________________________ 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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E http://www.programmingpages.com/?r=latiumsoftwarecomenpascal http://www.top219.org/cgi-bin/vote.cgi?delphi&83 http://top100borland.com/in.php?who=20 http://top200.jazarsoft.com/delphi/rank.php3?id=latium http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80 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 <eds2004 @ 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/download/p0045.zip ________________________________________________________________________ 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? eds2004 @ latiumsoftware.com ________________________________________________________________________ Latium Software http://www.latiumsoftware.com/en/index.php Copyright (c) 2003 by Ernesto De Spirito. All rights reserved. ________________________________________________________________________ |
The full source code examples of this issue are available for download.
![]() |
Errors? Omissions? Comments? Please contact us!






