Vytváření komponent v DELPHI. Úvod do vytváření komponent Delphi

Než vytvoříte komponentu, musíte pro ni vybrat předka. Kdo může být předkem vaší součásti?

Obvykle se používá jako předchůdce TComponent, TControl, TWinControl, TGraphicControl, TCustomXXXXXX, stejně jako všech komponent palety komponent.
Vezměme si například komponentu TOpenDialog, která se nachází na stránce Dialogs palety komponent. Svou práci plní dobře, ale má jednu malou nepříjemnost. Pokaždé, když ji použijete, musíte pokaždé změnit hodnotu vlastnosti Options. A zpravidla se jedná o stejné akce.
OpenDialog1.Options:= OpenDialog1.Options + ;

takže soubor, který se pokoušíme otevřít pomocí tohoto dialogového okna, na disku skutečně existuje.
Úkol jsme si již vybrali, zbývá pouze vytvořit komponentu. Přířez pro komponentu vytvoříme tak, že z nabídky vybereme příkaz Komponenta/Nová komponenta... a v dialogovém okně vybereme
Typ předka: TOpenDialog
Název třídy: TOurOpenDialog
Stránka palety: Náš test
Klikli jsme na OK a nyní máme šablonu pro naši budoucí komponentu.

U této komponenty přepíšeme konstruktor, tzn. ve veřejné části vložte řádek:

konstruktor Create(AOwner: TComponent); přepsat;

Kliknutím na tento řádek Ctrl + Shift + C vytvoříme šablonu pro tuto metodu, do které vložíme následující řádky:

zděděno Create(AOwner); (Zavolejte zděděný konstruktor)
Možnosti:= Možnosti + ; (Provádíme akce, které potřebujeme)

Poznámka: Klávesové zkratky Ctrl + Shift + šipky nahoru/dolů umožňují navigaci mezi deklarací metody a její implementací.

Instalace vytvořené komponenty Komponenta/Instalovat komponentu...
Instalovat do nového balíčku
Název souboru balíčku: C:Program FilesBorlandDelphi4LibOurTest.dpk
Popis balíčku: Náš testovaný balíček

Nelíbí se vám, že naše komponenta má stejnou ikonu jako standardní? Tak mu vytvořme vlastní.
K tomu musíme zavolat Tools/Image Editor. Vytvořte nový soubor *.dcr.
Vložte do něj obrázek Resource/New/Bitmap. Nastavte velikost obrázku na 24x24 pixelů. A pak - vaše kreativita...
Pozor: barva teček, která odpovídá barvě tečky v levém dolním rohu obrázku, bude považována za PRŮHLEDNOU!
Jakmile vytvoříte výkres, přejmenujte jej z Bitmap1 na TOurOpenDialog a uložte soubor jako OurOpenDialog.dcr.
Vyjměte komponentu z balíčku a nainstalujte ji znovu (pouze v tomto případě bude přidán odkaz na soubor *.dcr).
Kompilace, instalace a hodně štěstí!

jednotka OurOpenDialog; rozhraní používá Windows, Zprávy, SysUtils, Třídy, Grafika, Ovládací prvky, Formuláře, Dialogy; typ TOurOpenDialog = třída(TOpenDialog) soukromé(soukromá prohlášení) chráněný veřejnost(Veřejná prohlášení) konstruktér Create(AOwner: TComponent); přepsat; zveřejněno konec; postup Registrovat; implementace postup Registrovat; začít RegisterComponents("Vzorky", ); konec; (TOurOpenDialog) konstruktér TOurOpenDialog.Create(AOwner: TComponent); začít zděděno Create(AOwner); (Zavolejte zděděný konstruktor) Options:= Options + ; (Provádíme akce, které potřebujeme) konec; konec.

Deklarace komponenty se skládá z částí, jako je např soukromé, chráněné, veřejné a zveřejněné. Co tím myslí?
Toto jsou směrnice viditelnosti.
Vše, co je deklarováno v sekci soukromé, dostupné pouze uvnitř modulu, ve kterém je třída deklarována (soukromé deklarace). Zde jsou zpravidla deklarovány proměnné, které uchovávají hodnoty vlastností a také metody (procedury nebo funkce) pro přístup k nim.
Vše, co je deklarováno v sekci chráněný, je k dispozici jako v privátní sekci a také pro potomky této třídy (rozhraní pro vývojáře).
Zde můžete deklarovat metody pro přístup k hodnotám vlastností (pokud chcete umožnit potomkům vaší komponenty tyto metody měnit),
stejně jako vlastnosti, metody a události (metody reakce na události) v komponentách typu TCustomXXX.
Vše, co je deklarováno v sekci veřejnost, dostupný každému uživateli komponenty (runtime rozhraní).
Obvykle jsou zde deklarovány metody. V publikované sekci lze deklarovat pouze vlastnosti a události (jsou deklarovány jako vlastnosti).
Jsou k dispozici během návrhu aplikace (rozhraní fáze návrhu).

Vlastnosti

Vlastnosti typu masiv- běžná pole Object Pascal, ale na rozdíl od nich mohou být indexována nejen číselnými hodnotami, ale také řetězci. Bohužel tento typ vlastnosti vyžaduje editor uživatelských vlastností (v Object Inspector má editor vlastností tlačítko se třemi tečkami [...]), takže v příkladu níže vlastnost ArrayProp oznámeno v sekci veřejnost.

typ TOurComponent = třída(TComponent) soukromé( Soukromá prohlášení ) FArrayProp: pole z celé číslo; funkce GetArrayProp(aIndex: integer): integer; postup SetArrayProp(aIndex: integer; konst Hodnota: celé číslo); chráněný(Chráněná prohlášení) veřejnost(Veřejná prohlášení) vlastnictví ArrayProp: celé číslo číst GetArrayProp napsat SetArrayProp; zveřejněno(Zveřejněná prohlášení) konec;

Specifikátory vlastností

Specifikátor výchozí určuje, zda uložit hodnotu vlastnosti do souboru formuláře nebo ne. Pokud se hodnota vlastnosti shoduje s hodnotou výchozí- hodnota v souboru formuláře se neuloží, pokud se hodnoty nerovnají - uloží se. Můžete to zkontrolovat umístěním komponenty na formulář a výběrem položky nabídky "Zobrazit jako text" pravým tlačítkem myši. Výchozí nenastaví počáteční hodnotu vlastnosti na zadanou. To je nutné provést v konstruktoru komponenty.

jednotka Naše Komponenta; rozhraní používá Windows, SysUtils, Třídy, Grafika, Formuláře, Ovládací prvky; typ TOurComponent = třída(TComponent) soukromé( Soukromé deklarace ) FMyInteger: Integer; chráněný(Chráněná prohlášení) veřejnost(Veřejná prohlášení) konstruktér Create(AOwner: TComponent); přepsat; zveřejněno(Zveřejněná prohlášení) vlastnictví MyInteger: Celé číslo číst FMyInteger napsat FMyInteger výchozí 10; konec; implementace konstruktér TOurComponent.Create(AOwner: TComponent); začít zděděno Create(AOwner); FInteger:= 10; konec; konec.

Specifikátor nodefault přepíše výchozí hodnotu vlastnosti. Tento specifikátor se obvykle používá k přepsání výchozí hodnoty zděděné vlastnosti.
Například: vlastnictví Automatická velikost nodefault;

Specifikátor uloženy určuje, kdy uložit hodnotu vlastnosti do souboru formuláře. Po uloženy může stát skutečný(vždy uložit) Nepravdivé(nikdy neukládat) nebo název funkce, která vrací booleovský výsledek.

vlastnictví OneProp: celé číslo číst FOneProp napsat SetOneProp uloženy Nepravdivé; vlastnictví TwoProp: celé číslo číst FTwoProp napsat SetTwoProp uloženy Skutečný; vlastnictví ThreeProp: celé číslo číst FThreeProp napsat SetThreeProp uloženy Fuct;

A poslední věc:
Chcete-li přidat obrázek ke komponentě pro demonstraci v panelu komponenty, musíte: - vytvořit jej o velikosti 24*24 se souborem name.dcr (ve zdroji se název obrázku rovná názvu součást velkými písmeny)
- umístěte obrázek vedle součásti.

Rozvoj software pro OS Windows a další populární lze provádět pomocí různých typů nástrojů. Mezi ty, které jsou mezi ruskými a zahraničními programátory velmi oblíbené, patří program Delphi. Jaká jsou specifika tohoto vývojového nástroje? Jaké jsou jeho nejpozoruhodnější vlastnosti?

Obecné informace o Delphi

Delphi je vývojové prostředí pro aplikační programy, které jsou navrženy pro běh na Windows, MacOS a mobilních zařízeních. operační systémy- iOS a Android. Vyznačuje se jednoduchostí jazyka a procedur generování kódu.

V případě potřeby zajišťuje nízkoúrovňovou komunikaci s OS a knihovnami napsanými v C a C++. Programy vytvořené pomocí Delphi nevyžadují ke spuštění shelly třetích stran, jako je Java Virtual Machine. Delphi je vývojové prostředí, které mohou úspěšně používat jak profesionálové, tak i pro vzdělávací účely. Pro zvládnutí jeho základních schopností není nutné mít vysokou kvalifikaci a znalost složitých programovacích jazyků.

Hlavní výhody

Pojďme si prostudovat, jaké jsou klíčové výhody daného softwarového produktu. Když konkrétní IT společnost zdůvodňuje volbu vývojového prostředí, Delphi se stává volbou mnoha programátorů a je jimi doporučeno k použití. To je způsobeno skutečností, že toto prostředí umožňuje vytvářet aplikace v nejrychlejším možném čase a zajišťuje jejich vysoký výkon i na počítačích, které mají skromné ​​hardwarové vlastnosti. Významným argumentem pro volbu příslušného vývojového prostředí je, že jej lze doplnit o nové nástroje, které standardní sada řešení přítomná v rozhraní Delphi neposkytuje.

Podívejme se nyní na nuance praktického využití schopností Delphi.

Specifika rozhraní

Nejprve můžete věnovat pozornost některým funkcím rozhraní daného prostředí pro vývoj softwaru. Struktura pracovní plochy programu tedy zahrnuje současnou práci s několika hlavními okny. Podívejme se na tuto vlastnost podrobněji.

Vývojové prostředí Delphi, konkrétně verze 7, zahrnuje použití následujících klíčových modulů: návrhář formulářů, editor, paleta, inspektor objektů a referenční příručka. V některých modifikacích Delphi mohou být označené komponenty pojmenovány jinak. Například editor může odpovídat oknu programového kódu a návrhář může odpovídat oknu formuláře. nicméně funkční účel jejich bude stejný. Označené Delphi může doplňovat různé pomocné nástroje. První dva jsou považovány za hlavní z hlediska postupů tvorby programu. Ale zbytek je také důležitý. Podívejme se na vlastnosti používání označených modulů Delphi.

Návrhář formulářů, editor a paleta

S pomocí návrháře formulářů vytvoří vývojář rozhraní svého programu. Jeho kód je zase zapsán v editoru. Mnoho programátorů, kteří doporučují zvolit jako nejoptimálnější řešení vývojové prostředí Delphi, uvádí jako argument snadnost použití návrháře formulářů. Někteří odborníci se domnívají, že tento proces připomíná spíše hru.

Jakmile uživatel začne vytvářet program a spustí návrhář formulářů, zpočátku v něm nejsou žádné prvky, je prázdný. Okamžitě jej ale můžete vyplnit pomocí nástrojů umístěných na jiném modulu Delphi – paletě. Prvky rozhraní programu, které se konfigurují v návrháři formulářů, musí být řízeny příkazy, které se zase zapisují v editoru.

Ale vraťme se zatím k paletce. Pomocí něj můžete umístit potřebné objekty do oblasti návrháře formulářů. Chcete-li použít konkrétní nástroj, měli byste na něj kliknout jednou – když je v oblasti palety, a podruhé – v okně návrháře formulářů. Poté se odpovídající objekt přesune do vývojové oblasti a můžete pro něj napsat kód v editoru.

Inspektor objektů

Dalším významným prvkem, který Delphi, aplikační vývojové prostředí pro Windows a další běžné platformy, obsahuje, je objektový inspektor. Můžete si všimnout, že se v něm zobrazené informace mění: to je ovlivněno stavem objektu, který je vybrán v oblasti návrháře formulářů.

Struktura inspektora objektu je následující. Skládá se ze dvou oken. Každý z nich obsahuje algoritmy, které určují chování odpovídajících komponent. První zobrazuje vlastnosti, druhý zobrazuje události. Pokud chce programátor provést úpravy v algoritmech, které ovlivňují konkrétní komponentu, použijí se možnosti inspektoru objektů. Můžete například změnit umístění určitých prvků rozhraní programu, jejich výšku a šířku.

Inspektor objektů má karty, které umožňují přepínat mezi stránkami zobrazujícími vlastnosti nebo události, které přímo souvisejí s editorem. Pokud tedy dvakrát kliknete na pravou stranu libovolné položky zobrazené na obrazovce, v editoru se zaznamená kód, který odpovídá konkrétní události.

Vývoj softwaru v Delphi zahrnuje použití Object Inspector k řešení různých problémů. To je předurčeno tím, že pomocí tohoto nástroje můžete měnit vlastnosti prakticky libovolných objektů umístěných na formuláři, ale i formuláře samotného. Podívejme se blíže na některé funkce práce s objektovým inspektorem.

Inspektor objektů: Používání funkcí

Abyste pochopili, jak IDE Delphi funguje z hlediska interakce mezi Object Inspectorem a Form Inspectorem, můžete zkusit změnit vlastnosti některých běžných prvků softwarového rozhraní ve Windows – například Memo, Button a Listbox (budeme prozkoumat jejich podstatu podrobněji o něco později). Nejprve je musíte umístit do formuláře pomocí dostupných nástrojů Delphi.

Můžete zkusit experimentovat s vlastností Ctl3D. Chcete-li to provést, musíte kliknout na formulář, poté přejít do inspektoru objektů a změnit hodnotu příslušné vlastnosti. Poté se forma výrazně změní a zároveň se změní vlastnost Ctl3D na každém z prvků, které jsou umístěny v návrhovém okně.

Po provedení experimentů se můžeme vrátit zpět do formuláře a aktivovat hodnotu Ctl3D. Poté se podívejme na prvky Memo a Listbox. Nyní můžete změnit jejich vlastnosti, umístění na formuláři a vzhled. Například výběrem možnosti Upravit v položce nabídky a poté Velikost může programátor změnit šířku a výšku objektů. Existuje možnost je vycentrovat výběrem Upravit a Zarovnat. Odpovídající akce ovlivní prvky zobrazené v Inspektoru objektů.

Pomocí příslušného modulu Delphi můžete měnit vlastnosti komponent. Pokud je tedy například úkolem určit pro ně konkrétní barvu, pak existují možnosti použití několika nástrojů najednou. Nejprve můžete zadat příkaz odpovídající barvě - například červená - clRed - do oblasti Za druhé si uživatel může vybrat požadovanou barvu ze seznamu. Do třetice je zde možnost poklepat na Vlastnosti barvy – zobrazí se okno pro výběr barvy. Podobně může vývojář měnit další atributy objektů – například typ písma, jeho barvu nebo velikost.

Adresář

Delphi je vývojové prostředí, které je doplněno poměrně podrobným systémem nápovědy. Chcete-li jej otevřít, vyberte z nabídky položku Nápověda. Poté se v okně zobrazí jeden z těch, které jsme si poznamenali výše. softwarových modulů vývojové prostředí - referenční kniha. Zvláštností jeho použití je, že když stisknete F1, uživatel obdrží konkrétní nápovědu odrážející specifika používání aktuálního nástroje. Pokud například programátor pracuje s Inspektorem objektů, může vybrat jednu z vlastností, poté stisknout F1 a získat nápovědu k příslušné možnosti. Totéž lze provést při práci s jakýmkoli jiným prvkem rozhraní, který zahrnuje vývojové prostředí Delphi 7 a další verze odpovídajícího typu softwaru.

Další prvky rozhraní

Mezi další významné součásti příslušného rozhraní softwarové řešení- menu, panel rychlý přístup a také editor obrázků. Pokud jde o menu, umožňuje programátorovi rychlý přístup k potřebným komponentám přítomným ve struktuře vývojového prostředí. Můžete jej použít buď pomocí myši, nebo pomocí horkých kláves. Hned pod nabídkou je panel rychlého přístupu. Některé jeho funkce duplikují funkce nabídky, ale přístup k nim je rychlejší. Delphi je trochu podobný programu Malování ve Windows. To znamená, že s jeho pomocí můžete provádět jednoduché úpravy obrázků, vkládat na ně nápisy a další prvky.

Programovací nástroje

Delphi je vývojové prostředí, které obsahuje velké množství nástrojů určených ke zlepšení produktivity programátorů. Klíčové moduly, o kterých jsme hovořili výše, jsou tedy doplněny sadou speciálních nástrojů. Patří mezi ně debugger, kompilátor a také komponenty WinSight a WinSpector. Všimněte si, že v některých verzích Delphi musí být označené prvky nainstalovány samostatně. Pojďme studovat jejich specifika.

Debugger Delphi

Pokud jde o debugger, tento nástroj doplňuje editor kódu z hlediska provádění nezbytných kontrol správnosti odpovídajících softwarových algoritmů. S ním může vývojář skutečně zkoumat svůj zdrojový kód řádek po řádku. V některých případech, při řešení úkolu, jako je vývoj komponent, může být Delphi jako nezávislý produkt doplněn o externí debugger, který dává programátorovi rozšířené možnosti pro kontrolu kódu vytvářeného softwaru.

Kompilátor Delphi

Podívejme se nyní na specifika kompilátoru daného vývojového prostředí. Všimněte si, že ve struktuře Delphi může být několik odpovídajících prvků. Je zde tedy možnost využít DCC kompilátor, což je užitečné v případech, kdy je úkolem pracovat s aplikací v externím debuggeru.

Winsight a WinSpector

Uvedené moduly jsou ty, které je třeba dodatečně nainstalovat do Delphi. Vyznačují se relativní náročností na zvládnutí. Mnoho programátorů, kteří se rozhodli pro vývojové prostředí Delphi, se však domnívá, že se tyto komponenty musí naučit používat. Modul Winsight se tedy používá ke sledování zpráv systému Windows. K zaznamenání stavu počítače do speciálního souboru je zapotřebí komponenta, jako je WinSpector. Pokud během vývoje softwaru narazíte na nějaké problémy, můžete tento soubor kdykoli otevřít a zjistit, co by mohlo být příčinou problému.

Standardní komponenty

Vývojové prostředí Delphi, o kterém se obecně učíme, obsahuje řadu standardních komponent, o kterých je také užitečné vědět. Odborníci je klasifikují jako: MainMenu, PopupMenu, Label, Edit, Memo, Button, Checkbox, Radiobutton, Listbox, Combobox, Scrollbar, Groupbox, Panel a Scrollbox. Pojďme si jejich specifika prostudovat podrobněji.

Komponenta MainMenu je určena k umístění hlavní nabídky do rozhraní vytvořeného programu. Chcete-li to provést, musíte umístit odpovídající prvek do formuláře, poté zavolat vlastnost Items prostřednictvím inspektoru objektů a poté určit potřebné položky nabídky.

Komponenta PopupMenu je určena k umístění vyskakovacích nabídek do rozhraní vytvořeného programu, tedy těch, které se otevírají kliknutím pravým tlačítkem myši.

Komponenta Label slouží k zobrazení textu v okně programu. Lze jej přizpůsobit, například nastavením požadovaného písma v inspektoru objektů.

Komponenta Upravit se používá k zobrazení části textu na obrazovce, kterou může uživatel upravovat za běhu programu. Doplňuje ji komponenta Memo, kterou lze zase použít pro práci s rozsáhlejšími texty. Tento prvek zahrnuje například možnosti, jako je kopírování textu.

Komponenta Button je navržena tak, aby provedla určité akce stisknutím tlačítka, když je program spuštěn. Na formulář je nutné umístit odpovídající prvek a poté zadat požadovaný programový kód.

Komponenta Checkbox umožňuje zobrazit řádky na obrazovce pomocí malého okna, do kterého lze pomocí myši umístit zaškrtávací políčko. Podobným prvkem je Radiobutton. Liší se za prvé, vzhled- druhá součást je vyrobena ve formě kruhu a za druhé, první prvek umožňuje současný výběr několika možností, Radiobutton - pouze jedna.

Komponenta Listbox se používá k zobrazení seznamu na obrazovce, ve kterém může uživatel procházet pomocí myši. Další prvek, Combobox, je mu do jisté míry podobný, ale je doplněn o možnost zadávat text do speciálního pole.

Komponenta Scrollbar je posuvná lišta v oknech. Obvykle se automaticky zobrazí, jakmile se textový prostor nebo formulář s objekty zvětší než okno.

Komponenta Groupbox slouží k zaznamenání pořadí, ve kterém se pohybujete mezi okny při stisknutí klávesy TAB. Lze doplnit o prvek Panel, kterým lze ve formuláři přesouvat více objektů.

Komponenta Scrollbox umožňuje opravit oblast na formuláři, kterou lze posouvat vodorovně i svisle. Tato vlastnost standardně charakterizuje hlavní vývojová okna Delphi. Pokud je ale potřeba povolit takovou možnost v určité části formuláře, můžete použít komponentu Scrollbox.

souhrn

Delphi je výkonné prostředí pro vývoj aplikací, které se zároveň vyznačuje snadným používáním svých základních funkcí. S pomocí nástrojů, které jsou součástí jeho struktury, můžete vytvořit maximum odlišné typy programy pro Windows a další populární operační systémy.

Výběr vývojových nástrojů Delphi mnoha programátory je dán snadností použití rozhraní odpovídajícího softwaru a také širokou škálou nástrojů užitečných pro práci v jakékoli fázi tvorby programu - ve fázi návrhu, programování algoritmů nebo ladění.


Vývoj vlastních komponent

Pokud nejste spokojeni se standardními součástmi, které se dodávají s Delphi, pak je čas, abyste si zkusili vytvořit své vlastní. Začneme nejprve jednoduchými a postupně přejdeme ke složitějším. Takže, začněme.

Před vytvořením komponenty je důležité vybrat pro ni správného předka. Kdo může být předkem vaší součásti? Obvykle se používá jako předchůdce TComponent, TControl, TWinControl, TGraphicControl, TCustomXXXXXX, stejně jako všech komponent palety komponent. Vezměme si například komponentu TOpenDialog, která se nachází na stránce Dialogs palety komponent. Svou práci plní dobře, ale má jednu malou nepříjemnost. Pokaždé, když ji použijete, musíte pokaždé změnit hodnotu vlastnosti Options. A zpravidla se jedná o stejné akce.


Kliknutím na tento řádek Ctrl + Shift + C vytvoříme šablonu pro tuto metodu, do které vložíme následující řádky:


Instalace vytvořené komponenty Komponenta/Instalovat komponentu...

  • Instalovat do nového balíčku
  • Název souboru balíčku: C:\Program Files\Borland\Delphi4\Lib\OurTest.dpk
  • Popis balíčku: Náš testovaný balíček

Nelíbí se vám, že naše komponenta má stejnou ikonu jako standardní? Tak mu vytvořme vlastní. K tomu musíme zavolat Tools/Image Editor. Vytvořte nový soubor *.dcr. Vložte do něj obrázek Resource/New/Bitmap. Nastavte velikost obrázku na 24x24 pixelů. A pak – vaše kreativita... Pozor: barva teček, která odpovídá barvě tečky v levém dolním rohu obrázku, bude považována za PRŮHLEDNOU!

Jakmile vytvoříte výkres, přejmenujte jej z Bitmap1 na TOurOpenDialog a uložte soubor jako OurOpenDialog.dcr. Vyjměte komponentu z balíčku a nainstalujte ji znovu (pouze v tomto případě bude přidán odkaz na soubor *.dcr).

Kompilace, instalace a hodně štěstí!

Profesionální vývoj aplikací s Delphi 5 | Vývojové nástroje | ComputerPress 2"2001

Vytváření komponent Delphi

Úvod do vytváření komponent Delphi

Při vývoji aplikací pomocí Borland Delphi je vhodné vytvářet komponenty z následujících důvodů:

  1. Snadnost použití. Komponenta je umístěna na formuláři a musíte pro ni nastavit hodnoty vlastností a napsat kód obsluhy události. Pokud se tedy v projektu vyskytne jakákoli kombinace ovládacích prvků a s nimi spojených obslužných rutin událostí na dvou místech, pak má smysl přemýšlet o vytvoření odpovídající komponenty. Pokud se kombinace ovládacích prvků a s nimi spojených obslužných rutin událostí vyskytuje více než dvakrát, pak vytvoření komponenty zaručeně ušetří námahu při vývoji aplikace.
  2. Jednoduchá organizace vývoje skupinového projektu. Při skupinovém vývoji lze jednotlivé části projektu definovat jako komponenty a práci přidělit různým programátorům. Komponenty lze ladit odděleně od aplikace, což je docela snadné.
  3. Jednoduché a účinná metoda sdílení kódu s ostatními programátory. Existuje mnoho stránek, například http://www.torry.net/, kde můžete najít volně distribuované komponenty nebo je zakoupit za symbolický poplatek.

Balíčky funkcí

V Delphi jsou komponenty uloženy v balíčcích. Seznam použitých balíčků komponent lze vyvolat pomocí položky nabídky Komponenta/Instalovat balíčky (avšak z nějakého důvodu má tento dialog název Možnosti projektu).

Pomocí tohoto dialogu můžete přidat nový balíček (Přidat) nebo odstranit stávající (Odstranit). Smazání neznamená fyzické smazání souboru z disku, ale spíše odstranění odkazu z vývojového prostředí na tento balíček. Když přidáte nový balíček, komponenty v něm uložené se objeví na paletě, ale když jej smažete, naopak zmizí. Místo smazání balíčku můžete jeho obsah ve fázi vývoje „skrýt“ zrušením zaškrtnutí názvu balíčku v seznamu. Můžete také zobrazit komponenty a jejich ikony (Components). Nakonec můžete upravovat balíčky přidané uživatelem (Upravit) - balíčky dodávané s Delphi nelze upravovat (tlačítko Upravit je zašedlé).

V tomto dialogu můžete určit, jak vytvořit projekt: pomocí runtime balíčků nebo bez nich. Z toho je zřejmé, že existují dva typy balíčků komponent: runtime package (balíček, který funguje za běhu) a design-time package (balíček používaný během vývoje). Jsou to všechny knihovny DLL (dynamicky načítané knihovny).

Běhové balíčky (přípona *.bpl) jsou koncovému uživateli doručeny spolu s projektem, pokud byl projekt zkompilován s povolenou volbou Sestavit s běhovými balíčky. Samotná aplikace (*.exe nebo *.dll) se v tomto případě ukazuje jako malá, ale s ní musí být přeneseny spíše velké soubory *.bpl. Doručování projektu s runtime balíčky dává podle odborníků výhodu v objemu dodávaných souborů, pouze pokud obsahuje pět a více modulů (*.exe nebo *.dll) napsaných v Delphi. Když tyto moduly spolupracují, šetří se prostředky operačního systému, protože jeden balíček načtený do paměti RAM obsluhuje několik modulů.

Design-time balíčky (přípona *.dcp) se používají pouze ve fázi vývoje. Při vývoji podporují tvorbu komponent na formuláři. Kompilovaný projekt Delphi obsahuje kód nikoli z balíčku komponent, ale ze souborů *.dcu. Přestože je soubor *.dcp generován ze souboru *.dcu, jeho obsah nemusí být stejný, pokud byly v souboru *.pas provedeny změny a balíček nebyl znovu zkompilován. Kompilace je možná pouze pro balíčky vytvořené programátory. Toho dosáhnete kliknutím na tlačítko Upravit ve výše uvedeném dialogu. Poté se objeví formulář, který vám umožní manipulovat s balíčkem.

Balení obsahuje dvě části. Část Obsahuje obsahuje seznam modulů, které tvoří součásti tohoto balíčku (soubory *.pas- a *.dcu-) a jejich ikony (soubory *.dcr). Sekce Povinné obsahuje odkazy na další balíčky potřebné pro fungování těchto komponent. Přidání nové komponenty do balíčku se provádí tlačítkem Přidat a odstranění existující pomocí tlačítka Odebrat. Dokud není balíček zkompilován kliknutím na tlačítko Compile, žádné změny provedené v balíčku se ve vývojovém prostředí nezobrazí. Nakonec je příkaz Install dostupný, když byl obsah balíčku odstraněn z vývojového prostředí zrušením zaškrtnutí názvu balíčku v předchozím dialogu.

Příkaz Option vám umožňuje vybrat možnosti pro kompilaci balíčku, které jsou podobné možnostem projektu. Ty lze použít k určení, jaký typ balíčku je daný balíček: run-time, design-time nebo obojí (výchozí typ balíčku). Možnosti definují adresáře, ve kterých se mají vyhledat potřebné moduly a uložit výsledky kompilace. Definují také akce potřebné pro ladění: zda se má či nemá kontrolovat rozsah přijatelných hodnot, jak provádět optimalizace, jak zacházet s chybami I/O. Nakonec mohou volby obsahovat informace o verzi balíčku. To je velmi důležité, pokud je aplikace distribuována spolu s runtime balíčky: při spuštění instalačního programu vám informace o verzi umožní správně nahradit zastaralé verze balíčků a naopak, pokud se pokusíte nainstalovat balíček starší verze, než je jeden již dostupný na daném počítači, druhý nebude přepsán.

Šablony součástí

Delphi vám umožňuje vytvářet jednoduché kompozitní komponenty z několika běžných komponent vybraných na formuláři v době návrhu. Pomocí položky nabídky Components/Create Component Template zavoláte příslušného experta. Tato položka nabídky je dostupná, pokud je ve formuláři vybrána alespoň jedna komponenta. Po jeho výběru se zobrazí dialogové okno Informace o šabloně součásti.

V tomto dialogu byste měli zadat název třídy a název stránky na paletě komponenty, kam má být nová komponenta umístěna. Pokud stránka s tímto názvem není na paletě komponent, bude vytvořena. Můžete také změnit navrhovanou ikonu pro novou komponentu nahráním vhodného souboru *.bmp.

Když je vytvořena šablona, ​​zapamatují se jak vlastnosti změněné programátorem v Object Inspector, tak i obslužné rutiny událostí spojené s vybranými ovládacími prvky. V tomto případě jsou obslužné rutiny událostí zapamatovány zcela, bez filtrování volání jiných (nevybraných ve formuláři) komponent, globálních proměnných, metod atd. Pokud tedy takové komponenty (proměnné, metody) chybí v jiném projektu, pak při pokusu o kompilaci takového projektu bude přijata diagnostická zpráva Neznámý identifikátor.

Kdy byste měli používat šablony? Především v případech, kdy je potřeba změnit jakékoli vlastnosti, které jsou standardně dostupné v základní třídě. Aplikace například používá ovládací prvek k úpravě řádku žlutého textu. Komponentu TEdit můžete umístit na formulář, změnit vlastnost Color na žlutou, označit tuto komponentu a uložit jako šablonu. Poté budete mít přístup k této šabloně a součást umístěná na formuláři bude mít žlutou barvu. Tuto příležitost byste však neměli zneužívat, protože pro ovládací prvek bude vytvořena nová třída se změněnou barvou a všechny virtuální metody budou duplikovány v paměti. To bude mít negativní dopad na zdroje operačního systému.

Je také vhodné použít šablony komponent, když potřebujete přenést několik komponent spolu s obsluhou událostí z jednoho formuláře do druhého. K tomu se všechny vyberou, vytvoří se šablona součásti, která se umístí na nový formulář. V tomto případě se přenesou nejen samotné komponenty, ale také obslužné rutiny událostí, čehož nelze dosáhnout při volání příkazů Kopírovat/Vložit – v druhém případě se obslužné rutiny událostí ztratí.

Komponenty vytvořené pomocí příkazu Create Component Template se značně liší od běžných komponent vytvořených pomocí standardní metody (popsané níže). Vizuálně je hlavní rozdíl tento: pokud šablona obsahuje několik ovládacích prvků, můžete po umístění takové komponenty na formulář vybrat jednotlivý ovládací prvek a odstranit jej - zatímco zbytek zůstane na formuláři. U standardních komponent, pokud obsahují několik ovládacích prvků, není možné vybrat jeden z nich a smazat jej - komponenta je vybrána a odstraněna celá.

Vytvoření jednoduché součásti

Při psaní nové komponenty musíte mít jasno v tom, že komponenta je psána pro programátory, nikoli pro koncové uživatele. V tomto případě je žádoucí, aby se programátor neponořil do detailů implementace komponenty, ale jednoduše použil vlastnosti a události, které jsou jí vystaveny. Toho je dosaženo velmi důkladným testováním. Nový komponent musí být testován i v situacích, pro které není jednoznačně určen.

Položme si problém následovně. Musíte vytvořit tlačítko, které při stisknutí pípne, a implementovat jej jako komponentu, aby jej programátor mohl umístit na formulář a používat. Obecně platí, že při zvažování komponent budeme poměrně často používat nejjednodušší externí efekty: pípání, zobrazení zprávy atd. To znamená, že na místa, kde se používají vnější efekty, lze umístit jakýkoli poměrně složitý kód. Jen o něj momentálně nemáme zájem.

Vytvoření komponenty začíná výběrem položky nabídky Komponenta/Nové komponenty. Poté se okamžitě objeví dialogové okno Nová komponenta.

V tomto dialogu je potřeba definovat třídu předka, název nově vytvořené třídy, stránku na paletě, kam bude nová komponenta umístěna, název modulu obsahujícího implementaci nové komponenty a cestu k to. Pokud nová komponenta používá jiné moduly, jejichž cesta není popsána, musí být definovány v poli Search Path.

Takže prvním (a možná i hlavním) úkolem je výběr třídy předka. V rozevíracím seznamu jsou všechny komponenty dostupné v paletě nabízeny jako třída předka, včetně těch, které nejsou zahrnuty ve standardní distribuci Delphi. Jako třídu předka je nutné vybrat třídu, která je svými vlastnostmi co nejblíže vytvářené třídě. Pro náš úkol můžeme například vybrat TWinControl jako předka, ale v tomto případě budeme muset implementovat všechny vizuální efekty kliknutí na tlačítka atd. Proto jako předka zvolíme TButton.

Název nově vytvořené třídy musí odrážet obsah komponenty a v žádném případě se shodovat s názvem již registrované komponenty! Ve fázi vyplňování tohoto dialogu se jména nekontrolují na shodu - dobrodružství spojená s takovou chybou začnou později...

Při výběru stránky musíte vědět, že pokud zadáte název neexistující stránky, vytvoří se nová.

Nakonec, když klepnete na tlačítka Instalovat a OK, vytvoří se šablona pro implementaci nové součásti. Když však klepnete na tlačítko Instalovat, šablona se umístí na paletu komponent a po klepnutí na OK se jednoduše vytvoří. Doporučuje se použít tlačítko Instalovat. Poté, co je komponenta nainstalována, může být umístěna na formulář. Nyní budou všechny změny provedené v kódu implementace komponenty zkompilovány spolu s projektem a programátor okamžitě obdrží chybové zprávy. Pokud komponenta není nainstalována, pak je pro nalezení chyb nutné ji zkompilovat pomocí editoru balíčků (viz výše) kliknutím na tlačítko Kompilovat, což je méně pohodlné.

Po kliknutí na tlačítko Instalovat se tedy objeví další dialog, který vám umožní určit balíček, kam bude tato komponenta umístěna.

Tento dialog má dvě stránky, z nichž na první můžete vybrat jeden ze stávajících balíčků a na druhé vytvořit nový. Je velmi vhodné uvést krátký textový popis balíčku, který se zobrazí v dialogu vyvolaném příkazem Component/Install packages (viz výše). Po výběru balíčku a stisknutí tlačítka OK se vyvolá editor balíčků, kam se automaticky umístí nově vytvořený modul pro implementaci nové komponenty. Je užitečné jej nezavírat, ale přesunout do některého z rohů obrazovky, aby se dal aktivovat stisknutím tlačítka myši.

Současně se v editoru kódu vytvoří „prázdný prostor“ pro popis nové komponenty:

Unit ButtonBeep; rozhraní používá Windows, zprávy, SysUtils, třídy, grafiku, ovládací prvky, formuláře, dialogy, StdCtrls; typ TButtonBeep = class(TButton) private ( Soukromé deklarace ) chráněné ( Chráněné deklarace ) veřejné ( Veřejné deklarace ) publikované ( Publikované deklarace ) end; postup Registr; implementační postup Registr; begin RegisterComponents("Vzorky", ); konec; konec.

Samotná nová třída deklaruje čtyři sekce, jejichž význam je podrobně popsán v části „Viditelnost proměnných a metod“ předchozího článku této řady (ComputerPress č. 1 „2001). Kromě toho nová třída definuje Registrovat proceduru, kterou volá vývojové prostředí Delphi při instalaci tohoto modulu jako komponenty, obsahuje název stránky na paletě, kde je tato komponenta umístěna a v hranatých závorkách název třídy. metoda Register bere jako parametr pole typů tříd, protože v jednom modulu lze implementovat několik komponent. Proto jsou odděleny čárkou, například:

Registr procedur; begin RegisterComponents("Vzorky", ); konec;

Pokračujme v řešení úkolu - vytvoření tlačítka, které vydává pískání. Udělejme nejprve triviální věc (ale jak se později ukáže, nesprávně) – přiřaďte v konstruktoru tlačítka obsluhu události OnClick. K tomu v privátní sekci definujeme hlavičku nové metody BtClick(Sender:TObject) a implementujeme ji do implementační sekce:

Procedure TButtonBeep.BtClick(Sender:TObject); beginBeep; konec;

konstruktor Create(AOwner:TComponent); přepsat;

s povinnou nadřazenou směrnicí! Pojďme to implementovat v sekci implementace:

Konstruktor TButtonBeep.Create(AOwner:TComponent); begin zděděný Create(AOwner); OnClick:=BtClick; konec;

Poté komponentu zkompilujeme. Umístíme tlačítko na formulář ze stránky Ukázky a spustíme projekt k provedení. Můžete se ujistit, že tlačítko při stisknutí pípne!

Nyní se vraťme do vývojového prostředí a přiřaďme obslužnou rutinu události OnClick v inspektoru objektů. V obslužné rutině události zobrazíme text v názvu formuláře:

Procedure TForm1.ButtonBeep1Click(Sender:TObject); begin Caption:="Test"; konec;

Spusťte projekt a zkuste stisknout tlačítko. Název formuláře se změní, ale tlačítko přestane pípat! Chyba je v tom, že jsme se pokusili definovat dva handlery pro jednu událost tlačítka OnClick: jeden uvnitř komponenty BtClick a druhý přiřazený pomocí inspektoru objektů. Po vypracování konstruktoru TButtonBeep jsme měli odkaz na první handler BtClick. Poté se načtou prostředky a obslužné rutině události OnClick je přiřazena metoda ButtonBeep1Click. V tomto případě je nenávratně ztracena vazba na první handler – BtClick.

Proto byste při psaní nových komponent měli vždy zvážit změnu vlastností a obslužných rutin událostí pomocí Object Inspectoru. Pokud by se vlastnost (událost) neměla změnit, neměla by se zobrazovat v Inspektoru objektů. A pokud je již viditelná, měli byste ji skrýt (o tom si povíme později). Programátor má plné právo změnit jakékoli vlastnosti v inspektoru objektů, a pokud poté komponenta přestane fungovat, je na vině vývojář komponenty, ale v žádném případě programátor, který ji používá.

Jak můžeme tento problém správně vyřešit? Jedním ze způsobů, jak vytvořit komponenty, je přepsat existující metody. Při pohledu na soubor StdCtrls.pas, kde je implementován zdrojový kód pro komponentu TButton, si můžete všimnout, že obsahuje dynamickou metodu Click, kterou lze přepsat. Vracíme se proto opět ke zdrojovému kódu vytvořenému odborníkem na Delphi při vytváření komponenty (odstraníme konstruktor a metodu BtClick). Poté ve veřejné sekci definujeme hlavičku metody:

Postup Klikněte; přepsat;

a zde je implementace metody:

Postup TButtonBeep.Click; začít zděděný Click; pípnutí; konec;

Můžete si ověřit, že tlačítko při stisknutí píská. Navíc při přiřazení obsluhy události v inspektoru objektů se tato obsluha spustí a pípnutí nezmizí! Komponenta je implementována správně.

Pomocí tohoto příkladu je užitečné analyzovat možné chyby při psaní kódu:

  1. Zapomenutá direktiva přepsání při definování hlavičky metody Click. Tlačítko přestane pípat, proto není volána metoda Click.
  2. Zapomenuté volání metody předka (zděděné Click) při implementaci procedury Click. Tlačítko při stisknutí nadále pípá, ale kód v obslužné rutině události přiřazené v inspektoru objektů se neprovede. Proto metoda Click třídy TButton vyvolá událost OnClick.

Nyní změňme ikonu komponenty TButtonBeep na paletě. Ve výchozím nastavení se pro novou komponentu používá ikona předchůdce. Chcete-li to provést, zavolejte Editor obrázků pomocí příkazu Nástroje/Editor obrázků. V editoru zavolejte příkaz File/New/Component Resource File (*.dcr). Po příkazu Zdroj/Nový/Bitmapa se objeví dialogové okno s návrhem velikosti ikony 32x32. Tyto výchozí velikosti by měly být změněny na 24x24 – to je velikost, kterou musí mít ikony součástí! Po kliknutí na OK byste měli nakreslit obrázek pomocí standardních nástrojů podobných jako Editor barev. Pamatujte, že barva levého dolního pixelu je barva masky – tato barva bude „průhledná“.

Poté je třeba předefinovat název zdroje pomocí ikony, ve výchozím nastavení je jeho název Bitmap1. Nový název zdroje se musí shodovat s názvem třídy – v našem případě TButtonBeep.

Nyní je třeba uložit soubor ikony do stejného adresáře jako modul obsahující proceduru Register pro tuto komponentu a se stejným názvem jako název modulu. Pouze přípona souboru nebude *.pas, ale *.dcr. Soubor s ikonou komponenty je připraven. Pokud se však podíváme na paletu Components, uvidíme, že stará ikona je stále tam. Pokud restartujete Delphi nebo dokonce operační systém, stará ikona na paletě stále zůstane. Pro změnu ikony je nutné komponentu znovu zaregistrovat. K tomu potřebujete:

Tento příklad by měl být považován za testovací cvičení. Před napsáním nové komponenty musíte zjistit, zda podobné komponenty existují mezi volně distribuovanými komponentami. Existují téměř všechna tlačítka: průhledná, utíkající, kulatá, barevná atd. Přibližně stejná situace je i u ostatních komponent – ​​potomků stejné třídy. Nejčastěji tedy musíte implementovat komponenty skládající se z několika ovládacích prvků.

V tomto příkladu jsme tedy prozkoumali použití přepisování metod k vytvoření nových komponent.

Vytvoření komplexní komponenty

Řekněme, že potřebujete zadat seznam jmen zákazníků do aplikace. Ve stejné aplikaci budete také muset zadat seznam telefonních čísel. Zadání seznamu je poměrně běžná operace, takže byste měli zvážit jeho implementaci jako komponentu.

Pro vložení nového prvku do seznamu budete potřebovat editor - komponentu TEdit. Dále by měl mít uživatel možnost zobrazit seznam – bude potřeba komponenta TListBox. Kromě toho budete potřebovat příkazy pro zápis aktuální hodnoty z TEdit do seznamu, úpravu vybrané položky seznamu a její odstranění. Nejjednodušší způsob implementace těchto příkazů je pomocí tlačítek. Pro zjednodušení úlohy umístíme na formulář jedno tlačítko, po kliknutí přidáme do seznamu obsah komponenty TEdit.

Potřebujeme tedy vytvořit novou komponentu, která bude obsahovat TEdit, TListBox a TButton. Jako vždy jej začneme vytvářet příkazem Komponenta/Nová komponenta. Poté se objeví dialogové okno, ve kterém byste měli definovat třídu předka, název třídy a název modulu. S názvem třídy a názvem modulu nejsou žádné potíže, ale název třídy předka je nejasný. Máme tři ovládací prvky. Jejich společným předkem je TWinControl. Pokud si ji ale vybereme jako třídu předka, čeká nás velmi dlouhá a únavná implementace kódu TButton, TEdit a TListBox. V takových případech je nutné vybrat komponentu jako třídu předka, která může být „otcem“ ve vztahu k ostatním komponentám. Mezi standardní komponenty distribuované s Delphi jsou tři: TPanel, TGroupBox, TScrollBox. Vyberme panel jako třídu předka, ale ne samotnou komponentu TPanel, ale třídu TCustomPanel. Níže probereme výhody výběru TCustomPanel oproti TPanel.

Novou třídu pojmenujeme TListAdd a klikneme na tlačítko Instalovat. Po výběru balíčku se komponenta nainstaluje do palety, odkud ji lze umístit na formulář nově vytvořené aplikace. To je výhodné, protože při kompilaci projektu se zkompiluje i modul komponenty a pokud se vyskytnou chyby, kompilátor zobrazí zprávu.

Bylo by vhodné umístit naše ovládací prvky na nějaký formulář a pak z nich vytvořit komponentu. Ve standardním balíčku Delphi žádný takový expert neexistuje. Komponenty si tedy budete muset vytvořit sami a umístit je na panel. Je rozumné vytvořit ovládací prvky - TButton, TEdit a TListBox - v konstruktoru TCustomPanel, což samozřejmě vyžaduje jeho přepsání. Prozatím umístěme ovládací prvky do čtverce 100x100. Jejich souřadnice je také potřeba určit v konstruktoru. Je třeba si uvědomit, že po vypracování konstruktoru jakéhokoli ovládacího prvku ještě nemá rodiče, to znamená, že neví, ke kterému oknu má měřit souřadnice levého horního rohu vzhledem. Pokus o změnu souřadnic podřízeného okna, které nemá rodiče, okamžitě vyvolá výjimku. Prvním operátorem po zavolání konstruktoru ovládacího prvku tedy bude přiřazení rodiče, pro který vybereme TCustomPanel. Uděláme z něj také jejich vlastníka, v tomto případě nebude potřeba přepisovat destruktor.

V sekci použití tedy přidáme modul StdCtrls, kde jsou umístěny popisy tříd TEdit, TButton a TListBox a v sekci private definujeme tři proměnné:

Private FEdit:TEdit; FListBox:TListBox; FButton:TButton;

Ve veřejné části deklarujeme hlavičku konstruktoru s povinnou přepisovací direktivou:

Vytvořit konstruktor(AOwner:TComponent); přepsat;

Konstruktor implementujeme v sekci implementace:

Konstruktor TListAdd.Create(AOwner:TComponent); begin zděděný Create(AOwner); FButton:=TButton.Create(Self); FButton.Parent:=Self; FButton.Left:=5; FButton.Top:=5; FButton.Width:=40; FButton.Height:=25; FEdit:=TEdit.Create(Self); FEdit.Parent:=Self; FEdit.Left:=50; FEdit.Top:=5; FEdit.Width:=45; FEdit.Height:=25; FListBox:=TListBox.Create(Self); FListBox.Parent:=Self; FListBox.Left:=5; FListBox.Top:=35; FListBox.Width:=90; FListBox.Height:=60; konec;

Je třeba ještě jednou zdůraznit, že destruktor v tomto případě není třeba přepisovat: panel je vlastníkem všech ovládacích prvků a při zavolání jeho destruktoru se automaticky zavolají destruktory ovládacích prvků.

Po rekompilaci komponenty pomocí editoru balíčků jsou změny v komponentě viditelné již ve fázi vývoje.

Prvním nedostatkem, který vás upoutá, je neadekvátní chování ovládacích prvků při škálování komponenty. Při změně jeho rozměrů se rozměry a poloha prvků nemění. Součástku lze navíc udělat malou, takže se na ni nevejdou tři ovládací prvky. A konečně, při instalaci komponenty na formulář z palety komponent jednoduchým kliknutím myši také její rozměry zanechávají mnoho přání.

Nejprve opravme výchozí velikosti komponent, tedy ty, které se mu automaticky přiřadí po kliknutí na paletu komponent a následném kliknutí na formulář. Chcete-li to provést, stačí zadat nové rozměry panelu v konstruktoru:

Šířka:=100; Výška:=100;

Pak musíte zlepšit chování komponenty při škálování. Chcete-li to provést, musíte obdržet zprávu, že se rozměry změnily. Když se změní velikost ovládacího prvku, systém mu odešle zprávu WM_SIZE. Tato zpráva musí být zachycena. Za tímto účelem v soukromé části popíšeme hlavičku zachycovače zpráv:

Procedure WMSize(var Zpráva:Tmessage); zpráva WM_SIZE;

a v sekci implementace implementujeme jeho handler:

Procedure TListAdd.WMSize(var Zpráva:TMessage); začít zděděno; pokud Šířka<100 then Width:=100; if Height<100 then Height:=100; FEdit.Width:=Width-55; FListBox.Width:=Width-10; FListBox.Height:=Height-40; end;

První příkaz je volání výchozí obslužné rutiny WM_SIZE (zděděno). Po jejím vyvolání budou vlastnosti Width a Height obsahovat novou šířku a výšku panelu. Poté se určí minimální rozměry součásti, v tomto případě 100x100. Pokud je horizontální nebo vertikální velikost menší než minimální, pak je přiřazena minimální hodnota. Ovládací prvky jsou pak zmenšeny tak, aby vyplnily celý panel s určitým odsazením. Kompilací komponenty pomocí editoru balíčků si již ve fázi vývoje můžete všimnout správného chování ovládacích prvků na panelu při škálování a také toho, že velikost komponenty nemůže být menší než 100x100.

Nyní bude užitečné spustit celý projekt, zkusit zadat data do jednořádkového textového editoru a kliknout na tlačítko. V tomto případě se do seznamu nic nepřidává. A není divu, nikde v naší komponentě není specifikováno, co se má při stisku tlačítka udělat. Aby se obsluha události spojila s kliknutím na tlačítko, můžete postupovat jako při psaní komponenty TbuttonBeep, tedy definovat novou třídu - potomka TButton a přepsat metodu Click. Definování nové třídy však vyžaduje systémové prostředky (virtuálních metod je více). Pokud komponentu označíme ve formuláři a podíváme se na inspektor objektů, zjistíme, že komponenta TlistAdd zpřístupňuje málo vlastností a žádné události, včetně žádných obslužných rutin pro tlačítko OnClick. V tomto případě tedy platí to, co jsme v minulé kapitole odmítli jako nesprávnou metodu, předefinování handleru tlačítka OnClick, protože programátor nemůže v inspektoru objektů přiřadit nový handler. Takže v soukromé části popisujeme hlavičku nové metody:

Procedure BtClick(Sender:TObject);

V implementaci konstruktoru TListAdd přiřadíme tento handler k obsluze události FButton.OnClick:

FButton.OnClick:=BtClick;

Nakonec implementujme metodu BtClick:

Procedure TListAdd.BtClick(Sender:TObject); begin if length(FEdit.Text)>0 then begin FListBox.Items.Add(FEdit.Text); FEdit.Text:=""; FEdit.SetFocus; konec; konec;

Nejprve zkontrolujeme, zda je jednořádkový editor prázdný: do seznamu nebudeme přidávat prázdné řádky. Poté přeneseme obsah editoru do seznamu (FListBox.Items.Add(FEdit.Text);) a připravíme editor na zadání další hodnoty – konkrétně jej vyčistíme od textu (který již byl do seznamu přenesen ) a přeneste na něj vstupní fokus. Nyní, po zkompilování a spuštění aplikace, se můžete ujistit, že funguje správně – po stisku tlačítka se obsah editoru přenese do seznamu.

Přidání vlastností a metod

Pokud umístíte komponentu TPanel vedle komponenty TListAdd a porovnáte, co je zobrazeno v inspektoru objektů, všimnete si, že pro panel je vystaveno poměrně velké množství vlastností a událostí, zatímco pro TListAdd je vystaveno pouze několik vlastností. Mezitím je třída TCustomPanel předkem obou komponent. Abychom pochopili důvod, otevřeme modul ExtCtrls.pas a podíváme se na rozdíl mezi třídami TCustomPanel a TPanel. Lze poznamenat, že všechny metody a proměnné, které zajišťují funkčnost panelu, jsou definovány na úrovni třídy TCustomPanel. Definuje také vlastnosti, které se pak zobrazí v inspektoru objektů pro TPanel, pouze tyto vlastnosti jsou definovány v sekci Chráněné. Implementace třídy TPanel je extrémně jednoduchá: TCustomPanel je definován jako předek a vlastnosti této třídy jsou deklarovány, ale v publikované sekci. Je jasné, co je třeba udělat ve třídě TListAdd, aby se vlastnosti a metody třídy TcustomPanel objevily v inspektoru objektů, konkrétně deklarovat vlastnosti. V publikované sekci třídy TListAdd píšeme:

Property Align; vlastnost OnMouseDown;

Při deklaraci vlastnosti nemusíte specifikovat její typ nebo referenční proměnné nebo metody pro čtení nebo zápis vlastnosti. Po zkompilování komponenty pomocí editoru balíčků v inspektoru objektů můžete pozorovat vzhled vlastnosti Align a události OnMouseDown. Pro potomky tříd TCustom... tak má programátor možnost vybrat si, které vlastnosti a události se mají v inspektoru objektů zobrazovat a které ne. Z tohoto důvodu se doporučuje používat třídy TCustom... jako předchůdce pro vytváření komponent.

Nyní se podíváme na to, jak můžete zavést novou vlastnost (to, co jsme provedli výše, je opětovné deklarování stávajících vlastností). Text na tlačítku lze použít jako vhodnou vlastnost k zobrazení v inspektoru objektů: nechte programátora pomocí komponenty TListAdd změnit text v době návrhu. Pokus o zavedení nové vlastnosti (říkejme jí BtCaption) pomocí deklarace:

Vlastnost BtCaption:string čtení FButton.Caption zápis FButton.Caption;

způsobí chybu při pokusu o kompilaci komponenty. Proto definujeme záhlaví dvou metod v soukromé sekci:

Funkce GetBtCaption:string; procedure SetBtCaption(const Value:string);

V publikované sekci deklarujeme vlastnost BtCaption:

Vlastnost BtCaption:string čtení GetBtCaption zápis SetBtCaption;

Nakonec implementujeme dvě deklarované metody v sekci implementace:

Funkce TListAdd.GetBtCaption:string; begin Vysledek:=FButton.Caption; konec; procedure TListAdd.SetBtCaption(const Value:string); begin FButton.Caption:=Hodnota; konec;

Po zkompilování komponenty pomocí editoru balíčků se v Inspektoru objektů objeví nová vlastnost. Změna hodnoty této nemovitosti se projevuje přímo ve fázi vývoje.

Nyní definujeme novou událost. V tomto případě by bylo rozumné vytvořit událost, která umožní programátorovi používajícímu tuto komponentu analyzovat text před přidáním obsahu editoru do seznamu a povolit nebo zakázat přidávání textu do seznamu. Tato metoda tedy musí obsahovat jako parametr aktuální hodnotu textu v editoru a záviset na booleovské proměnné, které může programátor přiřadit hodnotu True nebo False. Kromě toho musí každá obsluha události v komponentě záviset na parametru Sender, ve kterém komponenta, která jej volá, předává odkaz na sebe. To je nutné, protože ve vývojovém prostředí Delphi může být stejná obsluha události volána z několika různých komponent a programátor musí být schopen analyzovat, která komponenta byla volána handler. Takže za typem slova v sekci rozhraní, před definováním TListAdd, definujeme nový typ metody:

Napište TFilterEvent=procedure(Sender:TObject; const EditText:string; var CanAdd:boolean) objektu;

FOnFilter:TFilterEvent;

A v publikované sekci definujeme vlastnost tohoto typu:

Vlastnost OnFilter:TFilterEvent čtení FOnFilter zápis FOnFilter;

Při definování nové vlastnosti odkazujeme na proměnnou FOnFilter, nikoli na metody – ty zde nejsou vyžadovány. Pokud nyní kompilujete komponentu pomocí editoru balíčků, můžete vidět událost OnFilter, která se objeví v Object Inspector. Pokud mu však přiřadíme handler a spustíme projekt k provedení, nemusí být zavolán. Je to proto, že jsme to nikde v naší komponentě nenazvali. Dobrým místem pro volání události OnFilter je obslužná rutina události OnClick pro FButton, která je již implementována. Proto změníme implementační kód dříve definované metody BtClick:

Procedure TListAdd.BtClick(Sender:TObject); var CanAdd:boolean; begin if length(FEdit.Text)>0 then begin CanAdd:=True; if Assigned(FOnFilter) then FOnFilter(Self,FEdit.Text,CanAdd); if CanAdd then begin FListBox.Items.Add(FEdit.Text); FEdit.Text:=""; FEdit.SetFocus; konec jinak pípnutí; konec; konec;

Ve výše uvedeném fragmentu kódu je tedy definována booleovská proměnná CanAdd. Při psaní kódu si uvědomte, že programátor nemusí vytvořit obslužnou rutinu události OnFilter. Proto nastavíme výchozí hodnotu proměnné CanAdd na True - přidejte všechny řádky do seznamu. Dále byste před voláním FonFilter měli zkontrolovat, zda programátor vytvořil obslužnou rutinu události. Toho je dosaženo voláním metody Assigned, která vrací booleovskou hodnotu. U ukazatele je volání metody Assigned ekvivalentní kontrole P<>nula. U objektové metody nemůžeme použít kontrolu FOnFilter<>nil, protože objektová metoda je charakterizována dvěma adresami a taková kontrola nebude kompilátorem povolena. Ale volání metody Assigned dokonale zkontroluje, zda byla vytvořena obsluha události. Výše uvedený kód je absolutně standardním způsobem volání obsluhy události z komponenty.

Zbývá jen otestovat obsluhu události. Umístíme na formulář dvě komponenty TListAdd, pro jednu umožníme přidávat pouze celá čísla a pro druhou pouze slova začínající velkými anglickými písmeny. Podle toho bude kód pro obsluhu událostí OnFilter vypadat takto:

Procedure TForm1.ListAdd1Filter(Sender: TObject; const EditText: String; var CanAdd: Boolean); var I,N:integer; begin Val(EditText,N,I); CanAdd:=I=0; konec; procedure TForm1.ListAdd2Filter(Sender: TObject; const EditText: String; var CanAdd: Boolean); begin CanAdd:=False; if length(EditText)>0 then CanAdd:=(EditText>="A") a (EditText<="Z"); end;

Kód je snadno srozumitelný, jedinou výhradou je, že před kontrolou prvního písmene textu v obsluze události ListAdd2Filter kontroluje, zda text není prázdný řetězec. Provedení takové kontroly je povinné: řetězce v Object Pascalu jsou objekty a prázdný řetězec odpovídá nulovému ukazateli. Pokud se pokusíte zkontrolovat první písmeno prázdného řetězce, aplikace se pokusí dereferencovat nulu, což vyvolá výjimku. V tomto případě to není problém: před voláním obslužné rutiny události FOnFilter z komponenty TListAdd je řetězec zkontrolován na nenulovou délku. U komponent, jejichž zdrojový kód nemáte k dispozici, je však takové ověření povinné!

Skrytí vlastností v Inspektoru objektů

Předpokládejme, že vytváříte komponentu pro přístup k datům, například potomka třídy TTable. Řekněme, že tato komponenta analyzuje seznam tabulek dostupných v databázi a na základě určitých kritérií (například přítomnost pole určitého typu a s určitým názvem) je vybrána pro práci. Pro normální provoz komponenty musí být název této tabulky zadán ve vlastnosti TableName. Ale tato vlastnost je viditelná v inspektoru objektů! Programátor používající tuto komponentu by mohl během vývoje změnit její hodnotu, což by pravděpodobně způsobilo nefunkčnost komponenty. A bude mít pravdu! Pokud některou z vlastností nebo událostí nelze změnit, měly by být skryty.

Budeme pokračovat v práci na komponentě TListAdd a odstraníme vlastnost Cursor z inspektoru objektů jako modelovou úlohu. Tato vlastnost je definována v publikované sekci třídy TControl a zobrazuje se v inspektoru objektů pro TListAdd od samého počátku vývoje komponenty. Na základě toho se můžete pokusit přepsat tuto vlastnost v chráněné sekci. Kompilátor takové přepsání umožní, ale nepovede k požadovanému výsledku: vlastnost Cursor zůstane v inspektoru objektů tak, jak byla... Jakákoli vlastnost, jakmile je definována v publikované sekci, bude vždy zobrazena v objektu inspektor pro všechny potomky této třídy.

Ke skrytí vlastnosti před objektovým inspektorem používáme dvě funkce kompilátoru Delphi, a to:

  1. Při deklaraci nové vlastnosti se stejným názvem jako existující vlastnost je dříve definovaná vlastnost „zastíněná“.
  2. Vlastnosti, které mají přístup pouze pro čtení nebo pouze pro zápis, se v inspektoru objektů nezobrazí, i když jsou deklarovány v publikované sekci.

Než začnete pracovat na skrytí vlastnosti Cursor, je dobré z formuláře odstranit komponenty TListAdd, jinak může při čtení zdroje formuláře dojít k výjimce. V soukromé sekci tedy deklarujeme proměnnou FDummy:integer (název a typ proměnné může být jakýkoli) a v publikované sekci definujeme novou vlastnost:

Property Cursor:integer read FDummy;

Nová vlastnost se musí jmenovat Cursor, její typ musí odpovídat typu proměnné definované výše, vlastnost musí být jen pro čtení nebo jen pro zápis. Po zkompilování komponenty pomocí editoru balíčků byste měli komponentu TListAdd znovu umístit do formuláře. Možná zjistíte, že vlastnost Cursor již není v Inspektoru objektů viditelná.

Nyní si úkol trochu zkomplikujeme. Předpokládejme, že chcete, aby se kurzor nezobrazoval jako šipka, ale jako přesýpací hodiny (crHourGlass). Chcete-li změnit výchozí hodnotu vlastností, musí být nová hodnota přiřazena proměnné v konstruktoru. Při pokusu o přiřazení nové hodnoty kurzoru v konstruktoru

Kurzor:=crHourGlass;

Kompilátor Delphi vydá diagnostickou zprávu o tom, že proměnné pouze pro čtení nelze přiřadit novou hodnotu. Pokud vytvoříte novou vlastnost „pouze pro zápis“, kompilátor vydá jinou diagnostickou zprávu – o nekompatibilních typech dat. Pokud deklarujete proměnnou FDummy:TCursor a nastavíte ji pouze na zápis, kompilátor toto přiřazení povolí, ale vzhled kurzoru se nezmění: bude to stále šipka.

Triviálním řešením tohoto problému je deklarovat potomskou třídu TCustomPanel, v jejímž konstruktoru je potřeba přiřadit novou hodnotu proměnné Cursor az ní vyrobit naši komponentu TListAdd. Toto řešení má dvě nevýhody:

  1. Je to náročné na zdroje – virtuální metody se množí.
  2. Vlastnost v inspektoru objektů jsme skryli před programátorem, který bude tuto komponentu používat. S touto nemovitostí chceme pracovat.

Řešení tohoto problému tedy vypadá takto: v konstruktoru TListAdd deklarujeme operátor:

Zděděný kurzor:=crHourGlass;

a to je vše! To stačí ke změně kurzoru.

Dříve jsme zděděné funkční slovo používali pouze k volání metody předka. Tato konstrukce vám umožní lépe porozumět významu zděděno jako odkazu na třídu předka. Můžete přistupovat k vlastnostem i metodám. Při přístupu k vlastnosti ji můžete buď přečíst, nebo jí přiřadit novou hodnotu; v tomto případě se pomocné slovo zděděné objeví vlevo od přiřazovacího znaku. Podobně můžete volat metody skrytého předka. Volání hierarchie vyšší než třída předka jsou zakázány – konstrukce

Zděděný zděděný kurzor:=crHourGlass;

nebude kompilovat.

V tomto okamžiku budeme tento projekt považovat za dokončený. V nové komponentě jsme zachytili zprávu, deklarovali vlastnosti, přidali nové vlastnosti a události a skryli dříve deklarovanou vlastnost. Všechny tyto metody se používají k vytváření komponent. Níže se podíváme na další zajímavou metodu.

Použití hákových procedur k vytváření komponent

Již dříve bylo zmíněno, že každé dítě TWinControl má proceduru, která přijímá a zpracovává zprávy. Pokud je tam odkaz na handle okna (HWND), pak můžete určit adresu tohoto postupu a hlavně tuto adresu přepsat a zpracovat tak přijaté zprávy po svém. Zpravidla nikdo nepíše kompletní handlery pro všechny zprávy; stará výchozí metoda se volá častěji. V tomto případě je nový postup použit jako filtr: když přijde událost, kód se spustí. Ve skutečnosti je to „špion“ v TwinControl: jsme upozorněni, když přijde zpráva a může být spuštěn nějaký kód. Pokud je procedura Hook implementována správně, TWinControl pokračuje v práci jako obvykle, aniž by si byl vědom, že sdílí své zprávy s někým jiným.

Postup háku je definován takto:

Procedure(var Zpráva:TMessage) objektu;

Závisí na proměnné typu TMessage, která obsahuje všechny informace o zprávě. Definování tohoto postupu však nestačí. Musí být zkopírován pro každý TWinControl, ke kterému bude připojen. Toho je dosaženo voláním metody WinAPI MakeObjectInstance. Tato metoda vezme jako parametr metodu objektu, vytvoří její kopii v paměti a vrátí adresu nové metody. Je jasné, že se tím rezervují systémové prostředky, které je třeba do systému vrátit. Toho je dosaženo voláním metody FreeObjectInstance.

Další důležitá podmínka: před zničením TWinControl musí být obnovena komunikace se starou procedurou zpracování zpráv, jinak se zdroje nevrátí do systému. To znamená, že si budete muset pamatovat ukazatel na starou proceduru, kterou najdete voláním metody Win API GetWindowLong s parametrem GWL_WNDPROC. Tento ukazatel bude také použit k volání výchozích obslužných rutin událostí TWinControl. Opačná metoda, SetWindowLong, se používá k nastavení procedury Hook.

Pojďme tedy formulovat problém pro další cvičení. Řekněme, že chceme vytvořit komponentu, která bude při stisku tlačítka myši pípat ostatní komponenty – potomci TWinControl. Je jasné, že tato komponenta by se neměla zobrazovat během spouštění aplikace, proto vybereme TComponent jako její předchůdce. Definujme název třídy jako TBeepWnd. V soukromé části definujeme tři proměnné:

FOldProc,FNewProc:ukazatel; FControl:TWinControl;

Z názvů je zřejmé, že si budeme pamatovat odkaz na starou proceduru v proměnné FOldProc, odkaz na novou proceduru (po provedení metody MakeObjectInstance) bude uložen v proměnné FNewProc. A do proměnné FControl uložíme odkaz na ovládací prvek, na kterém je právě „zavěšená procedura Hook“. Pojďme definovat tři metody ve stejné části:

Procedure HookProc(var Zpráva:TMessage); procedure HookWindow(W:TWinControl); postup UnhookWindow;

a v sekci implementace je implementujeme:

Procedure TBeepWnd.HookProc(var Zpráva:TMessage); begin case Message.Msg of WM_LBUTTONDOWN:begin (Náš úkol) Beep; Message.Result:=CallWindowProc(FOldProc, FControl.Handle, Message.Msg, Message.WParam, Message.lParam); konec; WM_DESTROY:begin (Když je okno o ničení, odstraňte háček) Message.Result:=CallWindowProc(FOldProc, FControl.Handle, Message.Msg, Message.WParam, Message.lParam); UnhookWindow; konec; (Volání výchozí obslužné rutiny) else Message.Result:=CallWindowProc(FOldProc, FControl.Handle, Message.Msg, Message.WParam, Message.lParam); konec; konec;

V samotné proceduře Hook je zachycena zpráva, na kterou dojde k reakci - WM_LBUTTONDOWN. Každá procedura Hook navíc musí zpracovat zprávu WM_DESTROY. Toto je poslední zpráva, která je odeslána do okna před jeho zničením. Naší odpovědí je obnovit předchozí metodu voláním metody UnhookWindow popsané níže. Nakonec se pomocí metody CallWindowProc volají výchozí obslužné rutiny zpráv. Zapomenutí výchozí obslužné rutiny události je stejné jako zapomenutí zděděné v obslužné rutině události; v 80 % případů to povede k nesprávnému chování aplikace. V žádném případě nezapomínejte přiřadit výsledek volání metody CallWindowProc do pole Result proměnné Message! Kód v tomto případě nebude fungovat!

Procedure TBeepWnd.HookWindow(W:TWinControl); begin if csDesigning v ComponentState then begin (Kontrola, zda komponenta při návrhu nebo běhu) FControl:=W; Výstup; konec; pokud FControl<>nil pak UnhookWindow; (Odstraňte háček, pokud byl dříve nainstalován), pokud W<>nil then begin FOldProc:=ukazatel(GetWindowLong(W.Handle,GWL_WNDPROC)); (Určuje adresu staré procedury) FNewProc:=MakeObjectInstance(HookProc); (Vytvořit kopii v paměti) SetWindowLong(W.Handle,GWL_WNDPROC,integer(FNewProc)); (Nastavit nový postup) end; FControl:=W; (Uložit referenci při kontrole) konec;

Tato metoda se používá k nastavení nové rutiny zpracování zpráv. Nejprve zkontroluje, ve které fázi se komponenta nachází: ve fázi vývoje nebo ve fázi provádění. Pokud je komponenta ve fázi vývoje, to znamená, že příznak csDesigning je nastaven ve vlastnosti ComponentState, pak se jednoduše uloží odkaz na komponentu bez instalace procedury Hook. To se provádí proto, aby se zabránilo instalaci procedury Hook do vývojového prostředí Delphi. Pokud byl tento postup dříve nastaven na jiném ovládacím prvku, je odebrán voláním metody UnhookWindow. Poté se zapamatuje adresa staré procedury (GetWindowLong), vytvoří se kopie v paměti nové procedury (MakeObjectInstance) a nastaví se adresa nové procedury (SetWindowLong). Používá se přetypování z celého čísla na ukazatel a naopak - volané metody vyžadují (nebo vracejí) proměnné ne zcela vhodných typů. Nakonec je odkaz na ovládací prvek uložen v proměnné FControl, kterou jsme definovali v soukromé sekci.

Postup TBeepWnd.UnhookWindow; begin if (FControl=nula) nebo (FOldProc=nula) nebo (FNewProc=nula) then Exit; (Nebyl nainstalován žádný háček) SetWindowLong(FControl.Handle,GWL_WNDPROC,integer(FOldProc)); (Nastavit starou proceduru okna) FreeObjectInstance(FNewProc); (volné zdroje) FControl:=nil; (Iniciovat proměnné) FOldProc:=nula; FNewProc:=nula; konec;

Tato metoda obnoví starou obslužnou rutinu události. Je volána z metody HookProc a musí být volána také z destruktoru komponenty - Hook musí být odstraněn jak při zničení okna, tak při zničení této komponenty. Metoda SetWindowLong s adresou staré metody obnoví starou obslužnou rutinu zprávy. Poté byste měli vrátit prostředky do systému voláním metody FreeObjectInstance.

Takže byly definovány základní metody pro práci s Hook procedurou. Nyní musíte přepsat destruktor tak, aby byla při zničení této komponenty odstraněna procedura Hook:

Destruktor TBeepWnd.Destroy; začít UnhookWindow; zděděný Destroy; konec;

A nakonec v publikované sekci definujeme vlastnost, která se zobrazí v inspektoru objektů:

vlastnost Control:TWinControl čtení FControl zápis HookWindow;

Pro instalaci nové komponenty odkazujeme na dříve definovanou metodu, která za běhu aplikace okamžitě „zavěsí“ na komponentu proceduru Hook, která po stisknutí tlačítka zapípá. Připomeňme, že místo operátoru Beep můžete napsat libovolný spustitelný kód.

Komponenta se testuje zcela jednoduše: umístí se na formulář, na kterém je umístěno několik potomků TWinControl. Po výběru komponenty TBeepWnd na pozadí se kliknutím myši do pole Control v inspektoru objektů rozbalí seznam obsahující všechny TWinControl definované ve formuláři. Měli byste vybrat jednu z nich a spustit aplikaci. Když kliknete levým tlačítkem myši na vybranou součást, ozve se pískání.

Editory vlastností a editory komponent

Vše popsané v předchozích částech se týká vytvoření kódu aplikace, který bude distribuován uživatelům. Vývojové prostředí Delphi vám však umožňuje upravit samo sebe. To nevyžaduje znalost speciálního jazyka, protože všechny metody pro změnu vývojového prostředí jsou napsány v Delphi. Zde jsou tyto metody, jmenovitě editory vlastností a editory komponent, uvažovány částečně - z hlediska vytváření nástrojů pro práci s komponentami. Při čtení materiálů v této části byste měli jasně pochopit, že koncový uživatel pracující s vaší aplikací nikdy neuvidí ani editor vlastností, ani editor komponent – ​​jsou vytvořeny pro programátory a fungují pouze ve vývojovém prostředí Delphi.

Redaktoři nemovitostí

Během vývoje aplikace se vlastnosti zobrazují v Inspektoru objektů. Pamatujte, že vlastnosti se v Inspektoru objektů upravují odlišně. Některým vlastnostem (Width, Caption) lze přiřadit pouze novou textovou hodnotu. Vlastnost typu Kurzor poskytuje rozevírací seznam, na který můžete kliknout a vybrat hodnotu. Vlastnost typu TFont má vlevo znaménko "+"; Když na něj kliknete, rozbalí se a umožní vám upravovat jednotlivá pole. Vpravo je navíc tlačítko se třemi tečkami (eliptické tlačítko), po kliknutí se zobrazí dialog editoru vlastností.

Každá z výše uvedených vlastností má svůj vlastní editor a velkou výhodou vývojového prostředí Delphi je možnost vytvářet si vlastní editory vlastností. Mezi distribuovanými komponentami jsou zcela běžné nové editory vlastností. Ale je třeba s nimi zacházet opatrně: nejprve spusťte testy na počítači, kde můžete v případě potřeby znovu nainstalovat Delphi. Zpravidla je vytvářejí kvalifikovaní programátoři a ke kódu nejsou žádné stížnosti, ale často zapomínají zahrnout jakoukoli DLL do distribuovaného editoru vlastností. Po instalaci takového editoru získáme řadu vlastností, které nelze upravovat - starý editor je zablokován a nový nefunguje...

Před vytvořením nového editoru vlastností má smysl se zamyslet nad tím, zda se to vyplatí dělat – mezi standardními editory pravděpodobně nějaký vhodný najdete. Pokud musíte vytvořit editor vlastností, musíte se řídit pravidlem: neměli byste se vytvářet editory pro standardní datové typy (celé číslo, řetězec atd.). Ostatní programátoři jsou zvyklí na standardní editory a ten váš se jim nemusí líbit. Proto se budete muset uskromnit a zaregistrovat si editor pro svou třídu, a ne pro třídu TComponent. Pokud se programátorům líbí váš editor vlastností, většina z nich bude moci registraci změnit sama tak, aby editor fungoval pro všechny komponenty. Otázku registrace editora probereme níže.

Položme si tedy modelový problém, pro jehož implementaci bude nutné implementovat editor vlastností. Předpokládejme, že některá komponenta má vlastnost - den v týdnu. V zásadě lze pro zadání dne v týdnu použít standardní editor s rozevíracím seznamem. Chceme však, aby programátor ve fázi vývoje mohl zadat den v týdnu, a to buď jeho pořadovým číslem (1 – pondělí, 2 – úterý atd.), nebo textem v národním nebo anglickém jazyce. Při zadávání textu je povoleno míchání velkých a malých písmen.

Nejprve je třeba vytvořit komponentu, která bude ukládat den v týdnu. Vytvořme novou komponentu voláním příkazu Komponenta/Nová komponenta. Vyberme TComponent jako třídu předka a dáme nové třídě název TDayStore. Poté nainstalujte komponentu do palety. Nyní se musíme rozhodnout, v jaké formě uložit den v týdnu. Je jasné, že pro jednoznačnou identifikaci a úsporu zdrojů by měl být uložen jako celé číslo s platnými rozsahy 1-7. Pokud však budeme vytvářet editor vlastností, měli bychom pamatovat na pravidlo nevytvářet nové editory pro stávající typy. Definujeme tedy nový typ - TDayWeek a všechny operace s ním budou prováděny jako s celými čísly. Pojďme definovat proměnnou FDay v soukromé části komponenty. Protože tato proměnná bude při spuštění výchozího konstruktoru inicializována na 0 a toto číslo je mimo povolené hodnoty, je nutné konstruktor přepsat. Nakonec definujme vlastnost DayWeek v publikované sekci, abychom ji zobrazili v inspektoru objektů. Finální komponenta vypadá takto:

Type TDayWeek=type integer; TDayStore = class(TComponent) private (Soukromé deklarace) FDay:TDayWeek; chráněné ( Chráněné deklarace ) veřejné ( Veřejné deklarace ) konstruktor Create(AOwner:TComponent); přepsat; publikováno ( Publikovaná prohlášení ) vlastnost DayWeek:TDayWeek čtení FDay zápis FDay; konec; ... implementační konstruktor TDayStore.Create(AOwner:TComponent); begin zděděný Create(Aowner); FDay:=1; konec;

Za pozornost stojí vzácná konstrukce definice nového typu

TDayWeek=typ celé číslo;

Zavádí se tak nový datový typ, který má stejnou velikost jako typ integer, všechny operace s tímto datovým typem se provádějí jako s celými čísly. Smyslem této operace je deklarovat nový datový typ, aby na něj bylo možné konkrétně použít náš editor vlastností a neovlivnil ostatní datové typy.

Nyní vytvoříme editor pro vlastnost TDayWeek. Chcete-li to provést, přidejte do stávajícího projektu nový formulář, zapamatujte si ho pod nějakým vhodným názvem (DayPropE.pas) a vyřaďte jej z projektu. Poté formulář otevřeme jako samostatný soubor a implementujeme do něj editor vlastností. V první fázi nebudeme formulář potřebovat, ale později na něm zavedeme dialog.

Modul pro tvorbu editorů vlastností se nazývá DsgnIntf.pas (Design Interface), definuje základní třídu TPropertyEditor a podřízené třídy určené pro úpravu standardních vlastností - TIntegerProperty, TFloatProperty, TStringProperty atd. Mechanismus fungování editorů vlastností je následující:

  1. Registruje se ve vývojovém prostředí Delphi voláním metody RegisterPropertyEditor. Tato metoda bere jako parametry následující hodnoty:

    a) informace o typu vlastností pro editaci, kterým je tento editor určen. Kvůli těmto informacím jsme museli definovat nový typ TDayWeek;

    b) informace o komponentě, ve které je tento editor použitelný. Editor bude volán nejen pro zadanou komponentu, ale také pro všechny její potomky. Pokud toto nastavíte na TComponent, editor bude volán pro jakoukoli komponentu;

    c) název vlastnosti, pro kterou se tento editor používá. Pokud je název prázdný řetězec, použijí se dva výše uvedené filtry;

  2. Metoda GetValue se volá, když je třeba z komponenty přečíst aktuální hodnotu vlastnosti. Pro jakoukoli vlastnost tato metoda vrací řetězec, který je umístěn v inspektoru objektů.
  3. Metoda SetValue je volána, když programátor zadá novou hodnotu vlastnosti do Object Inspector. Jako parametr je předán nový řetězec. V metodě musí být analyzován a převeden na typ upravované vlastnosti.

Metody GetValue a SetValue jsou virtuální, při jejich přepsání se vytvoří nové editory vlastností. Nyní tedy můžeme začít vytvářet nový editor vlastností.

Podívejme se na modul DsgnIntf ​​​​v sekci použití modulu DayPropE.pas a definujte novou třídu v sekci Rozhraní:

Zadejte TDWPropED=class(TPropertyEditor) veřejná funkce GetValue:string; přepsat; procedura SetValue(const Value:string); přepsat; konec;

Implementační sekce by měla implementovat obě tyto metody. V tomto případě navíc potřebujeme seznam názvů dnů v týdnu - v počáteční formulaci problému je vyžadováno, aby programátor mohl zadat den v týdnu:

Const DayWeek:array of string = ("pondělí", "úterý", "středa", "čtvrtek", "pátek", "sobota", "neděle"); DayWeekEn:array of string = ("pondělí", "úterý", "středa", "čtvrtek", "pátek", "sobota", "neděle");

Publikace na dané téma