Palm Conduit for Delphi Beta v0.1
This is the first beta release of a set of VCL components and Delphi classes
to enable Palm conduits to be developed in Delphi. In this release, the
components will only function while Delphi is running. The product includes
Delphi translations of the Sync Manager, Hot Sync Log, and Conduit API
functions, all of which will be available in the source code of the release
version.
Any feedback is welcome, including, but not limited to :
- Bug reports
- Feature requests
- Critiques of the design
- Pricing suggestions (is about US$60 reasonable?)
- Ideas for a better name
Please send all communications to
jim.cooper@virgin.net
Updates will be available from Tabdee Ltd
website.
Warning : Use this product at your own risk, as
it may not be completely stable. Ensure that you have secure backups of all
critical data on your Palm using something like BackupBuddy before
starting to develop your conduit by any method. I speak from experience!
It is assumed that you will use these components along with the documentation
in the CDK. If you don't understand something in this documentation, then that
should be your first reference. You may also find the book Palm Programming, The
Developer's Guide by Rhodes and McKeehan useful.
This product supports the CDK v3 and upwards, and is designed for use in
Delphi 5. It may work in earlier 32-bit versions of Delphi, but it hasn't been
tested (and in any case you would need the source code version).
How does it work?
All Palm conduits are dlls called by the HotSync application. These dlls have the
following set of possible entry points :
- CfgConduit
Newer version of ConfigureConduit. If it does not exist, the
HotSync Manager calls ConfigureConduit.
- ConfigureConduit
Called by the HotSync Manager when the user tries to change the conduit setup.
- ConfigureSubscription
Called by the file-linking dll.
- GetConduitInfo
Returns information about your conduit.
- GetConduitName
Called whenever the HotSync manager needs the conduit's name.
- GetConduitVersion
Called to retrieve the version number of your conduit.
- ImportData
Called when importing data if using file-linking.
- OpenConduit
Called to perform the synchronisation of data.
- SubscriptionSupported
Called to determine if file-linking supported.
The Palm Conduit for Delphi implements ConfigureConduit, GetConduitInfo,
GetConduitName, GetConduitVersion and OpenConduit. Of these, you will be able
to override the default behaviour for ConfigureConduit and OpenConduit.
OpenConduit is the most critical entry point, as this is where the actual
synchronisation code must be.
The product does not implement the CfgConduit entry point; it is left for
your use, should you need it.
In order to make life a little easier, much of the Sync Manager API has been
encapsulated in 2 components, modelled on Delphi's TDatabase and TDataset
components. Note : These controls are not descendants of
these components. You cannot connect the TtabdConduitDb to any
data-aware controls, for instance. This is not really a problem as there should
be no user interaction during a syncing operation (the user may be connecting
over a modem, for instance, and unable to see the PC screen). If there is
sufficient demand, this may change in future versions.
Installation
Unpack the zip file into a suitable directory, keeping the directory structure.
Add the TabdPalmConduit.dcu file to a package of your choice.
Creating a conduit.
1. Open a new project to create a dll.
2. Add a data module to the project (you should not normally create any forms).
3. Drop a TtabdConduit onto the data module and set the relevant properties.
4. Drop a TtabdConduitDb onto the data module and set the relevant properties
(database name, fields etc).
5. Add an event handler for the TtabdConduit.OnOpenConduit event. You do not
need to add the SyncStarted, SyncAborted or SyncFinished type HotSync log
messages, as they are sent automatically.
6. Optionally deal with the OnConfigureConduit event.
7. Compile the dll, ensuring that the HotSync manager can find the target.
8. Test.
Not what you're looking for?
This is not the only way of writing conduits in Delphi. You can also try :
EHAND Connect, an excellent ActiveX control.
ConduitDB, another Delphi control.
The components
TtabdConduit
This component controls the conduit. There can only be one instance of a
TtabdConduit in your dll.
Methods
constructor Create(AOwner : TComponent);
destructor Destroy;
The usual component constructor and destructor.
procedure AddLogEntry(const Msg : string);
Adds an entry to the HotSync log.
procedure YieldCycles(MaxMilliSecs : WORD);
Wrapper for the SyncYieldCycles function.
procedure TestSyncApi(const ErrorMsg : string;ReturnValue : Integer);
Calls to Sync Manager API functions should se this procedure to test the
results. It will convert error numbers into Delphi exceptions
Properties
ConduitHandle : TCondHandle
Read only. Supplies a conduit handle that can be used in Sync Manager API calls.
ConduitVersion : DWord
Read only. Returns the complete conduit version number, derived from the
MajorVersion and MinorVersion properties.
ApiMajorVersion : DWord
Read only. Returns the HotSync API major version number.
ApiMinorVersion : DWord
Read only. Returns the HotSync API minor version number.
PathName : string
LocalName : string
UserName : string
Registry : string
RootKey : HKEY
All read only. Correspond to members of CSyncProperties (see CDK docs).
ConduitName : string
Conduit name as displayed and used by HotSync Manager.
DefaultAction : TSyncTypes
Default type of hotsync. Can be one of :
stFast,stSlow,stHHtoPC,stPCtoHH,stInstall,stBackup,stDoNothing,
stProfileInstall
MajorVersion : Byte
Conduit (ie your dll) major version number.
MinorVersion : Byte
Conduit (ie your dll) minor version number.
Events
OnOpenConduit
The most important event. The handler for this event does all the syncing.
OnConfigureConduit
Add ahandler for this event to override the default conduit configuration.
Alternatively, you could implement the CfgConduit entry point.
TtabdConduitDb
This component provides access to a database on the Palm.
Note : Only one Palm database can be open at
a time. This is a limitation imposed by the CDK. However, the
types of Palm databases that can be synchronised are small by comparison with
normal PC memory, so you could easily read entire databases into memory, if
needed.
Currently this component only works with record databases, not resource
databases. This may change in future if there is any demand.
Methods
constructor Create(AOwner : TComponent);
destructor Destroy;
The usual component constructor and destructor.
procedure Open;
procedure Close;
Methods to control opening and closing the database. Remember that only one can
be open at a time.
procedure ReadAppInfo;
procedure ReadSortInfo;
Methods to read AppInfo and SortInfo blocks so that they are accessible from the
AppInfoFields and SortInfoFields properties.
procedure WriteAppInfo;
procedure WriteSortInfo;
Methods to read from the AppInfoFields and SortInfoFields properties and save
the information back into the AppInfo and SortInfo blocks.
procedure First;
procedure Next;
procedure Prior;
procedure Last;
Methods to move through the database. Similar to those in a TDataset.
procedure PurgeAllRecords;
procedure PurgeAllRecordsInCategory(CatId : SmallInt);
procedure PurgeDeletedRecords;
Methods to purge records. They correspond to the Sync Manager API functions of
the same names. The Palm documentation suggests that PurgeAllRecordsInCategory
should not be called while iterating through the database.
procedure Find(RecId : DWORD);
Searches for a record with the given id.
procedure Append;
procedure Edit;
procedure Post;
procedure Cancel;
procedure Delete;
Similar to TDataset methods. There is no way to guarantee where Append will add
the new record (see the CDK docs for more information).
procedure AddField(const AName : string;ADataType : TtabdPalmFieldType;ASize : Integer);
A way to programmatically define members of the Fields property. Usually you
would do this visually with the property editor. Available data types are :
pftUnknown,pftByte,pftSmallint,pftLongint,pftBoolean,pftSingle,pftDouble,
pftDate,pftTime,pftString,pftBlob
pftSmallint is 16 bits, pftLongint is 32-bits. pftDate
and pftTime use the Palm date and time formats (see the CDK for
details).
ASize is ignored except for pftString and pftByte
types. You should set the set to 0 if they are variable length fields (eg like
the Address Book fields).
function FieldByName(const FieldName : string) : TtabdPalmField;
Similar to the TDataset function of the same name.
procedure Reset;
procedure NextInCategory;
procedure NextModified;
procedure NextModifiedInCategory;
These methods correspond to the Palm iteration functions of the same names.
Palm advise not to modify the database while performing these iterations. You
must also call Reset before any of the other methods.
function DebugRawRecAsStr : string;
function DebugAppInfoAsStr : string;
function DebugSortInfoAsStr : string;
Methods to help when debugging. They return the record, AppInfo block and
SortInfo blocks as strings. Any null characters are replaced by '0' and any
unprintable characters by '*'.
Properties
FileHandle : Byte
Read only. Returns a file handle that can be used in Sync Manager API calls.
Active : Boolean
Same as the TDataset property of the same name.
RecordCount : Word
Read only. Returns the number of records in the database.
CurrentRecordNum : Integer
The current record number in the database. Changing this moves the cursor. The
first record is 0.
Eof : Boolean
Read only. Returns True if at the end of the database.
Bof : Boolean
Read only. Returns True if at the beginning of the database.
State : TtabdPalmDbState
Read only. Returns the database state. Can be one of :
pdsInactive,pdsBrowse,pdsAppend,pdsEdit
Attributes : Byte
Read only. The attributes of the current record. These values are allowed :
sraRecAttrDeleted, sraRecAttrDirty, sraRecAttrBusy, sraRecAttrSecret,
sraRecAttrArchived
The are combined with the or operator (so you need to use and
to test for them).
property CategoryId : SmallInt
Category of the current record. Also used to define the category for Palm
iteration functions.
property CurrentRecord : PByte
The current record as an array of bytes (the property is a pointer of type
PByte). Usually you should access the record via the Fields property.
property RecordSize : DWord
Read only. Size of current record (Palm records are not necessarily of a fixed size).
Currently the maximum size is 65536 bytes (ie 216).
property AppInfoBlock : PByte
The AppInfo block as an array of bytes. Usually you should access the block
via the AppInfoFields property.
property AppInfoSize : Word
Read only. Size of the AppInfo block.
property SortInfoBlock : PByte
The SortInfo block as an array of bytes. Usually you should access the block
via the SortInfoFields property.
property SortInfoSize : Word
Read only. Size of the SortInfo block.
property FileName : string
The database name on the Palm. Note that these are case sensitive.
property CardNum : Byte
Memory card number. Normally set to 0.
property OpenMode : Byte
Database opening mode. The following flags should be combined with the or
operator :
omDbShowSecret, omDbExclusive, omDbWrite, omDbRead
The default is omDbWrite or omDbRead or omDbExclusive
property Fields : TtabdPalmFields
Record field definitions and values of the current record. See TtabdPalmField
for more information.
property AppInfoFields : TtabdPalmFields
AppInfo block field definitions and values. Also uses TtabdPalmFields.
property SortInfoFields : TtabdPalmFields
AppInfo block field definitions and values. Also uses TtabdPalmFields.
Events
property OnTestFieldExistsForRead
property OnTestFieldExistsForWrite
Some databases do not include a field in a record if that field is empty.
For instance, the Address Book string fields are included or not depending
on values in the Flags field. Respond to these events to check whether a
field should be read, or to set the flag to say whether it does or not
when writing a record back to the Palm. See the demo for an example.
property BeforeOpen
property AfterOpen
property BeforeClose
property AfterClose
property BeforeAppend
property AfterAppend
property BeforeEdit
property AfterEdit
property BeforePost
property AfterPost
property BeforeCancel
property AfterCancel
property BeforeDelete
property AfterDelete
property OnNewRecord
Database state change events similar to those in TDatasets.
EtabdConduitError
Class of exception raised by the Palm Conduit for Delphi classes. Same as a
normal exception, but with the addition of an error number property, which
corresponds to those in the CDK. Also adds a HotSync log entry consisting of
the error message. Usually raised by the TestSyncApi method.
constructor CreateError(const Msg : string;ErrorNum : Integer);
property ConduitError : Integer;
TtabdPalmFields
A collection of TtabdPalmField objects. Used for the Fields, AppInfoFields and
SortInfoFields properties of TtabdConduitDB components.
It has the overridden Add function and Items property common to all TCollection
decendants.
TtabdPalmField
Like a simplified version of the normal TField objects. However, there is only
one class for all field types, and they do not connect to data-aware controls.
Methods
constructor Create(Collection : TCollection);
Normal overridden TCollectionItem constructor. You should not normally need to
call this directly.
procedure Assign(Source : TPersistent);
Normal overridden TCollectionItem Assign method.
Properties
property ArraySize : Integer
Some fields might actually be arrays (eg the list of categories in an AppInfo
block). This field is set to the number of elements in the array. It defaults
to 1, ie just a normal single valued field.
property ArrayValue[Index : Integer] : Variant
Used to get and set the value of an array field. ArrayValue[0] is
equivalent to using the Value property.
property FieldName : string
Field name. Used by the FieldByName method of TtabdConduitDb components.
property DataType : TtabdPalmFieldType
Field data type. Can be one of :
pftUnknown,pftByte,pftSmallint,pftLongint,pftBoolean,pftSingle,pftDouble,
pftDate,pftTime,pftString,pftBlob
pftSmallint is 16 bits, pftLongint is 32-bits. pftDate
and pftTime use the Palm date and time formats (see the CDK for
details).
property Size : Integer
Size of the field. It is ignored except for pftString and pftByte
types. You should set the size to 0 if they are variable length fields (eg like
the Address Book fields).
property Value : Variant
Value of the field as a variant. For a pftBlob this is a pointer into an array
of bytes.
property AsInteger : Integer
Get and set the field value as an integer. Only applies field with relevant data
types.
property AsDateTime : TDateTime
Get and set the field value as a Delphi TDateTime onject. Only applies field
with relevant data types.