24. Dynamickß v²m∞na dat
  1. DDE (Dynamic Data Exchange) umo₧≥uje dv∞ma aplikacφm z°φdit spojenφ a pou₧φvat jej pro p°enos dat (komunikovat formou rozhovoru). Jedna z aplikacφ ·Φastnφcφ se rozhovoru je oznaΦovßna jako server a druhß jako klient. Server vlastn∞ informace poskytuje; klient je aplikace, kterß proces °φdφ. Ka₧dß aplikace m∙₧e p∙sobit jako server pro vφce klient∙ nebo jako klient pro vφce server∙ a takΘ souΦasn∞ jako klient i server.

  2. ┌loha serveru je v podstat∞ posφlat data klientovi. Role klienta spoΦφvß v zahßjenφ rozhovoru, po₧ßdßnφ serveru o data nebo po₧ßdßnφ serveru o provedenφ p°φkaz∙ (execute). Jakmile je rozhovor aktivnφ, m∙₧e klient po₧ßdat server o data (request) nebo spustit avizovan² cyklus. To znamenß, ₧e klient m∙₧e po₧ßdat server, aby jej informoval o ka₧dΘ zm∞n∞ urΦitΘ Φßsti dat. Server doruΦφ bu∩ oznßmenφ nebo novou kopii dat p°i ka₧dΘ jejich zm∞n∞. Pro urΦenφ serveru a p°edm∞tu v²m∞ny dat pou₧φvß DDE t°i prvky: Service je v zßsad∞ nßzev aplikace serveru DDE. M∙₧e to b²t nßzev spustitelnΘho souboru (bez p°φpony), avÜak m∙₧e jφt i o jin² nßzev urΦen² p°φmo serverem. Topic je globßlnφ tΘma rozhovoru. M∙₧e to b²t datov² soubor, okno serveru nebo cokoliv jinΘho. Rozhovor DDE je mezi klientem a serverem navßzßn o urΦitΘm tΘmatu. Item je identifikßtor urΦitΘho datovΘho prvku. M∙₧e se jednat o polo₧ku databßze, bu≥ku tabulky. Pomocφ jednoduchΘho rozhovoru si mohou klient a server vym∞≥ovat ·daje o mnoha polo₧kßch.
    Nejprve se pokusφme vytvo°it pravd∞podobn∞ nejjednoduÜÜφ mo₧n² server, kter² bude p°ipojen k nejjednoduÜÜφmu mo₧nΘmu klientovi. Server naÜeho p°φkladu (aplikaci nazveme PRVSERV) obsahuje editaΦnφ komponentu a komponentu DdeServerItem. Pro editaΦnφ komponentu vytvo°φme obsluhu udßlosti OnChange, kterß je tvo°ena p°φkazem (p°i ka₧dΘ zm∞n∞ obsahu editaΦnφho ovladaΦe je jeho obsah p°ekopφrovßn do vlastnosti Text komponenty DdeServerItem):
    DdeServerItem1->Text = Edit1->Text;
    Tφm je aplikace serveru hotova. Aplikace klienta je jen nepatrn∞ slo₧it∞jÜφ. Formulß° zde obsahuje komponenty DdeClientConv, DdeClientItem, editaΦnφ ovladaΦ a tlaΦφtko (s textem P°ipojit). Vlastnost DdeConv u DdeClientItem nastavφme na DdeClientConv1. V dob∞ nßvrhu neexistuje ₧ßdnΘ spojenφ mezi DdeClientConv a serverem. Spojenφ je inicializovßno po stisku tlaΦφtka (obsluha jeho stisku je tvo°ena p°φkazy):
    if (DdeClientConv1->SetLink("PRVSERV", "Form1")) {
      ShowMessage("Spojeno");
      DdeClientItem1->DdeItem = "DdeServerItem1";
    }
    else ShowMessage("Chyba");
    Je zde volßna metoda SetLink, kterß jako parametry p°ebφrß slu₧bu (nßzev serveru) a tΘma (hlaviΦku formulß°e). Pokud je spojenφ ·sp∞ÜnΘ, nastavφ aplikace vlastnost DdeItem prvku klienta na prvek serveru. Kdy₧ je spojenφ navßzßno a vazba je aktivnφ, zaΦne server aplikace posφlat klientovi data p°i ka₧dΘ zm∞n∞ dat na serveru. Vytvo°φme jeÜt∞ obsluhu OnChange komponenty DdeClientItem. Je tvo°ena p°φkazem:
    Edit1->Text = DdeClientItem1->Text;
    Aplikace klienta je nynφ hotova. Pokud spustφme aplikaci serveru i aplikaci klienta a stiskneme tlaΦφtko P°ipojit je navßzßno spojenφ. VÜe co nynφ zapφÜeme do editaΦnφho ovladaΦe v aplikaci serveru je zobrazeno v editaΦnφm ovladaΦi aplikace klienta. VyzkouÜejte. Ob∞ editaΦnφ komponenty jsou nynφ propojeny pomocφ DDE.
  3. V dalÜφ aplikaci budeme demonstrovat podporu DDE pro kopφrovßnφ a vlepovßnφ. Prvnφm krokem bude vytvo°enφ novΘ verze serveru DDE. Formulß° novΘho serveru obsahuje t°i editaΦnφ ovladaΦe spojenΘ s komponentami DdeServerItem a t°i tlaΦφtka (s texty Kopφruj). Formulß° obsahuje takΘ komponentu DdeServerConv. Do editaΦnφch ovladaΦ∙ vlo₧φme texty: Prvnφ °ßdek, Druh² °ßdek a T°etφ °ßdek. U komponent DdeServerItem nastavφme vlastnost ServerConv na DdeServerConv1. V obsluze udßlosti OnCreate formulß°e jsou p°φkazy:

  4. DdeServerItem1->Text = Edit1->Text;
    DdeServerItem2->Text = Edit2->Text;
    DdeServerItem3->Text = Edit3->Text;
    Obsah editaΦnφch komponent je p°i vytvß°enφ formulß°e zkopφrovßn do odpovφdajφcφch prvk∙ serveru. P°i zm∞n∞ n∞kterΘho editaΦnφho ovladaΦe text musφme op∞t zkopφrovat. Vytvo°φme tedy obsluhy udßlostφ OnChange editaΦnφch ovladaΦ∙. Pro Edit1 obsluhu bude tvo°it p°φkaz (ostatnφ vytvo°te sami):
    DdeServerItem1->Text = Edit1->Text;
    Je nutno vytvo°it i obsluhy stisku tlaΦφtek. Tyto obsluhy jsou op∞t podobnΘ. Pro tlaΦφtko spojenΘ s Edit1 jsou zde p°φkazy:
    Clipboard()->Open();
    Clipboard()->AsText = DdeServerItem1->Text;
    DdeServerItem1->CopyToClipboard();
    Clipboard()->Close();
    Operace kopφrovßnφ prvku okopφruje informaci o vazb∞. Tato informace nejsou vlastnφ data, a je nutno do schrßnky vlo₧it i text. Pokud vytvo°φme pouze vazbu, potom mnoho aplikacφ takovß data nepoznß, proto₧e jsme nespecifikovali ₧ßdnΘ informace ohledn∞ formßtu. S tφmto programem m∙₧eme kopφrovat text jednoho z editaΦnφch ovladaΦ∙ tΘto aplikace a nalepit jej tΘm∞° do libovolnΘho klienta DDE. Nap°. v MS Wordu k nalepenφ slou₧φ p°φkaz ┌pravy | Vlo₧it jinak. Spustφme nßÜ program, zkopφrujeme tlaΦφtkem jeden editaΦnφ ovladaΦ, otev°eme dokument Wordu a zvolφme ┌pravy | Vlo₧it jinak. V zobrazenΘm dialogovΘm okn∞ vybereme Vlo₧it propojenφ a stiskneme OK. Dojde k vlo₧enφ textu, ale p°epneme-li se do naÜeho serveru a zm∞nφme text, pak se tento text zm∞nφ i v dokumentu Wordu.
  5. Nynφ, kdy₧ vidφme, ₧e nßÜ server funguje, m∙₧eme vytvo°it novΘho klienta schopnΘho nalepovat data. Pokud mßme pouze jeden zdroj dat, m∙₧eme z°φdit vazbu v dob∞ nßvrhu. Jestli₧e server DDE b∞₧φ, potom v klientskΘ aplikaci DDE p°i nßvrhu m∙₧eme z°φdit spojenφ p°es dialogovΘ okno DDE Info. Vybereme komponentu DdeClientConv a otev°eme editor vlastnosti DdeService. Zde m∙₧eme nadefinovat po₧adovanΘ spojenφ (zadßme Service a Topic serveru) a stiskneme tlaΦφtko Paste Link, Φφm₧ navß₧eme spojenφ se serverem. Formulß° naÜφ druhΘ klientskΘ aplikace DDE se podobß formulß°i prvnφ klientskΘ aplikace. Namφsto tlaΦφtka P°ipojit jsou zde dv∞ tlaΦφtka s texty Paste a Paste Link. U komponenty DdeClientItem nastavφme vlastnost DdeConv na DdeClientConv1. EditaΦnφ komponenta je op∞t spojena s prvkem klienta. Obsluha OnChange komponenty DdeClientItem je tedy tvo°ena p°φkazem:

  6. Edit1->Text = DdeClientItem1->Text;
    TlaΦφtko Paste prost∞ zkopφruje text schrßnky a zruÜφ spojenφ DDE:
    if (Clipboard()->HasFormat(CF_TEXT)) {
      Edit1->Text = Clipboard()->AsText;
      DdeClientConv1->CloseLink();
    }
    else MessageBeep(0xFFFF);
    Obsluha stisku druhΘho tlaΦφtka obsahuje p°φkazy:
    AnsiString Service, Topic, Item;
    if (Clipboard()->HasFormat(ddeMgr->LinkClipFmt)){
      GetPasteLinkInfo(Service, Topic, Item);
      DdeClientConv1->SetLink(Service, Topic);
      DdeClientItem1->DdeItem = Item;
    }
    else MessageBeep(0xFFFF);
    Nastavenφm t∞chto hodnot je spojenφ automaticky navßzßno, jeliko₧ implicitnφ hodnota vlastnosti ConnectMode klientovy komponenty DdeClientConv je nastavena na ddeAutomatic. Kdy₧ spustφme jak server, tak i klientskou aplikaci, pak m∙₧eme provßd∞t kopie textu z jednoho ze t°φ editaΦnφch ovladaΦ∙ nebo z°φdit vazbu.
  7. DalÜφ typickΘ pou₧itφ DDE je p°edßvßnφ p°φkaz∙ jinΘmu programu. Sprßvce program∙ Windows umo₧≥uje vytvß°et novΘ programovΘ skupiny. Pro komunikaci se sprßvcem program∙ pot°ebujeme na formulß° umφstit konverzaΦnφ komponentu klienta (DdeClientConv), vlastnosti DdeService a DdeTopic nastavit na PROGMAN a pro vytvo°enφ novΘ skupiny provΘst p°φkaz (m∙₧eme jej nap°. umφstit do obsluhy stisku tlaΦφtka):

  8. DdeClientConv1->ExecuteMacro("[CreateGroup(""Nova skupina"")]", false);
    Prvnφ parametr je makro, kterΘ chceme provΘst. VyzkouÜejte.
  9. Dßle vytvo°φme server DDE automaticky m∞nφcφ data. Aplikaci nazveme DATASERV. Aplikace mß jednoduch² formulß°. Obsahuje komponentu Memo s vlastnostφ ReadOnly nastavenou na true (vlo₧φme do nφ p∞t °ßdk∙ s hodnotami 40, 50, 60, 70 a 80 a komponentu zakß₧eme). Formulß° dßle obsahuje komponenty Timer, DdeServerItem a tlaΦφtko s textem Kopφruj. Obsluha ΦasovaΦe bude tvo°ena p°φkazy:

  10. for (int I = 0; I < 5; I++) {
      int Hodnota = StrToIntDef(Memo1->Lines->Strings[I], 50);
      Hodnota = Hodnota + random(21) - 10;
      Memo1->Lines->Strings[I] = IntToStr(Hodnota);
    }
    DdeServerItem1->Lines = Memo1->Lines;
    Nynφ po spuÜt∞nφ aplikace se hodnoty v komponent∞ Memo automaticky m∞nφ. Obsluha stisknutφ tlaΦφtka je tvo°ena p°φkazy (do schrßnky p°ekopφrujeme data i vazbu):
    Clipboard()->Open();
    Clipboard()->AsText = Memo1->Text;
    DdeServerItem1->CopyToClipboard();
    Clipboard()->Close();
    Tφm je aplikace serveru hotova.
  11. Klientskß aplikace obsahuje pouze komponenty DdeClientConv a DdeClientItem (propojφme je). Obsluhu udßlosti OnCreate formulß°e tvo°φ p°φkazy (p°i vytvo°enφ formulß°e je z°φzeno spojenφ):

  12. if (DdeClientConv1->SetLink("DATASERV", "Form1"))
      DdeClientItem1->DdeItem = "DdeServerItem1";
    else ShowMessage("Spus¥ server p°ed klientem!");
    Jako soukromou polo₧ku formulß°e vlo₧φme (pro ulo₧enφ hodnot serveru):
    int Hodnoty[5];
    Aby p°i p°enosu dat ze serveru (p°enßÜφme °et∞zec znak∙) se nep°eskakovaly znaky od°ßdkovßnφ, musφme nastavit vlastnost FormatChars u DdeClientConv na true. Obsluha OnChange komponenty DdeClientItem je tvo°ena p°φkazy (data ze serveru ulo₧φme do naÜeho pole):
    for (int I = 0; I < DdeClientItem1->Lines->Count; I++)
      Hodnoty[I] = StrToIntDef(DdeClientItem1->Lines->Strings[I], 50);
    Invalidate();
    Vlastnφ zobrazovßnφ dat budeme provßd∞t v obsluze OnPaint formulß°e:
    int DX = ClientWidth / 11;
    int DY = ClientHeight / 3;
    float Meritko = DY / 100.0;
    Canvas->Pen->Width = 3;
    Canvas->MoveTo(0, DY * 2);
    Canvas->LineTo(ClientWidth, DY * 2);
    Canvas->Pen->Width = 1;
    Canvas->MoveTo(0, DY);
    Canvas->LineTo(ClientWidth, DY);
    for (int I = 0; I < 5; I++){
      if (Hodnoty[I] > 0) Canvas->Brush->Color = clGreen;
      else Canvas->Brush->Color = clRed;
      Canvas->Rectangle(DX * (2*I+1), DY*2-floor(Hodnoty[I]*Meritko),
                        DX * (2*I+2), DY*2);
    }
    Tφm je klientskß aplikace hotova. M∙₧eme vyzkouÜet zobrazovßnφ dat zφskan²ch ze serveru. Vidφme, ₧e pomocφ DDE m∙₧eme zφskßvat r∙znß data (v∞tÜinou je vhodnΘ p°evΘst je na text).
24. Dynamickß v²m∞na dat