Ten minute tutorial - why write components
Presented to Australian Delphi User Group on 14th December 1998
by ADUG member John McDonald
I thought a discussion on "why write components" would be interesting.
I gave a examples of a couple of components that I have written, why I wrote them and a bit about how they worked, then asked for other reasons for writing components.
The first example was a descendant of DBGrid, which altered the behaviour of the right mouse click.
I defined a descendant of TDBGrid
type TJMDBGrid = class(TDBGrid)
I added a couple of private variables, a couple of public properties and a constructor to initialise the value of the private variables.
constructor Create(AOwner: TComponent); override;
.....
constructor TJMDBGrid.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
{ initialise variables, etc }
end;
A destructor was not needed, because there were no creates in the constructor, and there was nothing else that needed undoing when the component was destroyed.
And I added a procedure to intercept the RightButtonDown message.
procedure WMRButtonDown(var Msg: TWMRButtonDown); message WM_RBUTTONDOWN;
A Register procedure is always required to register the component on the palette:
procedure Register;
begin
RegisterComponents('JMcD',[TJMDBGrid]);
end;
The most difficult part was finding the documentation of the message procedure.
Using the component is just like using its ancestor TDBGRID, and Ive used the component in several programs.
The second example was a datacom component, to handle communication with a device connected by a serial cable. When the program was written in Delphi 1 it used the Windows API to handle the communication, but when I converted it to 32 bit I found the new API much more difficult to use, and converted the component to use AsyncPro.
It had various properties, several public methods;
function Open: Boolean; function Close: Boolean; function SendFile: Boolean; function ReceiveFile: Boolean;
and several events:
property OnDataRequired: TNotifyEvent read FOnDataRequired write FOnDataRequired; property OnSendOK........... property OnSendError........... etc.
Writing it as a component took longer than just writing the code in a datamodule, where you can drop other components onto the datamodule, and then use the object inspector to set them up.
When you write a component, you need to create other components in code, usually in the constructor, set their properties, and later free them in a destructor. But the resulting component is much cleaner to use later, and it is a neat way of modularising code.
The third example caused the most discussion. I needed to write code to handle transactions coming from a palmtop device.
I created a component with six methods, six events and very little code. Each method was paired with an event, and when a method was called, it called the corresponding event, after checking that it had been defined.
if Assigned(FOnTranReceived) then result:=FOnTranReceived(Data) else result:=rrUnknown;
The component made it simple to create multiple transaction handler objects. To create an object I made a datamodule, added some data access components, added one of these transaction handler components, then added code for each of the events.
In the program I would pass several of these objects to an interface component, which stored them in a list. The interface component would get a transaction from the palmtop device, and then pass it to one of the methods of each of these objects. Each object would return a status indicating whether it had handled the transaction or not, and whether it wanted to send a reply to the device.
Other method/event pairs were used to send the reply to the device, to notify the object of communication success or failure, etc.
I dont know whether others will consider this a legit use of components, but it worked well in terms of modularising the code, and it reduced the amount of repeated code considerably.
Other reasons members had written components included:
Combining several visual components into one component, so that they can be used as a group. Only required properties of the constituent components are exposed in the combined component.
Wrappers for DLLs or APIs. Writing a component to provide the functionality of a DLL or an API, with a simpler interface.