вторник, 17 мая 2011 г.

Урок 9 . Создание собственного компонента (TMyLabel)



Я предлагаю на время отложить проект таймера, которому были посвящены предыдущие уроки, вплоть до последнего. Когда-то я говорил, что использование стандартных компонентов рано или поздно надоест, если, конечно, Вы программируете постоянно, а не увлеклись этим в связи с предстоящим завтра зачетом. “Почему?” - удивленно спросите Вы. В качестве иллюстрации ответа, приведу в пример компонент TPanel. Сколько бы я ни использовал его, мне всегда приходилось стирать вручную надписи Panel1, Panel2 и т.п., располагаемые в центре панели поумолчнию.
Возьмите следующим TLabel. Киньте его на форму. По умолчанию его свойство AutoSize установлено в True, что приводит к автоматическому изменению ширины надписи в зависимости от длины текста, помещенного в Caption. Случаев, когда от такого поведения компонента я пришел бы в восторг, что-то припомнить не могу. Наоборот, всегда приходилось переназначать это свойство вручную.
Это были первые - самые простые примеры. С них и предлагаю начать, чтобы понять процесс, а впереди будут компоненты более сложные и очень сложные.
В двух словах коснусь того, что компоненты наследуются один от другого и имеют общих предков, которых в итоге меньше, чем пальцев на одной руке, но этот материал подробно изложен во множестве учебников. К сожалению, хороших учебников мало, а те, что общепризнаны удачными (Рея Конопки и Валерия Фаронова), довольно сложны для начала. Памятуя о тех трудностях, которые испытывал я, взявшись за изучение этой темы когда-то, я и хочу в простой и доступной форме рассказать о процессе создания и отладки компонентов.
Откройте среду разработки Delphi и создайте новый компонент, выбрав в меню Component - New VCL Component (создавать мы будем компонент для библиотеки визуальных компонентов - VCL).

В следующем окне выберите TLabel в левой колонке. Это и будет предок, от которого наш компонент унаследует все свои свойства. Нажмите “Next”.
Затем придумайте имя Вашему классу, помня о том, что можно использовать только латинские буквы и все подобные имена начинаются с заглавной “Т”. Выберите или задайте имя закладки на панели инструментов и укажите каталог, где будет храниться файл. Последнее поле “Search Path” оставьте пока пустым.

<Next> - <Finish> и оболочка создаст заготовку под Ваш новый компонент:
Сохраните файл, указав выбранный на предыдущем шаге каталог.
unit MyLabelLes;                     // Заголовок модуля
interface                                 // Начало раздела Interface
uses
SysUtils, Classes, Controls, StdCtrls;   // Объявления задействованных модулей
type
TMyLabelLes = class(TLabel)  // Объявление класса, наследуемого от TLabel
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
end;
procedure Register;                  // Объявление стандартной процедуры,
// регистрирующей новый компонент
implementation                         // Начало раздела  implementation
procedure Register;                 // Код стандартной процедуры
begin
RegisterComponents('Lessons', [TMyLabelLes]);  // Оператор, который зарегистрирует
// компонент TMyLabelLes на закладке
// Lessons
end;
end.
Все остальное нам придется дописать ручками.
А всего остального осталось не много: дописать в раздел implementation конструктор - специальную процедуру:
constructor TMyLabelLes.Create( AOwner: TComponent );  // Прародитель - TComponent
begin
inherited Create(AOwner);                       // Наследуются все “прелести” прародителя
AutoSize:=False;                                     // А следующие три оператора... устанавливают
Height:=13;                                          // нужные нам свойства, которыми будет
Width:=80;                                          // наделен новый экземпляр компонента
// сразу после его создания
end;
Эта специальная процедура “производит на свет”, как Вы могли догадаться из названия, собственно сам компонент. Помните, я упоминал в начале урока, что таких прародителей - по пальцам перечесть. Вот один из них: в первой строчке виден - TComponent. От него происходят визуальные компоненты.
Следующий оператор передает все свойства прародителя в новый компонент. Если больше ничего не написать, то мы получим новый компонент TMyLabelLes в точности копирующий обычную метку TLabel. Но у нас задача - сделать свойство AutoSize=False, чтобы надписи, размещаемые на форме, не меняли свою ширину в зависимости от помещенного в них текста. Следующие три оператора принудительно изменяют свойства у нового компонента.
Не забудьте добавить объявление этой процедуры в раздел Public
Constructor Create( AOwner: TComponent); override;
Сохраните файл.
Делаем следующий шаг - создаем пакет Меню - File - New … как показано на рисунке:

Затем кнопкой “Add File To Project” (на панели кнопок) необходимо добавить созданный на предыдущем шаге файл MyLabelLes.pas в данный пакет.
Обязательно сохраните пакет, дав ему осмысленное имя. Причем, если Вы попытаетесь назвать его так же, как файл, содержащий текст компонента, то Delphi выдаст ошибку, поэтому назовите его, например: MyLabelLesPack.
Затем скомпилируйте пакет, щелкнув правой кнопкой в окне Project Manager на заголовке проекта и выбрав в контекстном меню Compile.
Если система определит наличие ошибок, исправьте их и повторите компиляцию.
В случае, если ошибок нет, можно приступать к установке компонента в Вашу среду разработки. Для этого щелкните правой кнопкой все по тому же заголовку проекта в окне Project Manager и выберите Install.
Система должна выдать сообщение об успешной установке.
Важно: нажмите пиктограмму сохранить на панели кнопок.
Закройте проект.
Полюбуйтесь своим детищем:
меню Component - Install Packages, найдите его в списке и щелкните кнопку Components:

Есть!
Теперь нужно протестировать новый компонент.
Для чего создайте новый проект VCL Form Application и положите на форму Label с вкладки Standart и MyLabelLes с вкладки Lessons. Обратите внимание на разницу свойств и поведения этих компонентов. Это особенно видно в наглядном видео уроке.
Разберемся, где что хранится. Для чего это нужно? Предположим, что Вы отлаживали какой-то компонент, долго его настраивали и, наконец, получили то, что хотели. Но для его отладки Вы использовали временную папку, а все компоненты у вас живут где-то в Program Files/Borland и т.д. Или, например, Вы хотите передать этот удачный компонент коллеге по работе. Или у вас два компьютера: настольный и переносной. А Вы хотите везде иметь среду разработки с одинаковым набором. Чтобы лучше это понять, давайте удалим вновь созданный компонент. Перенесем его в другую папку и вновь инсталлируем его.
Я сделаю это один раз, в этом уроке и больше к этому важному вопросу возвращаться не будем.
Итак.
1. Закройте все открытые проекты (File - Close All)
2. Меню, Component и т.д., как показано на рисунке:

3. Очень важный шаг: удалите путь, меню Tools - Delphi Option - Library - Win 32 и т.д., как показано на рисунке.

Если этого не сделать, то перенос компонента в другую папку приведет к некоторой путанице. Система может упрямо тащить компонент из прежнего места.
4. Проверьте, используя проводник, каталог, указанный как Output:

В этой папке не должно остаться никаких файлов с тильдами в имени файла, никаких MyLabelLesPack.bpl.
5. Перенесите папку с исходниками компонента в папку Program Files/borland и т.д. или любой другой, удобный Вам.
6. Повторите установку компонента.
Что же дальше?
Предлагаю продолжить разговор о создании нескольких собственных компонентов: я к ним привык, а для Вас - полезная практика. Впереди - разговор о создании компонента сообщения, компонента гиперссылки и более сложного компонента - формы “About”. А чуть позже мы вернемся к оставленной временно программе и используем в ней новые конструкции.

3 комментария:

  1. Борис6/8/12 15:15

    В Delphi 7 никак не смог создать пакет. При компиляции выдается ошибка: "Required package 'rtl' not found". Не создавая пакет установил компонент - все заработало. Что это за ошибка и как ее устранить?

    ОтветитьУдалить
  2. Работает. Перепробовал с десяток примеров с разных сайтов. Работает только этот (пробовал на XE8, инструкция там правда уже немного отличается, но интуитивно понятно)

    ОтветитьУдалить

Примечание. Отправлять комментарии могут только участники этого блога.