DELPHI TIPS
Tips
1. Changing the units name
To keep the project synchronized, always change the units name through “SaveAs” and don’t change the name directly in the program code.
2. Change the form name
“frmDemo” in object inspector => new form type to => “TfrmDemo”
3. Event handler is always “Procedure”. Simply call it as “Event Handler”
4. Project file
Delphi keep tracks of the different units in a program through Project file. [Program => View Source]
5.OOPS
type
TOriginalClass=class
end;
type
TDescendantClass=Class(ToriginalClass)
end;
Note : TDescendant >= TAncestor.
6. Objects can consist of two element (Data & Method)
7. Simply declaring the variable, it allocates its memory automatically.
But for object the code is responsible for both allocating & releasing
their memory.
To allocate the memory you must call a special routine called a
“Constructor”. “Constructor” is actually a function which returns a
pointer to the memory it allocated.
<object> := <classname> <constructorname>;
Student1 := TStudent.Create;
<object>.Free;
Note : Always use
Try
{
. . .
use object
. . .
}
finally
. . .
freeing object
. . .
end;
8.Scope (access modifier)
public – Donate for public use
{By default for all method & instance variable}
private – Keep personal
published – Distribute for that component
{available in object inspector if we put it in component,
same like public}
protected – (Keep for descendant}
9.Declaring constructor
type
TSquare = class
Fx,Fy : Integer;
FCaption : String;
Constructor Create(px,py:Integer);
end;
Implementation
Constructor TSquare.Create(px,py:Integer);
Begin
. . .
. . .
End;
10. Destructor
Destructor always called “Destroy”
When “Free” method invoked in turn it will call automatically the “destructor” Note : Only it will be called if we declared destructor as “override”
Type
TMyList = class
private
Constructor Create;
Destructor destroy; override;
Public
End;
Implementation
Destructor TMyList.Destroy;
Begin
FMList.free;
Inherited destroy;
End;
11. Include form definition in the unit file
{$R*.dfm}
12. Overload
This directive allows us to have different version of the same named function and procedure with different argument.
We can avoid the need for overloading by giving final arguments default values
Procedure MyProc(a:byte; b:Bytpe=23);
Unit unit1
Interface
Uses windows, forms,messages,...;
Type
TRectangle = class
Private
Coords : array[1..3] of integer;
Public
Constructor Create(left,right,top,bottom : integer);Overload;
Published
Constructor Create(topleft,bottomright:TPoint);Overload;
End;
TForm1 = Class(TForm)
Procedure FormCreate(Sender:TObject);
End;
Var
Form1 : TForm1;
Implementation
{$R*.dfm}
Constructor TRectangle.Create(left,top,right,bottom:Integer);
Begin
Coords[0] := left;
Coords[1] := top;
Coords[2] := right;
Coords[3] := bottom;
End;
Constructor TRectangle.Create(lopleft,bottomright :TPoint);
Begin
Coords[0] := topleft.x;
Coords[1] := topleft.y;
Coords[2] := bottomright.x;
Coords[3] := bottomright.y;
End;
Procedure TForm1.FormCreate(sender : TObject);
Var
Rect1,rect2 : TRectangle;
Point1, Point2 : TPoint;
Begin
Point1 := Point(122,133);
Point2 := Point(144,155);
Rect1 := TRectangle.Create(22,33,44,55);
Rect2 := TRectangle.Create(Point1,Point2);
End;
End.
13. Inline overload function
function MaxValue(a,b:Byte):Overload;
begin
. . .
. . .
end;
function MaxValue(a,b:Integer):Overload;
begin
. . .
. . .
end;
function MaxValue(a,b:Extended):Overload;
begin
. . .
. . .
end;
procedure Tform1.ButtonClick(Sender:TObject)
begin
form1.close;
end;
procedure TForm1.FormCreate(Sender : TObject)
begin
MaxValue(15,23);
MaxValue(1500,23);
MaxValue(15.0,23.0);
end;
14. Override
Override directive defines a class method as overriding the same method in a parent class.
We can only override classes defined as Virtual (optimized for speed using
VMT) / Dynamic (Optimized for memory).
15. Difference between Virtual & Dynamic
Virtual: When running all objects which already had created, all “method” with word “virtual” will be in memory style FIFO (or what we call VMT Virtual Method Table) when object destroy, it will disappear as well.
Dynamic: Method with “dynamic” will be call to memory “VMT” as well when running, but it is only call when it is being used in order to save memory.
[ Refer the following program]
Unit unit1;
Interface
Uses forms,windows,...
Type
TPolygon = class
Private
Sidecount : Integer;
SideLength : Integer;
ShapeArea : Double;
Protected
Procedure setArea; Virtual; Abstract;
Published
Property count : Integer read sidecount;
Property length : Integer read sidelength;
Property count : double read shapeArea;
Constructor Create(sides,length:integer);
End;
TTriangle = Class(TPolygon)
Protected
Procedure setArea;Override; //override the abstract method
End;
TSquare = Class(TPolygon)
Procedure setArea;Override;
End;
Tform1= Class(TForm)
Procedure FormCreate(sender:TObject);
Private
Public
End;
Var
Form1 : Tform1;
Implementation
{$R*.dfm}
Procedure Triangle.SetArea;
Begin
ShapeArea := (sidelength * sidelength) / 2;
End;
Procedure TSquare.SetArea;
Begin
ShapeArea := sidelength * sidelength;
End;
Procedure TForm1.FormCreate(Sender:TObject);
Var
triangle : TTriangle;
square : TSquare;
Begin
triangle := TTriangle.Create(3,10);
square := TSquare.Create(4,10);
triangle.Area;
square.Area;
End;
Constructor TPolygon.Create(sides,length:Integer);
Begin
Sidecount :=sides;
Sidelength :=length;
End;
16.Uses
This keyword defines list of one or more units that are used by the current units, program or library.
Uses may be defined in the interface & implementation section
It is cleaner and may save recompilations, if we put units uses in implementation section if they are only used there.
17.Interfaces
Version 1:
Starts the definition of external interface of a unit.
Declarations here are externally visible by other units.
All of the declaration must be implemented in the “Implementation” section
Version 2:
Taking one step further of Abstract(Place holder), “Interface” defines a grouping of just abstract properties and methods.
It is like a class with only abstract method.
Note:
When implementing an interface, we must implement QueryInterface, _AddRef, _Release standard interface method. So going to write these from scratch, we can implement (TInterfaced object) directly this type contains 3 methods).
Type
IVechicle = Interface(IInterface)
function GetAge : Integer;
function GetMiles : Integer;
property age : Integer read GetAge;
property miles : Integer read GetMiles;
function GetValue : Currency;
end;
{Implement this interface in a car class. Note that TInterfaceObject defines QueryInterface, _Addref, _Release standard interface methods}
TCar = Class(TInterfaceObject, IVechicle)
Private
fAge,fMiles : Integer;
fcarType : String;
function GetAge : Integer;
function GetMiles : Integer;
public
property age : Integer read GetAge;
property Miles : Integer read GetMiles;
property CarType : string read fcarType;
function GetValue : Currency;
published
Constructor Create(age,miles:Integer;cartype:String);
End;
Constructor TCar.Create(age,miles:Integer;carType:String);
Begin
fAge := age;
fMiles := miles;
fcarType := carType;
End;
Function TCar.GetAge:Integer;
Begin
Result := fAge;
End;
Function Tcar.GetMiles: Integer;
Begin
Result := fMiles;
End;
Function TCar.GetValue : Currency;
Begin
Result := 10000.0 – ((age * miles) / 10.0);
End;
Procedure Tform1.FormCreate(Sender:TObject);
Var
Car :TCar;
Begin
Car := TCar.Create(1,2076,’Honda’);
ShowMessageFmt(‘My
%s...d...%d...%m’,[car.carType,car.age,car.miles,car.Getvalues]);
End;
NOTE:
Type TObject = class
Constructor Create;
...
destructor Destroy; virtual;
End;
Everyclass is ultimately derived from TObject because of this “every object inherits the methods of TObjects.
18.Circular Unit reference
When units reference each other directly or indirectly, the units are said to be mutual dependent.
Solution: One of the reference is moved to the implementation section
Unit unit1; Unit unit2;
Interface Interface
Uses unit2; uses unit1;
{Moved unit to implementation section}
Unit unit2;
Interface
...
Implementation
Uses unit1;
Multiple and indirect unit reference:
Program Prog;
Uses unit2;
Const a=b;
Unit unit2;
Interface
Uses unit1;
Const b=c
Unit unit1;
Interface
Const c=1
The order in which units appear in the uses clause determines the order of their initialization and affects the way identifiers are located by the compiler.
If 2 units declares const,var,... then the compliler uses the one from the unit listed ast in the uses interface.
Only interface section changed leads to recompile. It will be tracked by compiler itself.
19. Unit Program sections
unit unit1;
interface
uses {list of units goes here}
{Interface section goes here}
implementation
uses {list of units goes here}
{Implementation section goes here}
initialization
{Initialization section goes here}
finalization
{finalization section goes here}
end.
Note :
Uses A,B,C;
Initialization section of units used by client executed A->B->C order.
finialization section of units used by client executed C->B->A order.
20.Application Parameter
Run -> Parameter (1.Host Application : C:\x.exe 2.Parameters:Raj Kumar)
ParamCount : 2
ParamStr(0) : C:\x.exe (default)
ParamStr(1) : Raj
ParamStr(2) : Kumar
21. COM
These technology includes
-
COM servers and clients
-
ActiveX controls (dll/exe)
-
OLE (Object linking embedding) {embedding a spread sheet in a doc. Share data of one application to another application}
-
Automation
COM: The component object Model
It defines API and a binary standard for communication between objects that’s independent of any programming language
Similar to VCL objects except that they have only methods and properties associated with them not data field
(i) Across the process (ii) Across the machine boundaries(DCOM)
COM/ActiveX/OLE
1995’s : OLE was the blanket term used to describe the entire suit of
technology built on COM architecture.
1996’s : ActiveX, which became blanket term to describe non-OLE technologies
built on top of COM
It includes Automation (OLE Automation) controls, documents,
containers, scripting and several internal technologies.
Because of confusion created by using the term “ActiveX” to describe everything short of the family, MS backed off a bit and now refer to non-OLE COM technologies simply as COM technology based.
TIPS
(i) Instance of COM object => Object, the type that identifies that objects is
usually referred as “COMPONENT CLASS” / “COCLASS”.
(ii) Need to send CLSID of the COM class in order to create object.
(iii) Chunck of data’s shared between applications – OLE Objects.
(iv) Application that have the capability to contain OLE objects – OLE
Container.
(v) Application that have the capability to have their data contained within
an OLE container – OLE Server.
(vi) Document contains one or more OLE objects – Compound document.
Threading Model:
(i) Single: the entire COM server runs on a single thread.
(ii) Apartment (STA): each COM objects executes within the context of its own
thread multiple instance of same COM objects run in different thread.
(global var) protected by thread synchronization.
(iii) free (MTA) – client can call a method of an object on any thread at any
time.
(iv) Both – apartment / free threading models are supported.
In-Process COM servers (In-Proc)
- DLL’s
- with in same process as the calling application
- In-Proc server must export 4 standard entry point function:
(1) function DllRegisterServer:HResult; stdcall;
(2) function DllUnRegisterServer:HResult; stdcall;
(3) function DllGetClassObject(const CLID,IID GUID;var Obj):HResult;
(4) function DllCanUnoloadNow:HResult; stdcall;
Create a instance of COM server
Unit : ComObj
Function : CreateCOMObject(const ClassID:TGUID):IUnkown;
Out-of-process COM Servers
- run on its own process
Distributed COM
Function : CreateRemoteCOMObject(const macihnename:WideString;
const classID:TGUID) : Iunknown;
22. Tray notification icon component
function shell_notifiIcon(msg,@tnd);
23. TDataModule
It centralizes the handling of non visual components in an application
-
Typically it’s a data access component
-
Also contain TTimer, TopenDialog, TImagelist, TOLEContainer
-
We can place the business rules in the unit ifle of datamodule
Events : Oncreate, OnDestroy
Properties : OleCreateOrder
Advantage:
-
Sharing data access components and code
-
Design time visual organization
-
Business rules centralization
-
Code Maintainance
24. Object Hierarchy
TObject => TPersistent => TComponent => TControl => TWinControl => TButtonControl
TObject (Unit: System)
Ultimate ancestor of all VCL objects and components. It encapsulates
fundamental behaviors common to VCL objects
Ex: Create/Maintain/Destroy instances of the object by
Allocating/initializing/freeing required memory for the object
TPersistent (Unit: Classes) [read write properties]
It’s ancestor of all objects that have assignment & streaming capabilities.
It’s encapsulates behaviors of all objects that can be assigned to other
objects, and that can read/write their properties to and from a stream.
TComponent (Unit: Classes) [appear in form design]
Ancestor of all components that can be appear in the form designer.
TControl (Unit:Control) [visible at run time]
It’s base class for all components that are visible at runtime.
TWincontrol (Unit: Control)
Base class for all controls that are wrapper for MS windows screen objects.
TButtonControl (Unit: StdCtrls)
25. Access Modifier
A private member is invisible outside of the unit or program where its class is declared. In other words, a private method cannot be called from another module, and a private field or property cannot be read or written to from another module. By placing related class declarations in the same module, you can give the classes access to one another’s private members without making those members more widely accessible.
A protected member is visible anywhere in the module where its class is declared and from any descendant class, regardless of the module where the descendant class appears. In other words, a protected method can be called, and a protected field or property read or written to, from the definition of any method belonging to a class that descends from the one where the protected member is declared. Members that are intended for use only in the implementation of derived classes are usually protected.
A public member is visible wherever its class can be referenced.
26. Calling conventions
When you declare a procedure or function, you can specify a calling convention using one of the directives register, pascal, cdecl, stdcall, and safecall. For example,
function MyFunction(X, Y: Real): Real; cdecl;
...
Calling conventions determine the order in which parameters are passed to the routine. They also affect the removal of parameters from the stack, the use of registers for passing parameters, and error and exception handling. The default calling convention is register.
The register and pascal conventions pass parameters from left to right; that is, the leftmost parameter is evaluated and passed first and the rightmost parameter is evaluated and passed last.
The cdecl, stdcall, and safecall conventions pass parameters from right to left.
For all conventions except cdecl, the procedure or function removes parameters from the stack upon returning. With the cdecl convention, the caller removes parameters from the stack when the call returns.
The register convention uses up to three CPU registers to pass parameters, while the other conventions pass all parameters on the stack.
The safecall convention implements exception “firewalls.” On Windows, this implements interprocess COM error notification.
The table below summarizes calling conventions.
Directive Parameter order Clean-up Passes parameters in registers?
register Left-to-right Routine Yes
pascal Left-to-right Routine No
cdecl Right-to-left Caller No
stdcall Right-to-left Routine No
safecall Right-to-left Routine No
The default register convention is the most efficient, since it usually avoids creation of a stack frame. (Access methods for published properties must use register.) The cdecl convention is useful when you call functions from shared libraries written in C or C++, while stdcall and safecall are recommended, in general, for calls to external code. On Windows, the operating system APIs are stdcall and safecall. Other operating systems generally use cdecl. (Note that stdcall is more efficient than cdecl.)
The safecall convention must be used for declaring dual-interface methods. The pascal convention is maintained for backward compatibility.
The directives near, far, and export refer to calling conventions in 16-bit Windows programming. They have no effect in 32-bit applications and are maintained for backward compatibility only.
Sample Codes
1. Connecting to AS400
uses cwbx_TLB;
(Type Lib: C:\Program Files\IBM\Client Access\Shared\cwbx.dll)
var
dq : IcwbxDataQueue; //AS400 Data Queue
as400 : IcwbxSystem; //AS400 system
begin
strAS400Name := slServerParams.strings[0];
strLibrary := slServerParams.strings[1];
strDataQue := slServerParams.strings[2];
strTimerValue := slServerParams.strings[3];
strUserName := slServerParams.strings[4];
strPassWord := slServerParams.strings[5];
dq := coDataQueue.Create;
as400 := coAS400System.Create;
as400.Define(strAS400Name);
as400.UserID := strUserName;
as400.Set_Password(strPassWord);
as400.PromptMode := cwbcoPromptNever;
//Setting parameters for DataQue
dq._Set_System_(as400);
dq.LibraryName := strLibrary;
dq.QueueName := strDataQue;
//Connecting to AS/400 serevr
as400.Connect(cwbcoServiceDataQueues);
end;
2. Dynamic loading of library
{Compatable for Win NT/2000/XP}
function TPatroller.IsAppRespondigNT(wnd: HWND): Boolean;
type
TIsHungAppWindow = function(wnd:hWnd): BOOL; stdcall;
var
hUser32: THandle;
IsHungAppWindow: TIsHungAppWindow;
begin
Result := True;
hUser32 := LoadLibrary(PChar('user32.dll'));
if (hUser32 > 0) then
begin
@IsHungAppWindow := GetProcAddress(hUser32, 'IsHungAppWindow');
if Assigned(IsHungAppWindow) then
begin
Result := not IsHungAppWindow(wnd);
end;
end;
end;
3.Static loading of library
function InternetReadFile (hFile: Pointer; lpBuffer: Pointer;
dwNumberOfBytesToRead: DWORD;
var lpdwNumberOfBytesRead: DWORD): BOOL;
stdcall; external 'WinInet.DLL';
4.File Handling (Copy text file ‘TWLABEL.TXT’ and write it into COM port)
var
txtCommFile,txtComm : TextFile;
begin
AssignFile(txtComm, 'COM1'); {1. Assign COM Port}
Rewrite(txtComm);
AssignFile(txtCommFile,'TWLABEL.TXT'); {2. Assign text file}
Reset(txtCommFile);
while not eof(txtCommFile) do {3. Copy from 2 to 1}
begin
Readln(txtCommFile, strCommData);
Writeln(txtComm,strCommData);
end;
CloseFile(txtCommFile); {4. Close 2}
Writeln(txtComm,'');
CloseFile(txtComm); {5. Close 1}
end;