The interface "IBasic" is the very base interface for all other interfaces
that I'm using anywhere. It's properties and methods (see also the
IBasic Reference) are very important, because they're directly
available in every interface you'll ever come across when using mad*
packages.
|
type IBasic = interface ['{53F8CE42-2C8A-11D3-A52D-00005A180D69}'];
|
|
The following 2 methods check whether the interface "IID" is supported by
the implementing object. "Supports" only does the check, while "GetInterface"
also returns the specified interface, if it's supported.
|
function IBasic.Supports (const IID: TGuid ) : boolean;
function IBasic.GetInterface (const IID: TGuid; out obj) : boolean;
|
|
The method "SelfAsTObject" returns the object instance that implements the
IBasic interface. Generally you can't do much with this TObject pointer,
since the implementing classes are private to their units. So this method
is mainly useful when writing your own IBasic descendents.
|
function IBasic.SelfAsTObject : TObject;
|
|
There are several situations where you will encounter invalid interface
instances. Sometimes a valid object gets invalid, because whatever was
represented by the object got deleted. But the main reason why you'll have
to deal with invalid interface instances is that all the mad* functions which
are to return an interface instance never return "nil", even when they fail.
They also do not raise an exception. Instead they're returning an invalid
interface instance. "Invalid" means here that the property "IsValid" is
false. You can handle invalid objects in the same way as valid objects.
You can call all methods, you can use all properties, but they'll all simply
do nothing, if the object is invalid.
|
function IBasic.IsValid : boolean;
|
|
When calling methods you often get a direct boolean result, which tells you
whether the call succeeded or not. But how can you check whether a property
assignment has succeeded? The usual behaviour would be to raise an exception
if an assignment did not succeed, but I don't like that behaviour very much.
So my properties don't react this way. But how can you then know whether a
property assignment was successful or not? You can right after the assignment
ask the following method, it will tell you the result of the last action:
|
function IBasic.Success : boolean;
|
|
When an error occurs, my interfaces almost never raise an exception, instead
you'll get a function result which is indicating the error, or you can check
the IBasic.Success method. After you found out that an error occured, you
can ask the "LastErrorNo" and "LastErrorStr" properties about the reason. You
can also set error codes and strings yourself.
|
property IBasic.LastErrorNo : cardinal;
property IBasic.LastErrorStr : string;
procedure IBasic.SetLastError (no: cardinal; str: string = '');
|
|
Each "IBasic" descendent has 2 multi purpose properties, namely "StrBuf" and
"Data", one being a string and one a pointer. For the "Data" pointer you can
also define a function which is called when the interface instance is freed.
In this situation you should then free the Data pointer.
Both multi purpose properties are not used by any object internally. That
means you can freely do with them whatever you like, just like with the well
known "tag" property that exists in a lot of VCL objects.
|
property IBasic.StrBuf : string;
property IBasic.Data : pointer;
type
TDataDestroyProc = procedure (var data: pointer);
TDataDestroyProcOO = procedure (var data: pointer) of object;
procedure IBasic.SetData (data : pointer;
dataDestroyProc : TDataDestroyProc ); overload;
procedure IBasic.SetData (data : pointer;
dataDestroyProc : TDataDestroyProcOO); overload;
|
|
The following properties only have a meaning if our object is an item of one
or more ICustomBasicList descendents. Each of the following properties
correspond exactly to one parent list.
The property "Index" tells you at which position in the parent's item list
our object is stored in the moment. The properties "OldIndex" and
"LastChange" are useful when the parent list fires a TIListChangeEvent.
You can in such a situation then ask what exactly has changed and what value
the index had before the change.
The properties "Selected", "Focused" and "Checked" are useful e.g. when a
parent ICustomBasicList shows it's items in a TListView.
A little extension to the madTypes unit:
|
type TDABasic = array of IBasic;
|
|