Създаване на компоненти в DELPHI. Въведение в създаването на Delphi компоненти

Преди да създадете своя компонент, трябва да изберете предшественик за него. Кой може да бъде предшественикът на вашия компонент?

Обикновено се използва като предци на TComponent, TControl, TWinControl, TGraphicControl, TCustomXXXXXX, както и всички компоненти на палитрата на компонентите.
Да вземем за пример компонента TOpenDialog, който се намира на страницата Dialogs на палитрата на компонентите. Върши добре работата си, но има едно малко неудобство. Всеки път, когато го използвате, трябва да променяте стойността на свойството Options всеки път. И като правило това са едни и същи действия.
OpenDialog1.Options:= OpenDialog1.Options + ;

така че файлът, който се опитваме да отворим с този диалог, действително съществува на диска.
Вече сме избрали задача за себе си, остава само да създадем компонент. Създаваме заготовка за компонента, като избираме командата Component/New Component... от менюто и избираме в диалоговия прозорец
Тип предшественик: TOpenDialog
Име на класа: TOurOpenDialog
Страница Palette: Нашият тест
Щракнахме Ok и вече имаме шаблон за нашия бъдещ компонент.

Ние отменяме конструктора за този компонент, т.е. в публичната секция вмъкнете реда:

конструктор Create(AOwner: TComponent); отмяна;

Щракването върху този ред Ctrl + Shift + C създава шаблон за този метод, вътре в който вмъкваме следните редове:

наследено Създаване (AOwner); (Извикване на наследения конструктор)
Опции:= Опции + ; (Извършваме необходимите действия)

Моля, обърнете внимание: Клавишните комбинации Ctrl + Shift + стрелки нагоре/надолу ви позволяват да навигирате между декларация на метод и неговата реализация.

Инсталиране на създадения компонент Component/Install Component...
Инсталиране в нов пакет
Име на файла на пакета: C:Program FilesBorlandDelphi4LibOurTest.dpk
Описание на пакета: Нашият тестван пакет

Не ви ли харесва, че нашият компонент има същата икона като стандартния? Тогава нека създадем наши собствени за него.
За да направим това, трябва да извикаме Инструменти/Редактор на изображения. Създайте нов *.dcr файл.
Вмъкнете изображението Resource/New/Bitmap в него. Задайте размера на изображението на 24x24 пиксела. И тогава - вашето творчество...
Моля, обърнете внимание: цветът на точките, който съвпада с цвета на точката в долния ляв ъгъл на снимката, ще се счита за ПРОЗРАЧЕН!
След като създадете своя чертеж, преименувайте го от Bitmap1 на TOurOpenDialog и запазете файла като OurOpenDialog.dcr.
Премахнете компонента от пакета и го инсталирайте отново (само в този случай ще бъде добавена връзка към файла *.dcr).
Компилирайте, инсталирайте и успех!

мерна единица OurOpenDialog; интерфейс използва Windows, Съобщения, SysUtils, Класове, Графики, Контроли, Формуляри, Диалогови прозорци; Тип TOurOpenDialog = клас(TOpenDialog) частен(Лични декларации) защитени публичен(Публични декларации) конструкторСъздаване (AOwner: TComponent); отмени; публикувани край; процедура регистрирам; изпълнение процедура регистрирам; започвам RegisterComponents("Образци", ); край; (TOurOpenDialog) конструктор TOurOpenDialog.Create(AOwner: TComponent); започвам наследениСъздаване (AOwner); (Извикване на наследения конструктор) Опции:= Опции + ; (Извършваме необходимите действия) край; край.

Декларацията на компонент се състои от секции като частни, защитени, публични и публикувани. Какво имат предвид?
Това са директиви за видимост.
Всичко, което е декларирано в раздела частен, налични само в модула, в който е деклариран класът (частни декларации). Тук по правило се декларират променливи, които съхраняват стойности на свойства, както и методи (процедури или функции) за достъп до тях.
Всичко, което е декларирано в раздела защитени, е достъпен както в частния раздел, така и за потомците на този клас (интерфейс за разработчици).
Тук можете да декларирате методи за достъп до стойностите на свойства (ако искате да позволите на децата на вашия компонент да променят тези методи),
както и свойства, методи и събития (методи за реагиране на събития) в компоненти от тип TCustomXXX.
Всичко, което е декларирано в раздела публичен, достъпен за всеки потребител на компонента (интерфейс по време на изпълнение).
Методите обикновено се декларират тук. В публикувания раздел могат да се декларират само свойства и събития (те се декларират като свойства).
Те са достъпни по време на проектирането на приложението (интерфейс на етапа на проектиране).

Имоти

Свойства на типа масив- обикновени масиви на Object Pascal, но за разлика от последните те могат да бъдат индексирани не само чрез числови стойности, но и чрез низови. За съжаление този тип свойство изисква персонализиран редактор на свойства (в Инспектора на обекти редакторът на свойства има бутон с три точки [...]), така че в примера по-долу свойството ArrayPropобявен в раздел публичен.

Тип TOurComponent = клас(TComponent) частен( Частни декларации ) FArrayProp: масив нацяло число; функция GetArrayProp(aIndex: цяло число): цяло число; процедура SetArrayProp(aIndex: цяло число; констСтойност: цяло число); защитени(Защитени декларации) публичен(Публични декларации) Имот ArrayProp: цяло число Прочети GetArrayProp пишете SetArrayProp; публикувани(Публикувани декларации) край;

Спецификатори на имоти

Спецификатор по подразбиранеуказва дали да се запази стойността на свойството във файла на формуляра или не. Ако стойността на свойството съвпада със стойността по подразбиране- стойността във файла на формуляра не се записва, ако стойностите не са равни - се записва. Можете да проверите това, като поставите компонента във формуляра и изберете елемента от менюто "Преглед като текст" с десния бутон на мишката. По подразбиранене задава първоначалната стойност на свойството на посочената. Това трябва да се направи в конструктора на компонента.

мерна единица OurComponent; интерфейс използва Windows, SysUtils, класове, графики, формуляри, контроли; Тип TOurComponent = клас(TComponent) частен( Частни декларации ) FMyInteger: Цяло число; защитени(Защитени декларации) публичен(Публични декларации) конструкторСъздаване (AOwner: TComponent); отмени; публикувани(Публикувани декларации) Имот MyInteger: Цяло число Прочети FMyInteger пишете FMyInteger по подразбиране 10; край; изпълнение конструктор TOurComponent.Create(AOwner: TComponent); започвам наследениСъздаване (AOwner); FInteger:= 10; край; край.

Спецификатор възел по подразбиранезаменя стойността на свойството по подразбиране. Този спецификатор обикновено се използва за замяна на стойността по подразбиране на наследено свойство.
Например: Имот AutoSize възел по подразбиране;

Спецификатор съхранениуказва кога да се запази стойността на свойството във файла на формуляра. След съхранениможе да устои вярно(винаги запазвам) невярно(никога не записвайте) или името на функция, която връща булев резултат.

Имот OneProp: цяло число Прочети FOneProp пишете SetOneProp съхранениневярно; Имот TwoProp: цяло число Прочети FTwoProp пишете SetTwoProp съхранениВярно; Имот ThreeProp: цяло число Прочети FThreeProp пишете SetThreeProp съхранени Fuct;

И последното нещо:
За да добавите картина към компонент за демонстрация в панела на компонентите, трябва: - да я създадете с размер 24*24 с име на файла.dcr (в ресурса името на картината е равно на името на компонентът, с главни букви)
- поставете снимката до компонента.

развитие софтуерза Windows OS и други популярни може да се направи с помощта на различни видове инструменти. Сред тези, които са много популярни сред руските и чуждестранните програмисти, е програмата Delphi. Какви са спецификите на този инструмент за разработка? Кои са най-забележителните му характеристики?

Обща информация за Delphi

Delphi е среда за разработка на приложни програми, които са проектирани да работят на Windows, MacOS и мобилни устройства. операционна система- iOS и Android. Характеризира се с простотата на езика и процедурите за генериране на код.

При необходимост осигурява комуникация на ниско ниво с ОС и библиотеки, написани на C и C++. Програмите, създадени с помощта на Delphi, не изискват обвивки на трети страни, за да работят, като Java Virtual Machine. Delphi е среда за разработка, която може успешно да се използва както от професионалисти, така и за образователни цели. За да се овладеят основните му възможности не е необходима висока квалификация и познания по сложни езици за програмиране.

Основни предимства

Нека проучим кои са основните предимства на въпросния софтуерен продукт. Когато конкретна ИТ компания обосновава избора на среда за разработка, Delphi става изборът на много програмисти и се препоръчва от тях за използване. Това се дължи на факта, че тази среда ви позволява да създавате приложения възможно най-бързо, като гарантирате тяхната висока производителност дори на тези компютри, които имат скромни хардуерни характеристики. Съществен аргумент в полза на избора на въпросната среда за разработка е, че тя може да бъде допълнена с нови инструменти, които не се предлагат от стандартния набор от решения, присъстващи в интерфейса на Delphi.

Нека сега да проучим нюансите на практическото използване на възможностите на Delphi.

Специфика на интерфейса

На първо място, можете да обърнете внимание на някои характеристики на интерфейса на въпросната среда за разработка на софтуер. По този начин структурата на работното пространство на програмата включва едновременна работа с няколко основни прозореца. Нека разгледаме този имот по-подробно.

Средата за разработка на Delphi, по-специално версия 7, включва използването на следните ключови модули: дизайнер на формуляри, редактор, палитра, инспектор на обекти и справочник. В някои модификации на Delphi маркираните компоненти могат да бъдат именувани по различен начин. Например, редактор може да съответства на прозорец на програмен код, а дизайнер може да съответства на прозорец на формуляр. въпреки това функционално предназначениетехните ще са същите. Маркираният Delphi може да допълва различни помощни инструменти. Първите две се считат за основни от гледна точка на процедурите за разработване на програми. Но и останалите са важни. Нека да разгледаме характеристиките на използването на маркираните модули Delphi.

Дизайнер на формуляри, редактор и палитри

С помощта на дизайнера на формуляри разработчикът създава интерфейса на своята програма. На свой ред неговият код се записва в редактора. Много програмисти, които препоръчват избора на среда за разработка на Delphi като най-оптималното решение, цитират лекотата на използване на дизайнера на формуляри като аргумент. Някои експерти смятат, че този процес е по-скоро игра.

Веднага след като потребителят започне да създава програма и стартира дизайнера на формуляри, първоначално в него няма елементи, той е празен. Но можете веднага да го попълните с помощта на инструменти, разположени на друг модул на Delphi - палитрата. Елементите на програмния интерфейс, които са конфигурирани в дизайнера на формуляри, трябва да се управляват от команди, които от своя страна се записват в редактора.

Но да се върнем към палитрата засега. Използвайки го, можете да поставите необходимите обекти в областта на дизайнера на формуляри. За да използвате определен инструмент, трябва да щракнете веднъж върху него - докато е в областта на палитрата, и втори път - в прозореца на дизайнера на формуляри. След това съответният обект ще се премести в зоната за разработка и можете да напишете код за него в редактора.

Инспектор по обекти

Друг важен елемент, който съдържа Delphi, среда за разработка на приложения за Windows и други често срещани платформи, е обектният инспектор. Може да забележите, че информацията, показана в него, се променя: това се влияе от състоянието на обекта, който е избран в областта на дизайнера на формуляри.

Структурата на обектния инспектор е следната. Състои се от два прозореца. Всеки от тях съдържа алгоритми, които определят поведението на съответните компоненти. Първият показва свойства, вторият показва събития. Ако програмистът иска да направи корекции на алгоритмите, които засягат конкретен компонент, тогава се използват възможностите на обектния инспектор. Например, можете да промените позиционирането на определени елементи на програмния интерфейс, тяхната височина и ширина.

Инспекторът на обекти има раздели, които ви позволяват да превключвате между страници, които показват свойства или събития, които са пряко свързани с редактора. Така че, ако щракнете два пъти върху дясната страна на някой от елементите, показани на екрана, кодът, който съответства на конкретно събитие, ще бъде записан в редактора.

Разработката на софтуер в Delphi включва използването на Object Inspector за решаване на различни проблеми. Това се предопределя от факта, че с помощта на този инструмент можете да промените свойствата на практически всички обекти, разположени във формата, както и самата форма. Нека разгледаме по-подробно някои от функциите на работата с обектния инспектор.

Инспектор на обекти: Използване на функции

За да разберете как функционира IDE на Delphi по отношение на взаимодействието между инспектора на обекти и инспектора на формуляри, можете да опитате да направите промени в свойствата на някои общи елементи на софтуерния интерфейс в Windows - например Memo, Button и Listbox (ще разгледайте тяхната същност по-подробно малко по-късно). Първо, трябва да ги поставите във формуляра с помощта на наличните инструменти на Delphi.

Можете да опитате да експериментирате със свойството Ctl3D. За да направите това, трябва да кликнете върху формуляра, след това да отидете в инспектора на обекти и да промените стойността на въпросното свойство. След това формата ще се промени значително, като в същото време ще се промени свойството Ctl3D на всеки от елементите, които са поставени в прозореца за проектиране.

След като експериментите са проведени, можем да се върнем към формата и да активираме стойността Ctl3D. След това нека разгледаме елементите Memo и Listbox. Сега можете да промените техните свойства, местоположение във формуляра и външен вид. Например, като избере опцията Редактиране в елемента от менюто и след това Размер, програмистът може да промени ширината и височината на обектите. Има опция да ги центрирате, като изберете Редактиране и Подравняване. Съответните действия ще засегнат елементите, показани в инспектора на обекти.

С помощта на въпросния модул Delphi можете да промените свойствата на компонентите. Така например, ако задачата е да се определи конкретен цвят за тях, тогава има опции за използване на няколко инструмента наведнъж. Първо, можете да въведете команда, съответстваща на цвят - например червено - clRed - в областта Второ, потребителят може да избере желания цвят от списък. Трето, има възможност да щракнете два пъти върху свойствата на цвета - ще се появи прозорец за избор на цвят. По същия начин разработчикът може да промени други атрибути на обекти - например типа на шрифта, неговия цвят или размер.

Справочник

Delphi е среда за разработка, която е допълнена от доста подробна помощна система. За достъп до него изберете Помощ от менюто. След това в прозореца ще се покаже един от тези, които отбелязахме по-горе. софтуерни модуливъпросната среда за разработка - справочник. Особеността на използването му е, че когато натиснете F1, потребителят ще получи специфичен намек, отразяващ спецификата на използването на текущия инструмент. Например, ако програмист работи с Object Inspector, той може да избере едно от свойствата, след което да натисне F1 и да получи помощна информация за съответната опция. Същото може да се направи при работа с всеки друг интерфейсен елемент, който включва средата за разработка Delphi 7 и други версии на съответния тип софтуер.

Други елементи на интерфейса

Сред другите важни компоненти на въпросния интерфейс софтуерно решение- меню, панел бърз достъп, както и редактор на изображения. Що се отнася до менюто, то позволява на програмиста бърз достъп до необходимите компоненти, присъстващи в структурата на средата за разработка. Можете да го използвате или с помощта на мишката, или с помощта на горещи клавиши. Точно под менюто е панелът за бърз достъп. Някои от функциите му дублират тези на менюто, но са по-бързи за достъп. Delphi донякъде прилича на програмата Paint в Windows. Тоест с него можете да правите прости корекции на снимки, да поставяте надписи и други елементи върху тях.

Инструменти за програмиране

Delphi е среда за разработка, която включва голям брой инструменти, предназначени да подобрят продуктивността на програмиста. По този начин ключовите модули, които обсъдихме по-горе, се допълват от набор от специални инструменти. Те включват програма за отстраняване на грешки, компилатор, както и компоненти WinSight и WinSpector. Имайте предвид, че в някои версии на Delphi маркираните елементи трябва да се инсталират отделно. Нека проучим техните специфики.

Дебъгер на Delphi

Що се отнася до дебъгера, този инструмент допълва редактора на кода по отношение на извършването на необходимите проверки на коректността на съответните софтуерни алгоритми. С него разработчикът може действително да изследва своя изходен код ред по ред. В някои случаи, когато се решава задача като разработка на компонент, Delphi като независим продукт може да бъде допълнен с външен дебъгер, който дава на програмиста разширени възможности за проверка на кода на създавания софтуер.

Компилатор на Delphi

Нека сега проучим спецификата на компилатора на въпросната среда за разработка. Имайте предвид, че може да има няколко съответстващи елемента в структурата на Delphi. Така че има опция за използване на DCC компилатор, който е полезен в случаите, когато задачата е да работите с приложението във външен дебъгер.

Winsight и WinSpector

Посочените модули са тези, които трябва да бъдат инсталирани допълнително на Delphi. Характеризират се с относителна трудност при усвояване. Въпреки това много програмисти, избрали средата за разработка на Delphi, смятат, че тези компоненти трябва да се научат да използват. По този начин модулът Winsight се използва за наблюдение на съобщенията на Windows. Компонент като WinSpector е необходим за запис на състоянието на компютъра в специален файл. Ако срещнете някакви проблеми по време на разработката на софтуер, винаги можете да отворите този файл и да видите какво може да причинява проблема.

Стандартни компоненти

Средата за разработка Delphi, за която учим като цяло, включва редица стандартни компоненти, които също е полезно да знаете. Експертите ги класифицират като: MainMenu, PopupMenu, Label, Edit, Memo, Button, Checkbox, Radiobutton, Listbox, Combobox, Scrollbar, Groupbox, Panel и Scrollbox. Нека проучим техните специфики по-подробно.

Компонентът MainMenu е предназначен да постави главното меню в интерфейса на създадената програма. За да направите това, трябва да поставите съответния елемент във формуляра, след това да извикате свойството Items чрез инспектора на обекти и след това да определите необходимите елементи от менюто.

Компонентът PopupMenu е предназначен да поставя изскачащи менюта в интерфейса на създадената програма, тоест тези, които се отварят с щракване с десния бутон на мишката.

Компонентът Label се използва за показване на текст в прозореца на програмата. Може да се персонализира, например чрез задаване на желания шрифт в инспектора на обекти.

Компонентът Edit се използва за показване на част от текст на екрана, който потребителят може да редактира, докато програмата работи. Той е допълнен от компонента Memo, който от своя страна може да се използва за работа с по-големи текстове. Този елемент включва например опции като копиране на текст.

Компонентът Button е предназначен да извършва определени действия чрез натискане на бутон, докато програмата работи. Необходимо е да поставите съответния елемент на формата, след което да въведете необходимия програмен код.

Компонентът Checkbox ви позволява да показвате линии на екрана с малък прозорец, в който може да се постави квадратче с мишката. Подобен елемент е Radiobutton. Те се различават, на първо място, външен вид- вторият компонент е направен под формата на кръг, и второ, първият елемент позволява едновременен избор на няколко опции, Radiobutton - само един.

Компонентът Listbox се използва за показване на списък на екрана, който потребителят може да превърта с помощта на мишката. Друг елемент, Combobox, е донякъде подобен на него, но се допълва от възможността за въвеждане на текст в специално поле.

Компонентът Scrollbar е лента за превъртане в Windows. Обикновено се появява автоматично веднага щом текстовото пространство или формата с обекти стане по-голямо от прозореца.

Компонентът Groupbox се използва за запис на реда, в който се придвижвате между прозорците, когато натиснете клавиша TAB. Може да се допълни с панелен елемент, който може да се използва за преместване на няколко обекта във формата.

Компонентът Scrollbox ви позволява да фиксирате област във формуляр, която може да се превърта както хоризонтално, така и вертикално. Това свойство характеризира основните прозорци за разработка на Delphi по подразбиране. Но ако има нужда да активирате такава опция в конкретен раздел на формуляра, можете да използвате компонента Scrollbox.

Резюме

Delphi е мощна среда за разработка на приложения, която в същото време се характеризира с лекота на използване на основните си функции. С помощта на инструментите, включени в структурата му, можете да създадете най-много различни видовепрограми за Windows и други популярни операционни системи.

Изборът на средства за разработка на Delphi от много програмисти се определя от лекотата на използване на интерфейсите на съответния софтуер, както и широк набор от инструменти, полезни за работа на всеки етап от създаването на програма - на етапа на проектиране, програмиране на алгоритми или отстраняване на грешки.


Разработване на собствени компоненти

Ако не сте доволни от стандартните компоненти, които идват с Delphi, тогава е време да опитате ръката си в създаването на свои собствени. Първо ще започнем с прости и постепенно ще преминем към по-сложни. И така, да започваме.

Преди да създадете вашия компонент, е важно да изберете правилния предшественик за него. Кой може да бъде предшественикът на вашия компонент? Обикновено се използва като предци на TComponent, TControl, TWinControl, TGraphicControl, TCustomXXXXXX, както и всички компоненти на палитрата на компонентите. Да вземем за пример компонента TOpenDialog, който се намира на страницата Dialogs на палитрата на компонентите. Върши добре работата си, но има едно малко неудобство. Всеки път, когато го използвате, трябва да променяте стойността на свойството Options всеки път. И като правило това са едни и същи действия.


Щракването върху този ред Ctrl + Shift + C създава шаблон за този метод, вътре в който вмъкваме следните редове:


Инсталиране на създадения компонент Component/Install Component...

  • Инсталиране в нов пакет
  • Име на пакетния файл: C:\Program Files\Borland\Delphi4\Lib\OurTest.dpk
  • Описание на пакета: Нашият тестван пакет

Не ви ли харесва, че нашият компонент има същата икона като стандартния? Тогава нека създадем наши собствени за него. За да направим това, трябва да извикаме Инструменти/Редактор на изображения. Създайте нов *.dcr файл. Вмъкнете изображението Resource/New/Bitmap в него. Задайте размера на изображението на 24x24 пиксела. И след това - вашата креативност... Моля, обърнете внимание: цветът на точките, който съвпада с цвета на точката в долния ляв ъгъл на картината, ще се счита за ПРОЗРАЧЕН!

След като създадете своя чертеж, преименувайте го от Bitmap1 на TOurOpenDialog и запазете файла като OurOpenDialog.dcr. Премахнете компонента от пакета и го инсталирайте отново (само в този случай ще бъде добавена връзка към файла *.dcr).

Компилирайте, инсталирайте и успех!

Професионална разработка на приложения с Delphi 5 | Инструменти за разработка | КомпютърПрес 2"2001

Създаване на Delphi компоненти

Въведение в създаването на Delphi компоненти

Когато разработвате приложения с помощта на Borland Delphi, е удобно да създавате компоненти поради следните причини:

  1. Лекота на използване. Компонентът се поставя във формуляра и трябва да зададете стойности на свойствата за него и да напишете код за обработка на събития. Следователно, ако в даден проект някаква комбинация от контроли и манипулатори на събития, свързани с тях, се среща на две места, тогава има смисъл да се мисли за създаване на съответен компонент. Ако комбинацията от контроли и манипулатори на събития, свързани с тях, се случи повече от два пъти, тогава създаването на компонент гарантирано спестява усилия при разработване на приложението.
  2. Проста организация на групово разработване на проекти. При групова разработка отделните части на проекта могат да бъдат определени като компоненти и работата да бъде възложена на различни програмисти. Компонентите могат да бъдат дебъгвани отделно от приложението, което е доста лесно да се направи.
  3. Обикновено и ефективен методсподеляне на код с други програмисти.Има много сайтове, например http://www.torry.net/, където можете да намерите свободно разпространявани компоненти или да ги закупите срещу символична такса.

Пакети с функции

В Delphi компонентите се съхраняват в пакети. Списъкът с използвани компонентни пакети може да бъде извикан с помощта на елемента от менюто Component/Install Packages (обаче по някаква причина този диалогов прозорец има заглавие Project Options).

С помощта на този диалогов прозорец можете да добавите нов пакет (Добавяне) или да премахнете съществуващ (Премахване). Изтриването не означава физическо изтриване на файл от диска, а по-скоро премахване на връзката от средата за разработка към този пакет. Когато добавите нов пакет, съхранените в него компоненти се появяват на палетата, но когато го изтриете, напротив, изчезват. Вместо да изтриете пакет, можете да „скриете“ съдържанието му на етапа на разработка, като премахнете отметката от името на пакета в списъка. Можете също така да видите компонентите и техните икони (Components). И накрая, можете да редактирате добавени от потребителя пакети (Редактиране) - пакетите, които идват с Delphi, не могат да се редактират (бутонът Редактиране е сив).

В този диалогов прозорец можете да посочите как да създадете проекта: с помощта на пакети за изпълнение или без тях. От това става ясно, че има два вида компонентни пакети: пакет за изпълнение (пакет, който работи по време на изпълнение) и пакет за време на проектиране (пакет, използван по време на разработката). Всички те са DLL (динамично зареждащи се библиотеки).

Пакетите за изпълнение (разширение *.bpl) се доставят на крайния потребител заедно с проекта, ако проектът е компилиран с активирана опция Build with runtime packages. Самото приложение (*.exe или *.dll) в този случай се оказва малко, но заедно с него трябва да се прехвърлят доста големи *.bpl файлове. Според експерти предоставянето на проект с runtime пакети дава предимство в обема на предоставените файлове, само ако включва пет или повече модула (*.exe или *.dll), написани на Delphi. Когато тези модули работят заедно, ресурсите на операционната система се спестяват, тъй като един пакет, зареден в RAM, обслужва няколко модула.

Пакетите за време на проектиране (разширение *.dcp) се използват само на етапа на разработка. По време на разработката те поддържат създаването на компоненти във формуляр. Компилираният Delphi проект включва код не от компонентния пакет, а от *.dcu файлове. Въпреки че файлът *.dcp се генерира от файла *.dcu, тяхното съдържание може да не е същото, ако са направени промени във файла *.pas и пакетът не е компилиран отново. Компилирането е възможно само за пакети, създадени от програмисти. Това се постига чрез щракване върху бутона Редактиране в горния диалогов прозорец. След това се появява формуляр, който ви позволява да манипулирате пакета.

Пакетът съдържа два раздела. Разделът Съдържа съдържа списък с модули, които формират компонентите на този пакет (*.pas- и *.dcu-файлове) и техните икони (*.dcr-файлове). Разделът Required съдържа връзки към други пакети, необходими за работата на тези компоненти. Добавянето на нов компонент към пакета става с бутона Add, а премахването на съществуващ става с бутона Remove. Докато пакетът не бъде компилиран чрез щракване върху бутона Компилиране, всички промени, направени в пакета, няма да се появят в средата за разработка. И накрая, командата Инсталиране е достъпна, когато съдържанието на пакета е премахнато от средата за разработка чрез премахване на отметката от името на пакета в предишния диалогов прозорец.

Командата Option ви позволява да изберете опции за компилиране на пакет, които са подобни на опциите на проекта. Те могат да се използват, за да се определи какъв тип пакет е даден пакет: по време на изпълнение, по време на проектиране или и двете (тип пакет по подразбиране). Опциите определят директориите, в които да се търсят необходимите модули и да се записват резултатите от компилацията. Те също така определят действията, необходими за отстраняване на грешки: дали да се провери или не диапазонът от приемливи стойности, как да се извършват оптимизации, как да се обработват I/O грешки. И накрая, опциите може да включват информация за версията на пакета. Това е много важно, ако приложението се разпространява заедно с пакети за изпълнение: когато стартирате инсталационната програма, информацията за версията ще ви позволи да замените правилно остарелите версии на пакетите и обратното, ако се опитате да инсталирате пакет с по-ранна версия от един вече наличен на даден компютър, последният няма да бъде презаписан.

Шаблони за компоненти

Delphi ви позволява да създавате прости съставни компоненти от няколко общи компонента, избрани във формуляр по време на проектиране. Съответният експерт се извиква с помощта на елемента от менюто Компоненти/Създаване на шаблон на компонент. Този елемент от менюто е достъпен, ако във формуляра е избран поне един компонент. След като го изберете, се появява диалоговият прозорец Информация за шаблон на компонент.

В този диалогов прозорец трябва да посочите името на класа и името на страницата от палитрата на компонентите, където да бъде поставен новият компонент. Ако страница с това име не е в палитрата на компонентите, тя ще бъде създадена. Можете също да промените предложената икона за новия компонент, като качите подходящ *.bmp файл.

Когато се създаде шаблон, се запомнят както свойствата, променени от програмиста в Object Inspector, така и манипулаторите на събития, свързани с избраните контроли. В този случай манипулаторите на събития се запомнят напълно, без филтриране на извиквания към други (неизбрани във формата) компоненти, глобални променливи, методи и т.н. Съответно, ако такива компоненти (променливи, методи) липсват в друг проект, тогава при опит за компилиране на такъв проект ще бъде получено диагностичното съобщение за неизвестен идентификатор.

Кога трябва да използвате шаблони? На първо място, в случаите, когато е необходимо да се променят свойствата, които са налични по подразбиране в базовия клас. Например приложение използва контрола, за да редактира ред от жълт текст. Можете да поставите компонента TEdit във формуляра, да промените свойството Color на жълто, да маркирате този компонент и да го запишете като шаблон. След това можете да получите достъп до този шаблон и компонентът, поставен във формуляра, ще има жълт цвят. Въпреки това, не трябва да злоупотребявате с тази възможност, защото ще бъде създаден нов клас за контрола с променен цвят и всички виртуални методи ще бъдат дублирани в паметта. Това ще се отрази негативно на ресурсите на операционната система.

Също така е удобно да използвате шаблони на компоненти, когато трябва да прехвърлите редица компоненти заедно с манипулатори на събития от една форма в друга. За целта всички те се избират, създава се шаблон на компонент, който се поставя на нов формуляр. В този случай ще бъдат прехвърлени не само самите компоненти, но и манипулаторите на събития, което не може да се постигне при извикване на командите Copy/Paste - в последния случай манипулаторите на събития ще бъдат загубени.

Компонентите, създадени с помощта на командата Create Component Template, са доста различни от обикновените компоненти, създадени с помощта на стандартния метод (описан по-долу). Визуално основната разлика е следната: ако един шаблон включва няколко контроли, след като такъв компонент е поставен във формуляра, можете да изберете отделна контрола и да я изтриете - докато останалите ще останат във формуляра. При стандартните компоненти, ако включват няколко контроли, не е възможно да изберете един от тях и да го изтриете - компонентът се избира и изтрива изцяло.

Създаване на прост компонент

Когато пишете нов компонент, трябва да сте наясно, че компонентът се пише за програмисти, а не за крайни потребители. В този случай е желателно програмистът да не се задълбочава в детайлите на изпълнението на компонента, а просто да използва свойствата и събитията, изложени от него. Това се постига чрез много задълбочено тестване. Нов компонент трябва да бъде тестван дори в ситуации, за които не е ясно проектиран.

Нека поставим проблема по следния начин. Трябва да създадете бутон, който ще издава звуков сигнал при натискане, и да го внедрите като компонент, така че програмистът да може да го постави във формуляр и да го използва. Като цяло, когато разглеждаме компоненти, доста често ще използваме най-простите външни ефекти: звуков сигнал, показване на съобщение и т.н. Това означава, че на местата, където се използват външни ефекти, може да се постави всеки доста сложен код. Просто не се интересуваме от него в момента.

Създаването на компонент започва с избиране на елемент от менюто Компонент/Нови компоненти. След това веднага се появява диалоговият прозорец Нов компонент.

В този диалогов прозорец трябва да дефинирате класа предшественик, името на новосъздадения клас, страницата в палитрата, където ще бъде поставен новият компонент, името на модула, съдържащ изпълнението на новия компонент, и пътя до то. Ако новият компонент използва други модули, чийто път не е описан, те трябва да бъдат дефинирани в полето Search Path.

И така, първата (и може би основната) задача е изборът на клас предшественик. В падащия списък всички компоненти, налични в палитрата, се предлагат като предшестващ клас, включително тези, които не са включени в стандартната дистрибуция на Delphi. Необходимо е да изберете като предшественик клас, който е възможно най-близък по свойства до създавания клас. За нашата задача можем например да изберем TWinControl като предшественик, но в този случай ще трябва да внедрим всички визуални ефекти от щраквания на бутони и т.н. Следователно избираме TButton като предшественик.

Името на новосъздадения клас трябва да отразява съдържанието на компонента и в никакъв случай да не съвпада с името на вече регистриран компонент! На етапа на попълване на този диалог имената не се проверяват за съвпадения - приключенията, свързани с такава грешка, ще започнат по-късно...

Когато избирате страница, трябва да знаете, че ако посочите име на несъществуваща страница, ще бъде създадена нова.

Накрая, когато щракнете върху бутоните Инсталиране и OK, ще бъде създаден шаблон за внедряване на новия компонент. Въпреки това, когато щракнете върху бутона Инсталиране, шаблонът ще бъде поставен в палитрата на компонентите и когато щракнете върху OK, той просто се създава. Препоръчително е да използвате бутона Инсталиране. След като компонентът е инсталиран, той може да бъде поставен върху формата. Сега всички промени, направени в кода за внедряване на компонента, ще бъдат компилирани заедно с проекта и програмистът веднага ще получи съобщения за грешка. Ако компонентът не е инсталиран, за да намерите грешки, той трябва да бъде компилиран чрез редактора на пакети (вижте по-горе), като щракнете върху бутона Компилиране, което е по-малко удобно.

И така, след като щракнете върху бутона Инсталиране, се появява друг диалогов прозорец, който ви позволява да определите пакета, в който ще бъде поставен този компонент.

Този диалогов прозорец има две страници, на първата от които можете да изберете един от съществуващите пакети, а на втората можете да създадете нов. Силно препоръчително е да предоставите кратко текстово описание на пакета; това ще бъде показано в диалоговия прозорец, извикан от командата Component/Install packages (вижте по-горе). След избиране на пакет и натискане на бутона ОК се извиква пакетният редактор, където автоматично се поставя новосъздаденият модул за внедряване на новия компонент. Полезно е да не го затваряте, а да го преместите в един от ъглите на екрана, за да може да се активира с натискане на бутона на мишката.

В същото време в редактора на кода ще бъде създадено „празно“ за описание на новия компонент:

Звуков сигнал на бутона на устройството; интерфейсът използва Windows, Съобщения, SysUtils, Класове, Графики, Контроли, Формуляри, Диалози, StdCtrls; тип TButtonBeep = клас(TButton) частен ( Частни декларации ) защитен ( Защитени декларации ) публичен ( Публични декларации ) публикуван ( Публикувани декларации ) край; регистър на процедурите; процедура за изпълнение Регистър; begin RegisterComponents("Примери", ); край; край.

Самият нов клас декларира четири секции, значението на които е описано подробно в раздела „Видимост на променливи и методи“ на предишната статия от тази серия (ComputerPress No. 1 "2001). В допълнение, новият клас дефинира Процедура за регистриране, която се извиква от средата за разработка на Delphi при инсталиране на този модул като компонент.Тя съдържа името на страницата от палитрата, където е поставен този компонент, и в квадратни скоби - името на класа.Общо взето, методът Register приема масив от типове класове като параметър, тъй като няколко компонента могат да бъдат имплементирани в един модул.Затова те се разделят със запетая, например:

Регистър на процедурите; begin RegisterComponents("Примери", ); край;

Нека продължим с решаването на настоящата задача - създаване на бутон, който издава скърцане. Първо, нека направим нещо тривиално (но както се оказва по-късно, неправилно) - задайте манипулатор на събитие OnClick в конструктора на бутоните. За да направим това, в частния раздел дефинираме заглавката на новия метод BtClick(Sender:TObject) и го внедряваме в секцията за изпълнение:

Процедура TButtonBeep.BtClick(Sender:TObject); beginBeep; край;

конструктор Create(AOwner:TComponent); отмяна;

със задължителна директива за отмяна! Нека го внедрим в раздела за изпълнение:

Конструктор TButtonBeep.Create(AOwner:TComponent); начало наследено Създаване (AOwner); OnClick:=BtClick; край;

След това нека компилираме компонента. Нека поставим бутон на формуляра от страницата Примери и стартираме проекта за изпълнение. Можете да се уверите, че бутонът издава звуков сигнал при натискане!

Сега нека се върнем към средата за разработка и да зададем манипулатор на събитие OnClick в инспектора на обекти. В манипулатора на събития ще покажем текста в заглавието на формуляра:

Процедура TForm1.ButtonBeep1Click(Sender:TObject); begin Caption:="Тест"; край;

Нека стартираме проекта и се опитаме да натиснем бутона. Заглавието на формата се променя, но бутонът спира да бипка! Грешката е, че се опитахме да дефинираме два манипулатора за едно събитие на бутона OnClick: един вътре в компонента BtClick, а другият е зададен с помощта на инспектора на обекти. След като разработихме конструктора TButtonBeep, имахме връзка към първия манипулатор на BtClick. След това ресурсите се зареждат и методът ButtonBeep1Click се присвоява на манипулатора на събитие OnClick. В този случай връзката към първия манипулатор - BtClick - се губи безвъзвратно.

Следователно, когато пишете нови компоненти, винаги трябва да обмисляте промяна на свойствата и манипулаторите на събития с помощта на Object Inspector. Ако дадено свойство (събитие) не трябва да се променя, то не трябва да се показва в Инспектора на обекти. И ако вече се вижда, трябва да го скриете (ще говорим за това по-късно). Програмистът има пълното право да променя каквито и да е свойства в инспектора на обекти и ако след това компонентът спре да работи, виновен е разработчикът на компонента, но в никакъв случай програмистът, който го използва.

Как можем да решим правилно този проблем? Един от начините за създаване на компоненти е пренаписване на съществуващи методи. Когато разглеждате файла StdCtrls.pas, където е внедрен изходният код за компонента TButton, можете да забележите, че той съдържа динамичен метод Click, който може да бъде пренаписан. Затова се връщаме отново към изходния код, създаден от експерта на Delphi при създаването на компонента (премахваме конструктора и метода BtClick). След това в публичната секция дефинираме заглавката на метода:

Процедура Щракнете; отмяна;

и ето изпълнението на метода:

Процедура TButtonBeep.Click; начало наследено Щракване; звуков сигнал; край;

Можете да проверите дали бутонът издава скърцане при натискане. Освен това, при задаване на манипулатор на събитие в инспектора на обекти, този манипулатор се изпълнява и звуковият сигнал не изчезва! Компонентът е внедрен правилно.

Използвайки този пример, е полезно да анализирате възможни грешки при писане на код:

  1. Забравена директива за отмяна при дефиниране на заглавката на метода Click. Бутонът спира да издава звуков сигнал, следователно методът Click не се извиква.
  2. Забравено извикване на метода на предшественика (наследен Click) при изпълнението на процедурата Click. Бутонът продължава да издава звуков сигнал при натискане, но кодът в манипулатора на събития, зададен в инспектора на обекти, не се изпълнява. Следователно методът Click на класа TButton предизвиква събитието OnClick.

Сега нека променим иконата на компонента TButtonBeep на палитрата. По подразбиране иконата на предшестващия компонент се използва за нов компонент. За да направите това, извикайте редактора на изображения чрез командата Инструменти/Редактор на изображения. В редактора извикайте командата File/New/Component Resource File (*.dcr). След командата Resource/New/Bitmap ще се появи диалогов прозорец, предлагащ размер на иконата 32x32. Тези размери по подразбиране трябва да бъдат променени на 24x24 - това е размерът, който иконите на компонентите трябва да имат! След като щракнете върху OK, трябва да нарисувате изображение, като използвате стандартни инструменти, подобни на Paint редактор. Не забравяйте, че цветът на долния ляв пиксел е цветът на маската - този цвят ще бъде „прозрачен“.

След това трябва да предефинирате името на ресурса с иконата; по подразбиране името му е Bitmap1. Новото име на ресурс трябва да съвпада с името на класа - в нашия случай TButtonBeep.

Сега трябва да запишете файла с иконата в същата директория като модула, съдържащ процедурата за регистриране на този компонент, и със същото име като името на модула. Само разширението на файла няма да е *.pas, а *.dcr. Файлът с иконата на компонента е готов. Въпреки това, ако погледнем палитрата Components, ще видим, че старата икона все още е там. Ако рестартирате Delphi или дори операционната система, старата икона ще остане в палитрата. За да промените иконата, компонентът трябва да бъде пререгистриран. За да направите това ви трябва:

Този пример трябва да се счита за тестово упражнение. Преди да напишете нов компонент, трябва да видите дали съществуват подобни сред свободно разпространяваните компоненти. Има почти всякакви бутони: прозрачни, бягащи, кръгли, цветни и др. Приблизително същата е ситуацията и с други компоненти - потомци на същия клас. Следователно най-често трябва да внедрите компоненти, състоящи се от няколко контрола.

Така в този пример проучихме използването на пренаписване на метод за създаване на нови компоненти.

Създаване на сложен компонент

Да приемем, че трябва да въведете списък с имена на клиенти в приложение. В същото приложение ще трябва да въведете и списък с телефонни номера. Въвеждането на списък е доста често срещана операция, така че трябва да обмислите внедряването му като компонент.

За да въведете нов елемент в списъка, ще ви е необходим редактор - компонентът TEdit. След това потребителят трябва да може да види списъка - ще е необходим компонентът TListBox. Освен това ще ви трябват команди, за да запишете текущата стойност от TEdit в списъка, да редактирате избрания елемент от списъка и да го изтриете. Най-лесният начин за изпълнение на тези команди е използването на бутони. За да опростим задачата, ще поставим един бутон върху формуляра, при щракване върху който ще добавим съдържанието на компонента TEdit към списъка.

Така че трябва да създадем нов компонент, който включва TEdit, TListBox и TButton. Както винаги, нека започнем да го създаваме с командата Component/New Component. След това се появява диалогов прозорец, в който трябва да дефинирате класа предшественик, името на класа и името на модула. Няма затруднения с името на класа и името на модула, но името на класа предшественик е неясно. Имаме три контроли. Общият клас предшественик за тях е TWinControl. Но ако го изберем като клас предшественик, ще се сблъскаме с много дълга и досадна имплементация на кода TButton, TEdit и TListBox. В такива случаи е необходимо да изберете компонент като клас предшественик, който може да бъде „баща“ по отношение на други компоненти. Сред стандартните компоненти, разпространявани с Delphi, има три: TPanel, TGroupBox, TScrollBox. Нека изберем панела като клас предшественик, но не самия компонент TPanel, а класа TCustomPanel. По-долу ще обсъдим предимствата на избора на TCustomPanel пред TPanel.

Нека кръстим новия клас TListAdd и щракнете върху бутона Инсталиране. След избиране на пакета, компонентът ще бъде инсталиран в палитрата, откъдето може да бъде поставен във формата на новосъздаденото приложение. Това е удобно, защото когато проектът се компилира, компонентният модул също ще бъде компилиран и ако има грешки, компилаторът ще покаже съобщение.

Би било удобно да поставим нашите контроли върху някакъв формуляр и след това да създадем компонент от тях. В стандартния пакет Delphi няма такъв експерт. Следователно ще трябва сами да създадете компонентите и да ги поставите на панела. Разумно е да се създават контроли - TButton, TEdit и TListBox - в конструктора TCustomPanel, което очевидно изисква пренаписването му. Засега нека поставим контролите в квадрат 100x100. Техните координати също трябва да бъдат определени в конструктора. Трябва да се има предвид, че след като конструкторът на който и да е управляващ елемент е разработен, той все още няма родител, тоест не знае спрямо кой прозорец трябва да измерва координатите на горния ляв ъгъл. Опитът за промяна на координатите на дъщерен прозорец, който няма родител, веднага ще хвърли изключение. Следователно, първият оператор след извикване на конструктора на контролата ще бъде да й присвоим родител, за който ще изберем TCustomPanel. Ние също ще го направим техен собственик, в този случай няма да има нужда да пренаписваме деструктора.

И така, в секцията uses добавяме модула StdCtrls, където се намират описанията на класовете TEdit, TButton и TListBox, а в частната секция дефинираме три променливи:

Частен FEdit:TEdit; FListBox:TListBox; FButton:TButton;

В публичната секция декларираме заглавката на конструктора със задължителната директива за отмяна:

Конструктор Create(AOwner:TComponent); отмяна;

Ние внедряваме конструктора в секцията за изпълнение:

Конструктор TListAdd.Create(AOwner:TComponent); начало наследено Създаване (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; край;

Трябва да се подчертае още веднъж, че деструкторът в този случай не е необходимо да се пренаписва: панелът е собственик на всички контроли и когато неговият деструктор бъде извикан, деструкторите на контролите ще бъдат извикани автоматично.

След повторно компилиране на компонента с помощта на редактора на пакети, промените в компонента вече могат да се видят визуално, на етапа на разработка.

Първият недостатък, който хваща окото, е неадекватното поведение на контролите при мащабиране на компонента. При промяна на размерите му размерите и разположението на елементите не се променят. В допълнение, компонентът може да бъде направен малък, така че три контроли да не се побират върху него. И накрая, когато инсталирате компонент на формуляр от палитрата на компонентите с просто щракване на мишката, неговите размери също оставят много да се желае.

Първо, нека коригираме размерите по подразбиране на компонентите, тоест тези, които са му присвоени автоматично, когато щракнете върху палитрата с компоненти и след това щракнете върху формуляра. За да направите това, просто трябва да посочите новите размери на панела в конструктора:

Ширина:=100; Височина:=100;

След това трябва да подобрите поведението на компонента при мащабиране. За да направите това, трябва да получите съобщение, че размерите са променени. Когато размерът на контрола се промени, системата изпраща съобщение WM_SIZE към нея. Това съобщение трябва да бъде прихванато. За да направите това, в частния раздел описваме заглавката на прихващача на съобщения:

Процедура WMSize(var Message:Tmessage); съобщение WM_SIZE;

и в секцията за внедряване внедряваме неговия манипулатор:

Процедура TListAdd.WMSize(var Message:TMessage); започват да се наследяват; ако Ширина<100 then Width:=100; if Height<100 then Height:=100; FEdit.Width:=Width-55; FListBox.Width:=Width-10; FListBox.Height:=Height-40; end;

Първият оператор е извикване на манипулатора по подразбиране WM_SIZE (наследен). След като го извикате, свойствата Width и Height ще съдържат новата ширина и височина на панела. След това се определят минималните размери на компонента, в случая 100x100. Ако хоризонталният или вертикалният размер е по-малък от минималния, тогава му се присвоява минималната стойност. След това контролите се мащабират, така че да запълнят целия панел с известна вдлъбнатина. Като компилирате компонента чрез редактора на пакети, можете още на етапа на разработка да забележите, че контролите на панела се държат правилно при мащабиране и също така, че размерът на компонента не може да бъде по-малък от 100x100.

Сега ще бъде полезно да стартирате целия проект, опитайте да въведете данни в едноредов текстов редактор и щракнете върху бутона. В този случай нищо не се добавя към списъка. И не е изненадващо, че никъде в нашия компонент не е посочено какво трябва да се направи при натискане на бутона. За да направите манипулатор на събития, свързан с щракването на бутон, можете да продължите както при писането на компонента TbuttonBeep, тоест да дефинирате нов клас - наследник на TButton и да пренапишете метода Click. Дефинирането на нов клас обаче изисква системни ресурси (виртуалните методи се умножават). Ако маркираме компонента във формуляра и погледнем инспектора на обекти, ще открием, че компонентът TlistAdd излага малко свойства и никакви събития, включително никакви манипулатори на събития за бутона OnClick. Следователно това, което отхвърлихме в последната глава като неправилен метод, предефиниране на манипулатора на бутона OnClick, е приложимо в този случай, тъй като програмистът не може да присвои нов манипулатор в инспектора на обекти. И така, в частния раздел описваме заглавката на новия метод:

Процедура BtClick(Sender:TObject);

При реализацията на конструктора TListAdd ние присвояваме този манипулатор на манипулатора на събитие FButton.OnClick:

FButton.OnClick:=BtClick;

И накрая, нека внедрим метода BtClick:

Процедура TListAdd.BtClick(Sender:TObject); start if length(FEdit.Text)>0 then begin FListBox.Items.Add(FEdit.Text); FEdit.Text:=""; FEdit.SetFocus; край; край;

Първо, нека проверим дали едноредовият редактор е празен: няма да добавяме празни редове към списъка. След това прехвърляме съдържанието на редактора в списъка (FListBox.Items.Add(FEdit.Text);) и подготвяме редактора за въвеждане на следващата стойност - а именно изчистваме го от текст (който вече е прехвърлен в списъка ) и прехвърлете входния фокус към него. Сега, след като компилирате и стартирате приложението, можете да се уверите, че работи правилно - когато натиснете бутона, съдържанието на редактора се прехвърля в списъка.

Добавяне на свойства и методи

Ако поставите компонента TPanel до компонента TListAdd и сравните какво се показва в инспектора на обекти, ще забележите, че доста голям брой свойства и събития са изложени за панела, докато само няколко свойства са изложени за TListAdd. Междувременно класът TCustomPanel е предшественик и на двата компонента. За да разберем причината, нека отворим модула ExtCtrls.pas и да разгледаме разликата между класовете TCustomPanel и TPanel. Може да се отбележи, че всички методи и променливи, които осигуряват функционалността на панела, са дефинирани на ниво клас TCustomPanel. Той също така дефинира свойства, които след това се показват в инспектора на обекти за TPanel, само тези свойства се дефинират в секцията Защитени. Имплементацията на класа TPanel е изключително проста: TCustomPanel е дефиниран като предшественик и свойствата на този клас са декларирани, но в публикувания раздел. Става ясно какво трябва да се направи в класа TListAdd, за да се появят свойствата и методите на класа TcustomPanel в обектния инспектор, а именно да се декларират свойствата. В публикуваната секция на класа TListAdd пишем:

Property Align; свойство OnMouseDown;

Когато декларирате свойство, не е необходимо да указвате неговия тип или референтни променливи или методи за четене или запис на свойството. След като компилирате компонента чрез редактора на пакети в инспектора на обекти, можете да наблюдавате появата на свойството Align и събитието OnMouseDown. По този начин, за наследници на TCustom... класове, програмистът има възможност да избира кои свойства и събития да се показват в обектния инспектор и кои не. Поради тази причина се препоръчва класовете TCustom... да се използват като предци за създаване на компоненти.

Сега нека да разгледаме как можете да въведете ново свойство (това, което направихме по-горе, е повторното деклариране на съществуващи свойства). Текстът на бутона може да се използва като подходящо свойство за показване в инспектора на обекти: оставете програмиста, използващ компонента TListAdd, да промени текста по време на проектиране. Опитвайки се да въведем ново свойство (да го наречем BtCaption), използвайки декларация:

Свойство BtCaption:string read FButton.Caption write FButton.Caption;

води до грешка при опит за компилиране на компонента. Затова дефинираме заглавките на два метода в частния раздел:

Функция GetBtCaption:низ; процедура SetBtCaption(const Value:string);

В публикувания раздел декларираме свойството BtCaption:

Свойство BtCaption:низ чете GetBtCaption запис SetBtCaption;

И накрая, прилагаме двата декларирани метода в раздела за изпълнение:

Функция TListAdd.GetBtCaption:низ; begin Result:=FButton.Caption; край; процедура TListAdd.SetBtCaption(const Value:string); begin FButton.Caption:=Стойност; край;

След компилиране на компонент с помощта на редактора на пакети, ново свойство се появява в инспектора на обекти. Промяната в стойността на този имот се отразява директно на етапа на развитие.

Сега нека дефинираме ново събитие. В този случай би било разумно да се създаде събитие, което позволява на програмиста, използващ този компонент, да анализира текста, преди да добави съдържанието на редактора към списъка и да разреши или забрани добавянето на текст към списъка. Следователно този метод трябва да съдържа като параметър текущата стойност на текста в редактора и да зависи от булева променлива, на която програмистът може да присвои стойност True или False. В допълнение, всеки манипулатор на събития в компонент трябва да зависи от параметъра Sender, в който компонентът, който го извиква, предава препратка към себе си. Това е необходимо, защото в средата за разработка на Delphi един и същ манипулатор на събития може да бъде извикан от няколко различни компонента и програмистът трябва да може да анализира кой компонент е извикал манипулатора. И така, след типа дума в раздела за интерфейс, преди да дефинираме TListAdd, дефинираме нов тип метод:

Тип TFilterEvent=procedure(Sender:TObject; const EditText:string; var CanAdd:boolean) на обект;

FOnFilter:TFilterEvent;

И в публикувания раздел дефинираме свойство от този тип:

Свойство OnFilter:TFilterEvent четене FOnFilter запис FOnFilter;

Когато дефинираме ново свойство, ние се позоваваме на променливата FOnFilter, а не на методите - те не са задължителни тук. Сега, ако компилирате компонента с помощта на редактора на пакети, можете да видите събитието OnFilter да се появява в инспектора на обекти. Въпреки това, ако му присвоим манипулатор и стартираме проекта за изпълнение, той може да не бъде извикан. Това е така, защото не сме го извикали никъде в нашия компонент. Добро място за извикване на събитието OnFilter е в манипулатора на събитие OnClick за FButton, който вече е внедрен. Следователно ще променим кода за внедряване на дефинирания по-рано метод BtClick:

Процедура TListAdd.BtClick(Sender:TObject); var CanAdd:boolean; begin if length(FEdit.Text)>0 then begin CanAdd:=True; ако е присвоено(FOnFilter), тогава FOnFilter(Self,FEdit.Text,CanAdd); ако CanAdd тогава започнете FListBox.Items.Add(FEdit.Text); FEdit.Text:=""; FEdit.SetFocus; край на другия звуков сигнал; край; край;

И така, в горния кодов фрагмент е дефинирана булевата променлива CanAdd. Когато пишете код, имайте предвид, че програмистът може да не създаде манипулатор на събития OnFilter. Затова задаваме стойността по подразбиране на променливата CanAdd на True - добавяне на всички редове към списъка. След това, преди да извикате FonFilter, трябва да проверите дали програмистът е създал манипулатор на събития. Това се постига чрез извикване на метода Assigned, който връща булева стойност. За указател извикването на метода Assigned е еквивалентно на проверка на P<>нула. За обектен метод не можем да използваме FOnFilter проверка<>nil, тъй като обектният метод се характеризира с два адреса и такава проверка няма да бъде разрешена от компилатора. Но извикването на метода Assigned перфектно проверява дали е направен манипулатор на събитие. Горният код е абсолютно стандартен начинизвикване на манипулатор на събитие от компонент.

Остава само да тестваме манипулатора на събития. Нека поставим два компонента TListAdd върху формата, като за единия ще позволим добавяне само на цели числа, а за другия - само на думи, започващи с главни английски букви. Съответно кодът за манипулаторите на събития OnFilter ще изглежда така:

Процедура TForm1.ListAdd1Filter(Sender: TObject; const EditText: String; var CanAdd: Boolean); var I,N:цяло число; начало Val(EditText,N,I); CanAdd:=I=0; край; procedure TForm1.ListAdd2Filter(Sender: TObject; const EditText: String; var CanAdd: Boolean); begin CanAdd:=False; if length(EditText)>0 then CanAdd:=(EditText>="A") и (EditText<="Z"); end;

Кодът е лесен за разбиране, единственото предупреждение е, че той проверява дали текстът не е празен низ, преди да провери първата буква от текста в манипулатора на събития ListAdd2Filter. Извършването на такава проверка е задължително: низовете в Object Pascal са обекти и празен низ съответства на нулев указател. Ако се опитате да проверите първата буква на празен низ, приложението ще се опита да дереферира нула, което ще хвърли изключение. В този случай това не е проблем: преди да се извика манипулаторът на събития FOnFilter от компонента TListAdd, низът се проверява за ненулева дължина. Въпреки това, за компоненти, чийто изходен код не е достъпен за вас, такава проверка е задължителна!

Скриване на свойства в инспектора на обекти

Да предположим, че създавате компонент за достъп до данни, например наследник на класа TTable. Да кажем, че този компонент анализира списъка с таблици, налични в базата данни, и въз основа на определени критерии (например наличие на поле от определен тип и с определено име) се избира една за работа. За нормална работа на компонента името на тази таблица трябва да бъде въведено в свойството TableName. Но това свойство се вижда в инспектора на обекти! Програмист, използващ този компонент, може да промени стойността му по време на разработката, което вероятно ще направи компонента неработещ. И той ще бъде прав! Ако някое от свойствата или събитията не могат да бъдат променени, те трябва да бъдат скрити.

Ще продължим да работим върху компонента TListAdd и ще премахнем свойството Cursor от инспектора на обекти като моделна задача. Това свойство е дефинирано в публикувания раздел на класа TControl и се показва в обектния инспектор за TListAdd от самото начало на разработването на компонента. Въз основа на това можете да опитате да замените това свойство в защитения раздел. Компилаторът ще позволи такова заместване, но това няма да доведе до желания резултат: свойството Cursor ще остане в инспектора на обекти както беше... Всяко свойство, веднъж дефинирано в публикувания раздел, винаги ще се показва в обекта инспектор за всички потомци на този клас.

За да скрием свойство от инспектора на обекти, ние използваме две функции на компилатора Delphi, а именно:

  1. Когато декларирате ново свойство със същото име като съществуващо свойство, предварително дефинираното свойство е „засенчено“.
  2. Свойства, които имат достъп само за четене или само за запис, не се показват в инспектора на обекти, дори ако са декларирани в публикувания раздел.

Преди да започнете да работите по скриването на свойството Cursor, добра идея е да премахнете компонентите TListAdd от формуляра, в противен случай може да възникне изключение при четене на ресурса на формуляра. И така, в секцията private ние декларираме променливата FDummy:integer (името и типът на променливата могат да бъдат всякакви), а в секцията public ние дефинираме ново свойство:

Свойство Cursor: integer read FDummy;

Новото свойство трябва да се нарича Cursor, типът му трябва да съответства на типа на променливата, дефинирана по-горе, свойството трябва да е само за четене или само за запис. След като компилирате компонента с помощта на редактора на пакети, трябва отново да поставите компонента TListAdd във формуляра. Може да откриете, че свойството Cursor вече не се вижда в инспектора на обекти.

Сега нека усложним малко задачата. Да предположим, че искате курсорът да се показва не като стрелка, а като пясъчен часовник (crHourGlass). За да промените стойността по подразбиране на свойствата, новата стойност трябва да бъде присвоена на променлива в конструктора. Когато се опитвате да присвоите нова стойност на Cursor в конструктора

Курсор:=crHourGlass;

Компилаторът на Delphi ще издаде диагностично съобщение, че не може да бъде присвоена нова стойност на променлива само за четене. Ако направите ново свойство „само за запис“, компилаторът ще издаде различно диагностично съобщение – относно несъвместими типове данни. Ако декларирате променливата FDummy:TCursor и я направите само за запис, компилаторът ще позволи това присвояване, но външният вид на курсора няма да се промени: той все още ще бъде стрелка.

Тривиално решение на този проблем е да декларирате наследствен клас на TCustomPanel, в чийто конструктор трябва да присвоите нова стойност на променливата Cursor и от нея да създадете нашия компонент TListAdd. Това решение има два недостатъка:

  1. Той е ресурсоемък - виртуалните методи се умножават.
  2. Скрихме свойството в обектния инспектор от програмиста, който ще използва този компонент. Искаме да работим с този имот.

Следователно решението на този проблем изглежда така: в конструктора TListAdd декларираме оператора:

Наследен курсор:=crHourGlass;

и това е! Това е достатъчно, за да промените курсора.

Преди това използвахме наследената функционална дума само за извикване на метод на предшественик. Тази конструкция ви позволява да разберете по-добре значението на inherited като препратка към клас предшественик. Имате достъп както до свойства, така и до методи. При достъп до свойство можете или да го прочетете, или да му присвоите нова стойност; в този случай спомагателната дума inherited се появява отляво на знака за присвояване. По същия начин можете да извиквате скрити методи на предшественик. Извикванията на йерархия, по-високи от класа на предшественика, са забранени - конструкция

Наследено наследено Cursor:=crHourGlass;

няма да се компилира.

На този етап ще считаме този проект за завършен. В новия компонент прихванахме съобщението, декларирахме свойствата, добавихме нови свойства и събития и скрихме предварително декларираното свойство. Всички тези методи се използват за създаване на компоненти. По-долу ще разгледаме друг интересен метод.

Използване на Hook процедури за създаване на компоненти

Беше споменато по-рано, че всяко дете на TWinControl има процедура, която получава и обработва съобщения. Ако има препратка към манипулатора на прозореца (HWND), тогава можете да определите адреса на тази процедура и, което е по-важно, да замените този адрес и по този начин да обработите получените съобщения по ваш собствен начин. По правило никой не пише пълни манипулатори за всички съобщения; старият метод по подразбиране се извиква по-често. В този случай новата процедура се използва като филтър: когато пристигне събитие, кодът се изпълнява. Всъщност това е „шпионин“ в TwinControl: получаваме известие, когато пристигне съобщение и може да се изпълни някакъв код. Ако процедурата Hook е внедрена правилно, TWinControl продължава да работи както обикновено, без да знае, че споделя своите съобщения с някой друг.

Процедурата за закачане се дефинира, както следва:

Процедура (вар. Съобщение:TMessage) на обект;

Зависи от променлива от тип TMessage, която съдържа цялата информация за съобщението. Но дефинирането на тази процедура не е достатъчно. Той трябва да бъде копиран за всеки TWinControl, към който ще бъде прикрепен. Това се постига чрез извикване на WinAPI метода MakeObjectInstance. Този метод приема обектен метод като параметър, прави негово копие в паметта и връща адреса на новия метод. Ясно е, че това запазва системни ресурси, които трябва да бъдат върнати в системата. Това се постига чрез извикване на метода FreeObjectInstance.

Друго важно условие: преди да унищожите TWinControl, трябва да се възстанови комуникацията със старата процедура за обработка на съобщения, в противен случай ресурсите няма да бъдат върнати в системата. Това означава, че ще трябва да запомните указателя към старата процедура, която може да бъде намерена чрез извикване на метода GetWindowLong на Win API с параметъра GWL_WNDPROC. Този указател също ще се използва за извикване на манипулатори на събития по подразбиране на TWinControl. Обратният метод, SetWindowLong, се използва за задаване на Hook процедура.

И така, нека формулираме проблема за следващото упражнение. Да речем, че искаме да създадем компонент, който ще накара други компоненти - наследници на TWinControl - да издават звуков сигнал при натискане на бутона на мишката. Ясно е, че този компонент не трябва да се показва по време на изпълнение на приложението, така че ще изберем TComponent като негов клас предшественик. Нека дефинираме името на класа като TBeepWnd. В частния раздел дефинираме три променливи:

FoldProc,FNewProc:показател; FControl:TWinControl;

От имената става ясно, че ще запомним връзката към старата процедура в променливата FoldProc, връзката към новата процедура (след изпълнение на метода MakeObjectInstance) ще се съхранява в променливата FNewProc. И в променливата FControl ще съхраним връзка към контролния елемент, на който процедурата Hook в момента е „окачена“. Нека дефинираме три метода в същия раздел:

Процедура HookProc(var Message:TMessage); процедура HookWindow(W:TWinControl); процедура UnhookWindow;

и в раздела за внедряване ги прилагаме:

Процедура TBeepWnd.HookProc(var Message:TMessage); start case Message.Msg на WM_LBUTTONDOWN:begin (Нашата задача) Beep; Message.Result:=CallWindowProc(FOldProc, FControl.Handle, Message.Msg, Message.WParam, Message.lParam); край; WM_DESTROY:begin (Когато прозорецът е за унищожаване, премахнете куката) Message.Result:=CallWindowProc(FOldProc, FControl.Handle, Message.Msg, Message.WParam, Message.lParam); UnhookWindow; край; (Извикване на манипулатор по подразбиране) else Message.Result:=CallWindowProc(FOldProc, FControl.Handle, Message.Msg, Message.WParam, Message.lParam); край; край;

В самата Hook процедура се прихваща съобщение, на което се получава реакция - WM_LBUTTONDOWN. В допълнение, всяка Hook процедура трябва да обработва съобщението WM_DESTROY. Това е последното съобщение, което се изпраща до прозореца, преди да бъде унищожен. Нашият отговор е да възстановим предишния метод, като извикаме метода UnhookWindow, описан по-долу. И накрая, манипулаторите на съобщения по подразбиране се извикват чрез метода CallWindowProc. Забравянето на манипулатора на събития по подразбиране е същото като забравянето на наследеното в манипулатора на събития; в 80% от случаите това ще доведе до неправилно поведение на приложението. В никакъв случай не трябва да забравяте да присвоите резултата от извикването на метода CallWindowProc към полето Result на променливата Message! Кодът няма да работи в този случай!

Процедура TBeepWnd.HookWindow(W:TWinControl); start if csDesigning in ComponentState then start (Проверка дали компонент по време на проектиране или по време на изпълнение) FControl:=W; Изход; край; ако FControl<>нула след това UnhookWindow; (Премахнете куката, ако е била инсталирана преди това), ако W<>nil след това започнете FoldProc:=pointer(GetWindowLong(W.Handle,GWL_WNDPROC)); (Определя адреса на старата процедура) FNewProc:=MakeObjectInstance(HookProc); (Направете копие в паметта) SetWindowLong(W.Handle,GWL_WNDPROC,integer(FNewProc)); (Задаване на нова процедура) край; FCControl:=W; (Съхраняване на справка в контрола) край;

Този метод се използва за настройка на нова рутина за обработка на съобщения. Първо, той проверява на кой етап е компонентът: на етап на разработка или на етап на изпълнение. Ако компонентът е в етап на разработка, тоест флагът csDesigning е зададен в свойството ComponentState, тогава просто се запазва връзка към компонента, без да се инсталира Hook процедура. Това се прави, за да се избегне инсталирането на Hook процедура в средата за разработка на Delphi. Ако тази процедура е била предварително зададена на друга контрола, тя се премахва чрез извикване на метода UnhookWindow. След това адресът на старата процедура се запомня (GetWindowLong), прави се копие в паметта на новата процедура (MakeObjectInstance) и се задава адресът на новата процедура (SetWindowLong). Използва се прехвърляне на типове от цяло число към указател и обратно - наречените методи изискват (или връщат) променливи от не съвсем подходящи типове. И накрая, препратката към контролата се съхранява в променливата FControl, която сме дефинирали в частния раздел.

Процедура TBeepWnd.UnhookWindow; започнете ако (FControl=нула) или (FOldProc=нула) или (FNewProc=нула), след това Изход; (Не е инсталирана кука) SetWindowLong(FControl.Handle,GWL_WNDPROC,integer(FOldProc)); (Задаване на стара прозоречна процедура) FreeObjectInstance(FNewProc); (Безплатни ресурси) FControl:=nil; (Иницииране на променливи) FoldProc:=nil; FNewProc:=нула; край;

Този метод възстановява стария манипулатор на събития. Извиква се от метода HookProc и трябва също да бъде извикан от деструктора на компонента - Hook трябва да бъде премахнат както когато прозорецът е унищожен, така и когато този компонент е унищожен. Методът SetWindowLong с адреса на стария метод възстановява стария манипулатор на съобщения. След това трябва да върнете ресурсите на системата, като извикате метода FreeObjectInstance.

И така, основните методи за работа с процедурата Hook са дефинирани. Сега трябва да пренапишете деструктора, така че процедурата Hook да бъде премахната, когато този компонент бъде унищожен:

Деструктор TBeepWnd.Destroy; започнете UnhookWindow; наследено Унищожи; край;

И накрая, в публикувания раздел дефинираме свойство, което ще се показва в инспектора на обекти:

свойство Control:TWinControl четене FControl запис HookWindow;

За да инсталираме нов компонент, ние се позоваваме на предварително дефиниран метод, който, докато приложението работи, незабавно ще „закачи“ Hook процедура на компонента, която ще издаде звуков сигнал при натискане на бутона. Спомнете си, че вместо оператора Beep можете да напишете произволен изпълним код.

Компонентът се тества съвсем просто: той се поставя върху формуляр, върху който са поставени няколко наследствени компонента на TWinControl. След като изберете компонента TBeepWnd във фонов режим, щракването с мишката в полето Control в инспектора на обекти разширява списък, съдържащ всички TWinControl, дефинирани във формуляра. Трябва да изберете един от тях и да стартирате приложението. Когато щракнете с левия бутон на мишката върху избрания компонент, той издава скърцане.

Редактори на свойства и редактори на компоненти

Всичко, обхванато в предишните раздели, се отнася до създаването на кода на приложението, който ще бъде разпространен на потребителите. Въпреки това, средата за разработка на Delphi ви позволява да променяте себе си. Това не изисква познаване на специален език, тъй като всички методи за промяна на средата за разработка са написани на Delphi. Тук тези методи, а именно редактори на свойства и редактори на компоненти, се разглеждат частично - от гледна точка на създаване на инструменти за работа с компоненти. Когато четете материалите в този раздел, трябва ясно да разберете, че крайният потребител, работещ с вашето приложение, никога няма да види нито редактора на свойствата, нито редактора на компоненти - те са създадени за програмисти и работят само в средата за разработка Delphi.

Редактори на имоти

По време на разработката на приложение свойствата се показват в инспектора на обекти. Моля, обърнете внимание, че свойствата се редактират по различен начин в инспектора на обекти. На някои свойства (ширина, надпис) може да се присвои само нова текстова стойност. Свойство от тип Cursor предоставя падащ списък, върху който можете да щракнете, за да изберете стойност. Свойство от тип TFont има знак "+" отляво; Когато щракнете върху него, той се разширява, което ви позволява да променяте отделни полета. Освен това вдясно има бутон с три точки (елипсовиден бутон), при щракване върху който се появява диалоговият прозорец на редактора на свойствата.

Всяко от горните свойства има свой собствен редактор и голямо предимство на средата за разработка на Delphi е възможността да създавате свои собствени редактори на свойства. Новите редактори на свойства са доста често срещани сред разпределените компоненти. Но те трябва да се третират с повишено внимание: първоначално изпълнете тестовете на компютър, където можете да преинсталирате Delphi, ако е необходимо. По правило те се създават от квалифицирани програмисти и няма оплаквания относно кода, но често забравят да включат DLL в редактора на разпределени свойства. След като инсталираме такъв редактор, получаваме редица свойства, които не могат да се редактират - старият редактор е блокиран, а новият не работи...

Преди да създадете нов редактор на свойства, има смисъл да помислите дали си струва да направите това - вероятно можете да намерите подходящ сред стандартните редактори. Ако трябва да създадете редактор на свойства, трябва да следвате правилото: трябва да избягвате създаването на редактори за стандартни типове данни (цяло число, низ и т.н.). Други програмисти са свикнали със стандартните редактори и може да не харесат вашия. Следователно ще трябва да сте скромни и да регистрирате редактора за вашия клас, а не за класа TComponent. Ако програмистите харесат вашия редактор на свойства, повечето от тях ще могат сами да променят регистрацията, така че редакторът да работи за всички компоненти. По-долу ще обсъдим въпроса за регистриране на редактор.

И така, нека поставим моделна задача, за чиято реализация ще е необходимо да се внедри редактор на свойства. Да предположим, че някой компонент има свойството ден от седмицата. По принцип, за да въведете деня от седмицата, можете да използвате стандартен редактор с падащ списък. Искаме обаче програмистът на етапа на разработка да може да въведе деня от седмицата, като посочи или неговия пореден номер (1 - понеделник, 2 - вторник и т.н.), или текст на националния или английски език. При въвеждане на текст е разрешено смесването на главни и малки букви.

На първо място, трябва да създадете компонент, който ще съхранява деня от седмицата. Нека създадем нов компонент, като извикаме командата Компонент/Нов компонент. Нека изберем TComponent като клас предшественик и да дадем на новия клас името TDayStore. След това инсталирайте компонента в палитрата. Сега трябва да решим в каква форма да съхраняваме деня от седмицата. Ясно е, че за недвусмислена идентификация и спестяване на ресурси трябва да се съхранява като цяло число с валидни диапазони 1-7. Въпреки това, ако ще създадем редактор на свойства, трябва да запомним правилото да не създаваме нови редактори за съществуващи типове. Затова ще дефинираме нов тип - TDayWeek, като всички операции с него ще се извършват като с цели числа. Нека дефинираме променливата FDay в частната секция на компонента. Тъй като тази променлива ще бъде инициализирана на 0, когато се изпълни конструкторът по подразбиране и това число е извън разрешените стойности, конструкторът трябва да бъде пренаписан. И накрая, нека дефинираме свойството DayWeek в публикуваната секция, за да го покажем в инспектора на обекти. Крайният компонент изглежда така:

Тип TDayWeek=тип цяло число; TDayStore = class(TComponent) private ( Частни декларации ) FDay:TDayWeek; защитен ( Защитени декларации ) публичен ( Публични декларации ) конструктор Create(AOwner:TComponent); отмяна; публикувано ( Публикувани декларации ) свойство DayWeek:TDayWeek четене FDay запис FDay; край; ... конструктор на внедряване TDayStore.Create(AOwner:TComponent); начало на наследено Създаване (Собственик); FДен:=1; край;

Струва си да се обърне внимание на рядката конструкция на определението за нов тип

TDayWeek=тип цяло число;

Така се въвежда нов тип данни, който има същия размер като целочисления тип; всички операции с този тип данни се извършват като с цели числа. Смисълът на тази операция е да се декларира нов тип данни, така че нашият редактор на свойства да може да се приложи конкретно към него и да не засяга други типове данни.

Сега нека създадем редактор за свойството TDayWeek. За да направите това, добавете нов формуляр към съществуващия проект, запомнете го под подходящо име (DayPropE.pas) и го изключете от проекта. След това ще отворим формуляра като отделен файл и ще внедрим редактора на свойства в него. На първия етап няма да имаме нужда от формата, но по-късно ще реализираме диалог върху нея.

Модулът за създаване на редактори на свойства се нарича DsgnIntf.pas (Design Interface), той дефинира базовия клас TPropertyEditor и класове наследници, предназначени за редактиране на стандартни свойства - TIntegerProperty, TFloatProperty, TStringProperty и др. Механизмът на работа на редакторите на свойства е както следва:

  1. Той се регистрира в средата за разработка Delphi чрез извикване на метода RegisterPropertyEditor. Този метод приема следните стойности като параметри:

    а) информация за типа свойства, за които е предназначен този редактор. Поради тази информация трябваше да дефинираме нов тип TDayWeek;

    б) информация за компонента, в който е приложим този редактор. Редакторът ще бъде извикан не само за посочения компонент, но и за всичките му наследници. Ако зададете това на TComponent, редакторът ще бъде извикан за всеки компонент;

    c) името на свойството, за което се използва този редактор. Ако името е празен низ, се използват горните два филтъра;

  2. Методът GetValue се извиква, когато текущата стойност на свойство трябва да бъде прочетена от компонента. За всяко свойство този метод връща низ, който се поставя в инспектора на обекти.
  3. Методът SetValue се извиква, когато програмистът е въвел нова стойност на свойството в Object Inspector. Нов низ се предава като параметър. В метода той трябва да бъде анализиран и преобразуван към типа на свойството, което се редактира.

Методите GetValue и SetValue са виртуални; когато се пренаписват, се създават нови редактори на свойства. Така че сега можем да започнем да създаваме нов редактор на свойства.

Нека се обърнем към модула DsgnIntf ​​​​в раздела за използване на модула DayPropE.pas и дефинираме нов клас в раздела за интерфейс:

Тип TDWPropED=class(TPropertyEditor) public function GetValue:string; отмяна; процедура SetValue(const Value:string); отмяна; край;

Разделът за изпълнение трябва да прилага и двата метода. В този случай допълнително се нуждаем от списък с имена на дните от седмицата - при първоначалната формулировка на проблема се изисква програмистът да може да въведе деня от седмицата:

Const DayWeek: масив от низ = ("Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота", "Неделя"); DayWeekEn: масив от низ = ("Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота", "Неделя");

Публикации по темата