Dynamic Data Exchange – základní informace
DDE neboli Dynamic Data Exchange (dynamická výměna dat) je protokol vyvinutý firmou Microsoft, který slouží ve dvaatřicetibitovém prostředí Windows ke komunikaci mezi programy. Win32 API poskytuje řadu metod pro výměnu dat mezi (spuštěnými) aplikacemi a jedna z nich spočívá právě ve využívání protokolu DDE. Základní princip mechanismu dynamické datové výměny spočívá v zasílání speciálních zpráv mezi aplikacemi, která sdílí (cítí potřebu vyměňovat si) data; data jsou následně vyměňována přes sdílenou paměť. Komunikující aplikace mohou použít DDE jen k jednorázové výměně dat, stejně jako k trvalému datovému toku, v jehož rámci si posílají aktualizace dat vždy, když se vyskytnou nová data.
Hned na začátku je nutné podotknout, že mechanismus DDE je dnes již poněkud zastaralý. V nově vyvíjených aplikacích se obvykle používá spíše technologie OLE Automation, případně jiná metoda založená na technologii COM. V našem seriálu se budeme podrobně věnovat jak OLE Automation (což je vlastně „rozšíření“ – avšak značné – mechanismu OLE, kterým jsme se podrobně zabývali v dílech 38 – 40), tak i technologiím COM (a DCOM). Proto (z důvodu úplnosti), ale také pro jednoduchost používání DDE, se nevyhneme ani tomuto (poněkud staršímu) konceptu. Konec konců – programátoři by neměli znát jen nejnovější technologické výstřelky, ale i metody, jež se v hojné míře používaly před časem.
Používání DDE se trochu podobá používání schránky systému Windows, neboť ta se také používá k výměně dat mezi aplikacemi. Jeden rozdíl však spočívá v tom, že schránka je (skoro) vždy použita jako jednorázový důsledek specifické akce uživatele (např. zvolení položky Vložit z hlavní nabídky). Přestože dynamická datová výměna pomocí DDE může být také iniciována uživatelem, typicky pokračuje bez jeho dalších zásahů.
Nejčastější využití DDE spočívá v tom, že si dvě aplikace mezi sebou „zřídí spojení“, které následně udržují a využívají k přenosu dat.
Jak používat DDE
Rozhodneme-li se začít využívat DDE, máme k dispozici několik možností, přičemž už teď samozřejmě víme, že zvolíme ten nejjednodušší, který nabízí Delphi a jeho komponenty zapouzdřující DDE komunikaci. Přesto však pohovoříme i ke zbývajícím způsobům.
První verze DDE (která byla používána především jako dodatek k tabulkám Microsoft Excelu) skutečně spočívala v existenci množiny zpráv a pravidel, která bylo nutné používat (a dodržovat), aby bylo možné komunikovat s aplikacemi napsanými jinými programátory. Později se však situace trochu změnila, když byla do Windows 3.1 přidána knihovna DDEML (Dynamic Data Exchange Management Library, knihovna pro správu DDE). Tato knihovna (je to typická dynamicky linkovaná knihovna DDL) poskytuje jakési rozhraní, které značně zjednodušuje proces „přidání DDE do vaší Win32 aplikace“. Namísto přímého posílání a zpracovávání DDE zpráv může aplikace využívat funkce, které ke správě DDE spojení poskytuje DDEML.
Existující aplikace využívající (přímé) DDL jsou samozřejmě zcela kompatibilní s těmi, které pracují pomocí DDEML, jinak řečeno – aplikace, která při správě DDE spojení přímo zasílá zprávy, může navázat spojení s aplikací používající funkce DDEML. Je asi zbytečné dodávat, že rozhodnete-li se použít ve své aplikaci DDE, silně je doporučováno využívání knihovny DDEML.
Nutno ovšem podotknout, že problematika DDE versus DDEML se týká především programátorů ve Windows API. My, uživatelé Delphi:-), máme (jako obvykle) nesmírně zjednodušenou úlohu, neboť Delphi poskytuje několik komponent, s nimiž je používání DDE procházkou růžovým sadem.
Jak pracuje DDE
Při komunikaci pomocí DDE se často používání pojem „DDE konverzace“, případně „DDE rozhovor“. V těchto pojmech se skrývá velká část principu technologie DDE: jedná se o interakci mezi aplikací vystupující jako „server“ a aplikací typu „klient“. Server poskytuje informace, klient si je v případě potřeby vyžádá (v podstatě tedy řídí komunikaci). Každá aplikace může působit jako server pro více klientů, stejně tak klient může mít navázané spojení s více servery a využívat data více serverů. V zásadě je také možné, aby jedna aplikace vystupovala zároveň v roli serveru i klienta (a to dokonce v tentýž časový okamžik).
Úlohou serveru, jak už bylo zmíněno, je posílat data klientům. Úloha klienta je (trochu paradoxně) složitější: je zodpovědný za navázání spojení, zasílá požadavky na data, případně požádat server o provedení příkazu (v takových případech se však již skoro výhradně používá mechanismus OLE Automation). Klient může také požádat server, aby mu poslal data vždy v případě jejich změny (nebo změny jejich části).
Abychom si mohli ukázat navázání spojení, musíme si vysvětlit tři důležité pojmy:
- služba (service) – v podstatě název aplikace, která vystupuje jako DDE server. Není to sice podmínkou, ale ve většině případů to platí. Budeme-li mít aplikaci DATUM.EXE, která bude DDE Serverem, budeme jako název služby uvádět vždy řetězec `DATUM`.
- téma (topic) – „jemnější“ určení komunikace. Služba (tedy server) může být schopna poskytovat informace týkající se více témat. Tématem může být např. jméno souboru s daty, ale také jedno z oken serveru, případě vlastně cokoliv jiného. Vždy, když klient navazuje rozhovor se serverem, udává název tématu, o němž se hodlá se serverem „bavit“. Z tohoto popisu pravděpodobně nemůže být zřejmé, co to vlastně téma je, nicméně z praktických ukázek to okamžitě pochopíte.
- položka (item) – nejkonkrétnější identifikace přenášených dat, neboť ta se člení právě na položky. Položkou může být např. údaj z databáze, prvek z tabulky, nebo v zásadě (opět) cokoliv jiného :-) V rámci jednoho navázaného rozhovoru si může klient se serverem vyměňovat informace skládající se z mnoha položek.
DDE v Delphi
Tolik tedy k obecnému a teoretickému (avšak nezbytnému) úvodu. Nyní se můžeme směle vrhnout do Delphi a ukázat si, jakým způsobem tohoto způsobu komunikace využívat. Jako tradičně, začneme ukázkovou aplikací, abyste viděli, nač se můžete později těšit:-)
Z toho, co jsme si dosud řekli, je zřejmé, že vytvoříme dvě aplikace. První z nich bude sloužit jako jednoduchý DDE server, druhá jako klient. Úlohou serveru bude vypisovat do nápisu text, který uživatel serveru zadává do editačního pole. Celé manévry rozdělíme do dvou kroků – nejprve vytvoříme server, posléze klienta.
Vytvoření jednoduchého DDE serveru
- Vytvořte novou aplikaci a na formulář (frmHlavni) umístěte nejprve editační pole (edtText).
- Dále je nutné vložit na formulář komponentu zapouzdřující položku DDE komunikace. Komponenta se nazývá DdeServerItem a naleznete ji v paletě System. Název (vlastnost Name) ponecháme na přednastaveném DdeServerItem1.
- Ošetříme událost OnChange komponenty edtText. Obsluha bude nesmírně jednoduchá: v případě změny textu v editačním poli se tento text přiřadí do vlastnosti Text komponenty DdeServerItem, jinak řečeno – změněný text se stane položkou komunikace:
procedure TfrmHlavni.edtTextChange(Sender: TObject);
begin
DdeServerItem1.Text := edtText.Text;
end;
Toť vše – server pro DDE komunikaci máme vytvořen. V rámci zdrojového kódu si jen můžete všimnout, že při vytvoření formuláře změníme jeho pozici, velikost a titulek:
unit Hlavni;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DdeMan, StdCtrls;
type
TfrmHlavni = class(TForm)
edtText: TEdit;
DdeServerItem1: TDdeServerItem;
procedure edtTextChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmHlavni: TfrmHlavni;
implementation
{$R *.dfm}
procedure TfrmHlavni.edtTextChange(Sender: TObject);
begin
DdeServerItem1.Text := edtText.Text;
end;
procedure TfrmHlavni.FormCreate(Sender: TObject);
begin
frmHlavni.Left := 100;
frmHlavni.Top := 100;
frmHlavni.Height := 150;
frmHlavni.Width := 300;
frmHlavni.Caption := `DDE Server`;
edtText.Text := ``;
end;
end.
Vytvoření jednoduchého DDE klienta
Nyní vytvoříme druhou aplikaci – klienta. Vzhledem k tomu, že klient je zodpovědný za mnohem více činností než server, bude jeho vytvoření nepatrně složitější.
procedure TfrmHlavni.DdeClientItem1Change(Sender: TObject);
begin
lblText.Caption := DdeClientItem1.Text;
end;
Tím je vytváření klienta dokončeno. V události OnCreate formuláře jen opět změníme pozici, velikost a titulek formuláře a můžeme klienta přeložit a spustit:
unit Hlavni;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DdeMan, StdCtrls;
type
TfrmHlavni = class(TForm)
lblText: TLabel;
btnSpojeni: TButton;
DdeClientConv1: TDdeClientConv;
DdeClientItem1: TDdeClientItem;
procedure btnSpojeniClick(Sender: TObject);
procedure DdeClientItem1Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmHlavni: TfrmHlavni;
implementation
{$R *.dfm}
procedure TfrmHlavni.btnSpojeniClick(Sender: TObject);
begin
if DdeClientConv1.SetLink(`prjDDEServer`,`DDE Server`) then begin
ShowMessage(`Spojeni bylo uspesne navazano!`);
DdeClientItem1.DdeItem := `DdeServerItem1`;
end
else
ShowMessage(`Chyba pri navazovani spojeni!`);
end;
procedure TfrmHlavni.DdeClientItem1Change(Sender: TObject);
begin
lblText.Caption := DdeClientItem1.Text;
end;
procedure TfrmHlavni.FormCreate(Sender: TObject);
begin
frmHlavni.Left := 300;
frmHlavni.Top := 500;
frmHlavni.Width := 300;
frmHlavni.Height := 200;
frmHlavni.Caption := `DDE Client`;
lblText.Caption := ``;
btnSpojeni.Caption := `Spojeni`;
end;
end.
Vyzkoušejte DDE komunikaci
Server i klient je hotov, nezbývá, než začít experimentovat. Nejprve vyzkoušíme spuštění klienta a navázání spojení (aniž běží server). Po klepnutí na tlačítko Spojeni bude samozřejmě hlášena chyba při navazování spojení.
Necháme klienta spuštěného a spustíme také server. Než se pokusíme znovu navázat spojení, napíšeme nějaký údaj do editačního pole na serveru. Klient samozřejmě nezobrazuje nic.
Pokud však nyní klepneme na tlačítko Spojeni, bude již spojení úspěšně navázáno. Důsledkem je hlášení o úspěšném navázání spojení:
Vyzkoušejte si, že nyní se změny v editačním poli serveru ihned promítají do nápisu na klientu:
Ve své podstatě jsme tedy vytvořili DDE spojení mezi editačním polem jedné aplikace a nápisem druhé aplikace.
Pokud se více zahloubáte do zdrojových kódů, můžete si všimnout, že průběh spojení (tedy vlastní výměnu dat) zajišťují obě „položkové“ komponenty – DdeServerItem a DdeClientItem. „Konverzační“ komponenty (v tomto jednoduchém případě jsme ji pro server ani nepoužili, využíváme jen klientskou DdeClientConv) jsou zodpovědné prakticky jen za navázání spojení; vlastní výměna dat probíhá pak jen prostřednictvím položek (proto položky je to, co je vyměňuje).
Poznámka pro detailůchtivé uživatele: použitím těchto Delphi komponent jsme vytvořili DDE spojení pomocí knihovny DDEML, jejíž funkce jsou v těchto komponentách zapouzdřeny. I kdybychom chtěli pracovat přímo s DDEML (bez použití komponent Delphi, takže pomocí funkcí Windows API), bylo by to podstatně složitější. Používání přímého DDE ani nemá smysl zmiňovat.
Na závěr
Tolik pro dnešek k technologii DDE: Vysvětlili jsme si její princip a bez velkých teoretických znalostí vytvořili dvě aplikace, které spolu dokáží vcelku úspěšně komunikovat pomocí DDE. Za týden budeme pokračovat, přičemž začneme systematickým popisem jednotlivých Delphi komponent zapouzdřujících DDE komunikaci.