V dnešním díle dokončíme celé DDE manévry začaté před týdnem: nejprve dopíšeme ukázkový příklad napsáním klientů, pak si zahrajeme na špióny a budeme sledovat DDE rozhovory probíhající v systému, a nakonec zapojíme do DDE komunikace také Microsoft Word. V závěru se také dozvíte, proč je tento díl poslední, na jak dlouho a v jakém slova smyslu.
Druhá část příkladu – vytvoření DDE klienta
Před týdnem jsme dokončili server DDE, dnes se bez okolků pustíme do programování klientů.
- Vytvořte novou aplikaci. Na formulář umístěte nápis Label1, seznam ListBox1 a tři tlačítka: Button1 (Caption = Vymaz server), Button2 (Caption = Pripoj), Button3 (Caption = Odpoj); titulky nastavíme za běhu při vytvoření formuláře.
- Dále na formulář umístěte jednu komponentu DdeClientConv a tři komponenty DdeClientItem.
- Do vlastnosti DdeConv všech tří komponent DdeClientItem vložte název komponenty DdeClientConv (tedy DdeClientConv1). Tím jste zajistili, že všechny tři položky se budou získávat prostřednictvím komunikace udržované DdeClientConv1.
- Nemusíte nastavovat vlastnosti DdeItem žádné z komponent DdeClientItem, neboť to provedeme za běhu programu (po navázání spojení).
- Ošetřete událost OnClick tlačítka Button2. Po stisku tohoto tlačítka se klient pokusí navázat se serverem. Pokud jste se drželi instrukcí při vytváření serveru, bude se serverová aplikace jmenovat prjDDEServer. Pokud ne, doplňte své jméno:-) V každém případě se připojujeme k tématu identifikovanému komponentu DdeServerConv1 na serveru, takže právě toto jméno bude druhým parametrem funkce SetLink. Vzhledem k tomu, že (implicitně) je hodnota vlastnosti ConnectMode nastavena na ddeAutomatic, způsobí SetLink bezprostřední (pokus o) navázání spojení. Pokud bude tento pokus úspěšný, nastavíme hodnoty vlastností DdeItem všech tří komponent DdeClientItem. Tím vlastně „svážeme“ jednotlivé položky klienta a serveru: klientská položka DdeClientItem1 bude obsahovat hodnotu serverové položky DdeServerItem1 apod. Posledním krokem bude požadavek na data první položky (aby se ihned po navázání spojení zobrazil text v komponentě Label). Pokud se podivujete, proč zavoláme jen RequestData a získaná data nikam nepřiřazujeme, vězte, že získání dat vyvolá událost OnChange první položky (DdeClientItem1), takže nastavení titulku se provede v rámci obsluhy této události:
procedure TForm1.Button2Click(Sender: TObject);
begin
if DdeClientConv1.SetLink(`prjDDEServer`, `DdeServerConv1`) = True then begin
ShowMessage(`Spojeni uspesne navazano.`);
DdeClientItem1.DdeItem := `DdeServerItem1`;
DdeClientItem2.DdeItem := `DdeServerItem2`;
DdeClientItem3.DdeItem := `DdeServerItem3`;
DdeClientConv1.RequestData(DDEClientItem1.DDEItem);
end
else
ShowMessage(`Chyba pri navazovani spojeni!`);
end;
- Ošetřete událost OnClick tlačítka Button1. Klepnutí na toto tlačítko způsobí poslání serveru makro s textem VYMAZ.
procedure TForm1.Button1Click(Sender: TObject);
begin
if DdeClientConv1.ExecuteMacro(`vymaz`, False) = True then
ShowMessage(`Makro bylo uspesne prijato serverem.`)
else
ShowMessage(`Chyba pri prijmu makra!`);
end;
- Ošetřete událost OnClick tlačítka Button3. Klepnutí na toto tlačítko způsobí ukončení spojení se serverem:
procedure TForm1.Button3Click(Sender: TObject);
begin
DdeClientConv1.CloseLink;
end;
- Nyní nás čeká nejzajímavější (avšak vlastně nejjednodušší)úkol: ošetření událostí OnChange jednotlivých položek (komponent DdeClientItem). Začneme první položkou – DdeClientItem1. V obsluze této události vložíme text položky do nápisu; tím zajistíme, že při každé změně položky dojde ihned k bezprostřední aktualizaci nápisu:
procedure TForm1.DdeClientItem1Change(Sender: TObject);
begin
Label1.Caption := DdeClientItem1.Text;
end;
- Druhou položkou, jejíž OnChange nás zajímá, bude DdeClientItem2. Otestujeme, zda obsahem této položky je číslo 1 a pokud ano, přidáme aktuální údaj do seznamu:
procedure TForm1.DdeClientItem2Change(Sender: TObject);
begin
if DdeClientItem2.Text = `1 ` then
ListBox1.Items.Add(Label1.Caption);
end;
- Poslední položkou je DdeClientItem3. Její změna (aktuální hodnota musí být jedna) způsobí vymazání seznamu:
procedure TForm1.DdeClientItem3Change(Sender: TObject);
begin
if DdeClientItem3.Text = `1 ` then
ListBox1.Clear;
end;
Tím je klient hotov. Pro úplnost si opět uvedeme jeho kompletní zdrojový kód:
unit Hlavni;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DdeMan, StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
ListBox1: TListBox;
Button1: TButton;
Button2: TButton;
Button3: TButton;
DdeClientConv1: TDdeClientConv;
DdeClientItem1: TDdeClientItem;
DdeClientItem2: TDdeClientItem;
DdeClientItem3: TDdeClientItem;
procedure Button2Click(Sender: TObject);
procedure DdeClientItem1Change(Sender: TObject);
procedure DdeClientItem2Change(Sender: TObject);
procedure DdeClientItem3Change(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button2Click(Sender: TObject);
begin
if DdeClientConv1.SetLink(`prjDDEServer`, `DdeServerConv1`) = True then begin
ShowMessage(`Spojeni uspesne navazano.`);
DdeClientItem1.DdeItem := `DdeServerItem1`;
DdeClientItem2.DdeItem := `DdeServerItem2`;
DdeClientItem3.DdeItem := `DdeServerItem3`;
DdeClientConv1.RequestData(DDEClientItem1.DDEItem);
end
else
ShowMessage(`Chyba pri navazovani spojeni!`);
end;
procedure TForm1.DdeClientItem1Change(Sender: TObject);
begin
Label1.Caption := DdeClientItem1.Text;
end;
procedure TForm1.DdeClientItem2Change(Sender: TObject);
begin
if DdeClientItem2.Text = `1 ` then
ListBox1.Items.Add(Label1.Caption);
end;
procedure TForm1.DdeClientItem3Change(Sender: TObject);
begin
if DdeClientItem3.Text = `1 ` then
ListBox1.Clear;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if DdeClientConv1.ExecuteMacro(`vymaz`, False) = True then
ShowMessage(`Makro bylo uspesne prijato serverem.`)
else
ShowMessage(`Chyba pri prijmu makra!`);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
DdeClientConv1.CloseLink;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.Caption := `DDE klient`;
Form1.Width := 200;
Form1.Height := 350;
Form1.Top := 300;
Form1.Left := 400;
Button1.Caption := `Vymaz server`;
Button2.Caption := `Pripoj`;
Button3.Caption := `Odpoj`;
Label1.Caption := ``;
end;
end.
Program uložte, přeložte a spusťte. Zkuste si různé pořadí spouštění klienta a serveru, vyzkoušejte si navazování spojení, posílání makra i posílání dat ze serveru. Je samozřejmě možné spustit více klientů zároveň a kochat se pohledem na to, jak je server dokáže všechny obhospodařit:-))
Sledování DDE komunikace
Pokud bychom se technologií DDE komunikací zabývat „vážněji“, potřebovali bychom nástroj, který by dokázal (na úrovni celého systému) sledovat veškerou DDE komunikaci. Hodilo by se nám to už kvůli ladění – proč klient dostal jiná data než měl server poslat? Kde je chyba? V klientu? V serveru?
V tomto ohledu nám bohužel Borland a Delphi příliš nepomůže a musíme se porozhlédnout u konkurence. Máte-li instalováno Microsoft Visual Studio, máte vyhráno. V adresáři Common\Tools\WinNT najdete program DdeSpy.exe. Pomocí tohoto nástroje je možné velmi jednoduše a efektivně sledovat veškeré DDE rozhovory probíhající aktuálně v systému. Základní obrazovku DdeSpy vidíte na následujícím obrázku:
Do tohoto okna se posléze budou vypisovat všechny informace o jednotlivých položkách DDE, které si aplikace vyměňují. V hlavní nabídce programu je možné nastavit celou řadu vlastností týkajících se množství údajů, které má DdeSpy sledovat a míst, kam má zjištěné informace (záznamy o komunikaci) zapisovat. Pro naše účely vyberte v nabídce Output pouze Screen a v nabídce Monitor zaškrtněte všechno, co jde:-)
Abyste se s ním lépe seznámili, zkusíme jej použít na komunikaci mezi námi vytvořeným klientem a serverem. Spusťte tedy server i klienta a navažte spojení (klepnutím na Pripoj). Hned v tom okamžiku „prolétne“ systémem celá řada DDE informací; zorientování v záznamech programu DdeSpy zabere nějaký čas, nicméně v zásadě je realizovatelné:-)
Součástí DdeSpy jsou také další nástroje, které umožňují sledovat jen vybrané informace. Vyberete-li např. z hlavní nabídky položku Track a v ní Conversations, otevře se další okno, jehož obsahem bude přehled všech probíhajících konverzací, příklad viz obrázek:
DDE klientem je Microsoft Word
Na závěr si ukážeme malou perličku, která demonstruje další možnosti technologie DDE. Přestože ovládání aplikací Microsoft Office je samozřejmě možné také pomocí novějších technologií (typicky OLE Automation), i DDE umožňuje zajímavá kouzla:-)
Abychom si jedno z nich mohli předvést, je nutné mírně upravit funkčnost našeho DDE serveru (který jsme vytvořili v předcházejícím dílu). Upravíme pouze obsluhu události OnClick tlačítka Button1. Dosud se po klepnutí na toto tlačítko pouze nastavil text editačního pole do položky serveru; nyní přidáme kód zajišťující zkopírování tohoto textu do schránky systému Windows. Pozor: abychom mohli používat objekt Clipboard, je nutné do sekce Uses připsat modul Clipbrd!
procedure TForm1.Button1Click(Sender: TObject);
begin
DdeServerItem2.Text := `1`;
Clipboard.Open;
Clipboard.AsText := DdeServerItem1.Text;
DdeServerItem1.CopyToClipboard;
Clipboard.Close;
end;
Všimněte si několika maličkostí:
- Komponenta DdeServerItem obsahuje metodu CopyToClipboard, je tedy velmi jednoduché umístit položku do schránky.
- Do schránky jsme ovšem neumístili jen text položky, ale i informaci o vazbě. Ve schránce jsou tedy data i vazba na položku serveru.
Nyní můžeme do aplikace (např. MS Word) vložit propojení na tuto položku DDE serveru, takže jakákoliv změna položky na serveru se ihned promítne i v klientech, které tuto vazbu vložily.
Spusťte tedy klienta a Microsoft Word. Na serveru klepněte na Potvrď. Tím se umístily informace do schránky. Ve Wordu otevřete nový dokument a z nabídky vyberte Úpravy – Vložit jinak... Otevře se následující (nebo podobný) dialog:
Vyberte Vložit propojení a jako typ zvolte např. Neformátovaný text. Nyní dojde k vložení vazby na položku DDE serveru. Když budete na serveru editovat text v editačním poli, v dokumentu MS Wordu se budou všechny změny ihned objevovat:
Na závěr o DDE
V tomto okamžiku jsme definitivně uzavřeli kapitolu DDE. Na závěr bych rád ještě jednou zdůraznil, že DDE v současnosti není příliš progresivní metoda, neboť nastupují novější, propracovanější technologie – Ole Automation a jiné technologie založené na COM. Všemi se však budeme v našem seriálu zabývat, takže tento popis DDE berte spíše jako demonstraci toho, co vše je (bylo) možné v Delphi velmi jednoduše vytvořit, jako úvod do složitější problematiky a jako základní materiál pro pochopení fungování architektury klient/server.
Končí tento seriál?
V žádném případě seriál nekončí … nicméně bude na nějaký čas přerušen. Důvodem tohoto kroku není nedostatek aktuálních témat: při této příležitosti se veřejně omlouvám všem čtenářům, kterým jsem v emailu nebo přímo v diskusi slíbil popis některé problematiky a tento slib nenaplnil. Uvědomuji si, že těchto případů je celá řada a že jsem v tomto smyslu zatím poněkud zklamal.
Důvod dočasného ukončení (hovořme raději o přerušení) seriálu je zcela pragmatický a spočívá v mé nepřítomnosti, jež nastane v několika následujících měsících; nejsem si také jist, zda budu mít ve své cílové destinaci dostatečné možnosti přístupu k Delphi.
Z toho důvodu právě dočítáte díl, který bude zhruba na 3 měsíce dílem posledním. Návrat předpokládám koncem září, proto – bude-li o něco takového zájem – můžete začátkem října očekávat energický příval nových dílů:-) Jedním z prvních témat by měly být databázové možnosti v Delphi 6 (přesněji řečeno – jak psát databáze jinak než přes BDE).
Dovoluji si tedy popřát Vám příjemné léto protkané nezapomenutelnými zážitky s Delphi i s čímkoliv jiným:-)