Palm og Delphi

Tags:    delphi
Skrevet af Bruger #132 @ 04.09.2001
Palm Conduits i Delphi - en kort intro


Indledning

Denne artikel er en intro til udviklingen af PalmConduits i Delphi. Niveauet kan måske synes lidt højt, men hvis man holder hovedet koldt og følger vejledningen, er det ikke så slemt.

Software

For at programmere PalmConduits i Delphi skal man bruge et udviklerkit. Jeg har valgt at bruge det officielle Conduit Developers Kit (CDK) fra Palm. CDK kan hentes hos Palm på http://www.palmos.com/dev/tech/conduits/. Desuden kan det anbefales at hente den nyeste version af den HotSync software der følger med Palm'en på adressen http://www.palm.com/support/downloads/. Til sidst vil jeg anbefale at man henter POSE (Palm OS Emulator). Det er et program der kører på PC'en, og som emulerer en Palm. D.v.s. at man kan køre Palm programmer på den og Hotsynce sin dekstop med den. POSE kan findes på http://www.palmos.com/dev/tech/tools/emulator/.

Et par indledende bemærkninger

Allerførst har jeg lige et par bemærkninger. For det første har jeg besluttet mig for i denne artikel at lave en conduit til at synkronisere memo-applikationen der følger med alle Palms. Det betyder, at den oprindelige Conduit til memoen skal slettes, og at man derfor ikke har mulighed for at synkronisere normalt. Dernæst vil jeg kraftigt anbefale at man henter POSE, og bruger den, frem for sin rigtige Palm. Så gør det nemlig ikke noget, hvis man skulle komme til at slette et par records i databasen ved et uheld.

Opsætning af POSE og Palm Desktop

Opsætningen af POSE vil jeg springe let og elefant hen over. Den er beskrevet udemærket i den medfølgende dokumentation, og jeg kan ikke se nogen grund til at gentage det her. Start med at sætte den op, og få den til at hotsynce med din normale Palm Desktop. Når det er gjort, vil jeg foreslå at du opgraderer din Palm Desktop software, hvis du ikke allerede har gjort det. Til sidst installeres CDK, og den endelige konfiguration kan begynde. I CDK installationen er der et directory der hedder common\\bin\\C4.02. Det er her de fleste af de filer der skal bruges ligger. Start med at afslutte HotSync programmet, hvis du har det kørende. Start dernæst programmet CondCfg, der ligger i C4.02 directoriet. I programmet er der en liste over de installerede conduits. Start med at slette den der har CreatorID 'memo'. Tryk derefter på Add. Du har nu mulighed for at tilføje en ny conduit som erstatning for den memo-conduit der lige er slettet. I feltet CreatorID skal der altså stå 'memo'. Da der er memo-databasen der skal synkroniseres med, skal der stå MemoDB i Remote Database-feltet. Til sidst vælges at det er en COM-conduit vi vil lave. I feltet COM Client skrives den fulde sti til Delphi, altså fx. C:\\Program Files\\Borland\\Delphi5\\Bin\\delphi32.exe, afhængig af hvilken Delphi der er installeret, og hvor den er installeret henne. Grunden til at det er stien til Delphi der skal stå i feltet er, at når synkroniseringen kommer til den nye conduit, vil den starte Delphi op. Her har man så mulighed for at loade det project man vil arbejde med, og debugge sit program med breakpoints, step o.s.v. Ret smart. Når det hele er tastet ind trykkes ok. Til sidst er det nøvendigt at checke efter, om alle filer er tilstede, det er nemlig ikke sikkert, at de er det (hvilket tog mig et par dage at regne ud :-) ). Start med at checke at alle de filer der står i listen (som regel DLL'er) findes i C4.02 directoriet. Tryk derefter på View Notifiers, og check efter om alle de filer der er i den liste findes i C4.02 directoriet. Skulle der være nogen på listen, der ikke er i det directory, skal de kopieres over fra den almindelige Palm Desktop installation. Til sidst køres det HotSync program der ligger i C4.02 directoriet. Det er det der skal bruges under udviklingen, ikke det der følger med Palm Dekstop'en.

Opsætning af Delphi

Efter opsætning af HotSync software er turen kommet til installation af COM objekterne i Delphi. Start Delphi op, og start på en ny application. Vælg Project/Import Type Library. Nu skulle der komme en liste mde en masse libraries. Kig i listen om der er to der hedder hhv. Palm ComDirect og Palm ComStandard. Hvis de er det, tilføjes de en efter en med install knappen. Hvis de ikke er på listen, vælges Add, og i C4.02 directoriet vælges filerne ComDirect.tlb og ComStandard.tlb, som installeres på skift med install knappen. Nu skulle der gerne være kommet nogle nye komponenter i ActiveX fanen.

Første program - Developer version

Efter at have overstået installationen, er vi klar til at tage hul på selve udviklingen. Det eksempel-program jeg vil lave er et lille program der kan søge igennem memo-databasen i palm'en efter en given tekst. Ikke særlig opfindsomt, men det er jo også kun en demo (ok, jeg indrømmer, idéen er hugget fra den medfølgende dokumentation :-) ). Start med at placere en editboks (edit1), en button (Button1) og en memo (memo1) på formen. Dernæst placeres en PDatabaseQuery (pDbQuery), en PDUtility (pUtility) og en PDRecordAdapter (pMemo) fra ActiveX fanen på formen. Dernæst skrives koden i button1.OnClick. Jeg vil starte med at skrive koden i små bider, som jeg gennemgår, og derefter skrive hele koden til sidst, så den kan Cut'n'Pastes ind i Delphi.

Opret først flg. variable i proceduren:
var
  Index: integer;
  Category: integer;
  Attributes: ERecordAttributes;
  Memo: widestring;
  Count: integer;
  UniqueID: olevariant;
  Data: olevariant;
  Test: olevariant;
  pMemoIntf: IPDRecordAdapter;
Dernæst følger:
  pMemoIntf := IPDRecordAdapter(pDbQuery.OpenRecordDatabase
  ('MemoDB', 'PDDirect.PDRecordAdapter', eRead or eWrite or eShowSecret));
Det første der sker er at databasen åbnes med et kald til pDbQuery.OpenRecordDatabase. Parametrene er først navnet på databasen, dernæst programID-navnet på den database-adapter der bruges til at hente data ud med. Det sidste er den Access-mode databasen åbnes med. Her opnås der læse+skrive-rettigheder (selvom det sidste ikke bruges i denne demo), samt ret til at se skjulte records. Resultatet af OpenRecordDatabase er et Interface af typen IUnknown, som typecastes til en IPDRecordAdapter. Nu er det ikke sikkert at det er alle der ved hvad et interface er, og hvordan de bruges. Det kan, meget kort fortalt, ses som en beskrivelse af de metoder et givent objekt implementerer. Hvis du vil vide mere om interfaces kan det anbefales at læse noget om COM-objekter, da yderligere beskrivelse ligger uden for denne artikels rammer.
  pMemo.ConnectTo(pMemoIntf);
Dette "forbinder" vores PDRecordAdapter (som vi har lagt på formen) til det interface vi har fået tilbage fra OpenRecordDatabase.
  pMemo.IterationIndex := 0;
  Data := pMemo.ReadNext(Index, UniqueID, Category, Attributes);
Allerførst sætter vi index til 0, da vi skal læse fra starten af databasen. Dernæst læser vi den første record. Efter kaldet vil Index indeholde indexet på den record vi lige har læst, UniqueID vil være et unikt ID nummer på recorden, Category være den kategori den er placeret i, og Attributes vil være oplysninger om hvor vidt den er blevet slettet, ændret, om den er privat etc.
  while (not pMemo.EOF) do
  begin
    pUtility.ByteArrayToBSTR(Data, 0, MaxInt, Memo);
    if pos(edit1.text, Memo) > 0 then
      Memo1.lines.add(Memo);

    Data := pMemo.ReadNext(Index, UniqueID, Category, Attributes);
  end;
Til sidst looper vi igennem alle records, indtil der ikke er flere (pMemo.EOF er true). Det første i loopet er en konvertering af de læste data fra et Byte array til en string. Der konverteres fra første byte (0) til vi møder et #0 eller til vi har læst ret mange (MaxInt). MaxInt kan rettes til hvad man nu vil have som det maksimale antal tegn der skal læses. Dernæst kigges der efter den tekst der søges, og hvis den er der, hældes recorden i memo-feltet, og der læses en ny record.

Det var så den første lille conduit. Når koden er færdig, og skal laves til en "rigtig" conduit, der kører uden Delphi, skal den konverteres til en ActiveX komponent. Fordelen ved at lave en ActiveX komponent er også, at man kan konfigurere den inde fra HotSync programmet, ligesom man kan med de andre. D.v.s. vælge om Palm skal overskrive Desktop, omvendt eller om der ikke skal sync'es eller hvad man nu vil. Det vil jeg dog gemme til en senere artikel, da der er nok at tage fat på her.

Jeg håber, at folk forstår bare en smule af alt mit ævl. Hvis der er uklare punkter, må I skrive det i en kommentar, så skal jeg prøve at svare så godt jeg kan (jeg er selv begynder på det her område :-) ). Hvis man vil lære nogle af de andre funktioner at kende (og det vil man, hvis man vil lave noget der er bare en smule mere kompliceret end det her), kan det anbefales at læse ComSyncReference og ComSyncCompanion (ligger i Common/docs). Nu hvor selve installationen af udvikler-kittet er overstået, og du har set et lille eksempel på, hvordan man kalder de rutiner der er i API'et, er det ikke så svært at lave noget der er mere avanceret. Se på hvordan jeg har oversat de funktionskald jeg har brugt fra Visual Basic til Delphi, og overfør det til de andre funktionskald du vil bruge. God fornøjelse :-).

/Data

Her følger koden til demoen:
unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  PDDirectLib_TLB, StdCtrls, PDStandardLib_TLB, OleServer;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Memo1: TMemo;
    Label1: TLabel;
    pDbQuery: TPDDatabaseQuery;
    pMemo: TPDRecordAdapter;
    pUtility: TPDUtility;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  Index: integer;
  Category: integer;
  Attributes: ERecordAttributes;
  Memo: widestring;
  Count: integer;
  UniqueID: olevariant;
  Data: olevariant;
  Test: olevariant;
  pMemoIntf: IPDRecordAdapter;

begin
  pMemoIntf := IPDRecordAdapter(pDbQuery.OpenRecordDatabase
  ('MemoDB', 'PDDirect.PDRecordAdapter', eRead or eWrite or eShowSecret));
  pMemo.ConnectTo(pMemoIntf);
  pMemo.IterationIndex := 0; 
  Data := pMemo.ReadNext(Index, UniqueID, Category, Attributes);
  while (not pMemo.EOF) do
  begin
    pUtility.ByteArrayToBSTR(Data, 0, MaxInt, Memo);
    if pos(edit1.text, Memo) > 0 then
      Memo1.lines.add(Memo);

    Data := pMemo.ReadNext(Index, UniqueID, Category, Attributes);
  end;
end;

end.



Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (0)

Du skal være logget ind for at skrive en kommentar.
t