Советы по Delphi


FAQ 9, Компоненты


"Могу ли я пользоваться исходным кодом VCL?"

Если вам интересен процесс создания новых компонентов, тогда да, стопроцентное ДА! Имея исходный код VCL, вы можете изучить и понять принцип создания компонентов VCL вплоть до секций private. Это окажет неоценимую помощь при создании собственных компонентов. Также вы будете иметь возможность пройтись по исходному коду компонент с помощью отладчика.

"По вашему совету я приобрел исходный код VCL, но почему я не нашел там исходный код для "tab"-элементов управления (например, TTabbedNotebook и др.)?"

Исходный код VCL не содержит код "tab"-компонентов из-за юридических причин. Тем не менее, исходники интерфейса (interface source) расположены в каталоге DELPHI\DOC и имеют расширение INT.

Примечание: зарегистрированные владельцы исходного кода Delphi RTL могу запросить исходный код TTabSet и TTabbedNotebook у подразделения Borland Corporate Affairs, контактное лицо Karen Rogers, факс (US) 408-431-4171.

"Я пытаюсь создать свой собственный компонент, но я не знаю от кого мне нужно наследоваться."

Простейший путь - унаследоваться от существующего компонента, т.к. он уже содержит необходимый набор свойств и характеристик. Если вы хотите создать новый компонент "с нуля", используйте один из следующих классов:

TComponent - Базовая отправная точка для невизуальных компонентов. TWinControl - Базовая отправная точка для компонентов, которым необходимо иметь оконный дескриптор. TGraphicControl - Хорошая отправная точка для компонентов, которым не нужен дескриптор окна. Данный класс имеет метод Paint, который должен быть перекрыт, но не имеет холста. TCustomControl - Наиболее удачная отправная точка для визуальных компонентов. Данный класс имеет дескриптор окна, общий набор событий и свойств и, что наиболее важно, хост и метод Paint(). "Как мне переписать для моего приложения обработчик сообщения по умолчанию?"

Создайте динамический метод, индексирующий константу сообщения, которую вы хотите перекрыть. Например, если вы хотите перекрыть сообщение CM_DIALOGKEY, объявите следующую процедуру в секции public объявлений класса:

    Procedure CMDialogKey(var Message: TCMDialogKey);message CM_DIALOGKEY;

Это распространенная практика - объявление имени процедуры такой же, как и имя сообщения минус символ подчеркивания. Ваш обработчик сообщения должен выглядеть примерно так:

    Procedure TForm1.CMDialogKey(var Message: TCMDialogKey); begin if CharCode = VK_TAB then begin {Здесь обрабатываем нажатие Alt+Tab} result := 1; exit; end; inherited; end;

Устанавливаем результат в единицу и недопускаем последующюю обработку. С помощью ключевого слова inherited мы передаем управление родительскому обработчику. Не забывайте выполнять inherited, если вам необходимо дополнить поведение компонента, оставив выполнение обработки по умолчанию.

"Какое наилучшее место в коде программы, откуда можно вызвать окно с логотипом программы при ее запуске?"

Наилучшее место для показа окна с логотипом - в исходном коде проекта после первого FormCreate и перед Run. Этим мы осуществляем создание формы на лету и показ ее до момента фактического запуска приложения.

    program Project1;
uses Forms,  Unit1 in 'UNIT1.PAS' {Form1}, Splash;
{$R *.RES} var SplashScreen : TSplashScreen; {в модуле Splash}
begin Application.CreateForm(TForm1, Form1); SplashScreen := TSplashScreen.Create(Application); try SplashScreen.Show; { осуществите остальные CreatForms или другие действия прежде чем приложение запустится } SplashScreen.Close; finally  {Убедитесь что окно с логотипом освобождается} SplashScreen.Free; end; Application.Run; end.

"Какой порядок возникновения событий при создании формы и ее показе?"

При создании формы события происходят в следующем порядке: OnCreate, OnShow, OnPaint, OnActivate, OnResize и снова OnPaint.

"Почему моя программа не может найти ресурсы, упакованные мной в .RES-файл, если .RES-файл имеет то же самое имя, что и модуль формы?"

Если имя используемого вами .RES-файла совпадает с именем .DPR-файла, Delphi перезапишет его, создав собственный .RES-файл с этим именем.

"Я унаследовался от компонента TPanel. Я вижу, что в конструкторе присутствует свойство BevelWidth; его значение всегда равно 1 независимо от того, что установил пользователь в режиме проектирования. Очевидно, значение свойства изменяется в режиме проектирования где-то после того, как "сработает" конструктор. Где это происходит? Где лучшее место для перехвата этого значения при инициализации компонента?"

При чтении компонент из потока каждый компонент сначала создается, после чего его значения читаются из потока. Метод компонента Loaded вызывается после окончания его чтения из потока. Если вам необходимо изменить его свойства после его загрузки из потока, вы должны перекрыть метод Loaded.

"Я пытаюсь опубликовать свойство массива, но получаю ошибку #202, говорящую о том, что свойство не может быть опубликовано. Я думал что свойство, имеющее редактор, можно опубликовать.

Обратитесь в раздел электронной справки "published parts", где вы можете увидеть, какие свойства и поля могут быть опубликованы, а какие нет. Для того, чтобы нестандартные типы данных (к которым относятся свойства массива) могли работать с потоком, перекройте унаследованный метод компонента DefineProperties для регистрации авторской реализации механизма чтения и записи свойства. Для примера посмотрите исходный код TStringList - там используется DefineProperties для регистрации собственного "читателя" и "писателя" для обработки потока строк в собственном списке.

"Я создаю компонент во время выполнения приложения, но объявленные значения по умолчанию ("default") почему-то не работают. Почему?"

Вам нужно убедиться в том, что вы присвоили свойству значение по умолчанию в конструкторе вашего компонента. Значение свойства "default" не используется, если вы создаете компонент во время выполнения приложения.

[000585]




Начало  Назад  Вперед