Компоненты Delphi

Динамическое создание компонентов в Delphi




Уроки Delphi
  1.  Первая программа
  2.  Использование компонентов
  3.  События Delphi
  4.  Типы данных Delphi
  5.  Создание своих типов данных
  6.  Выражения и операторы
  7.  Работа с файлами в Delphi
  8.  Дополнительные формы
  9.  Подпрограммы в Delphi
  10. Исключительные ситуации
  11. Обзор компонентов
  12. Работа со строками
  13. Создание интерфейса
  14. Графика в Delphi
  15. Многопоточность в Delphi
  16. Динамическое создание
        компонентов
Поиск по сайту


 Это важно:
   Метод Application.ProcessMessages;

 Это полезно:
   Параметр Sender в обработчиках событий;














   Динамически создаваемые компоненты - это компоненты, место в памяти под которые выделяется по мере необходимости в процессе работы приложения. Этим они и отличаются от компонентов, которые помещаются на Форму при проектировании приложения. Возможность создавать компоненты динамически это очень большое удобство для программиста. Например, можно создавать в цикле сразу много однотипных компонентов, формируя из них массив, которым в дальнейшем очень просто управлять.

   Все компоненты, как объекты, имеют множество свойств, определяющих их работу. При установке компонента на Форму из палитры большинство этих свойств определяются системой Delphi автоматически. При создании динамического компонента программист должен описать и настроить их вручную. Посмотрим, как это делается.

   Прежде всего, для появления динамически создаваемого компонента нужно выделить под него место в памяти. Выделением места в памяти компьютера под любой компонент занимается конструктор типа объекта этого компонента - метод Create. Для этого сначала нужно описать переменную нужного типа, а затем для выделения памяти воспользоваться методом Create. Метод Create имеет параметр Owner, определяющий так называемого "владельца" для создаваемого компонента.

   Хотя на самом деле владелец нужен не для создания, а для уничтожения компонента. То есть, при уничтожении компонента-владельца происходит автоматическое уничтожение всех компонентов, у которых он указан в качестве владельца.
   При обычной установке компонента из палитры система делает владельцем этого компонента Форму. Проще всего поступать так же. Однако можно указать в качестве владельца сам этот компонент, воспользовавшись в качестве параметра ключевым словом Self.

   Далее. Когда компонент создан, то есть место в памяти под него выделено, можно задавать значения параметрам этого объекта. Прежде всего, это ещё один компонент, так называемый "родитель". Компонент-родитель будет отвечать за отрисовку нашего динамически создаваемого компонента. Это значит, что новый компонент появится в границах компонента-родителя.

   Если компонент-владелец имеет тип TComponent, то есть может быть любым компонентом, то компонент-родитель уже имеет тип TWinControl. То есть это должен быть "оконный" компонент, умеющий принимать и обрабатывать сообщения от системы Windows. Это необходимо, так как компонент должен находиться в некоторой иерархии компонентов, принимающих и передающих сообщения от системы Windows. Нашему динамическому компоненту сообщения будут передаваться через компонент-родитель.

   А некоторые компоненты вообще не умеют принимать сообщения от системы, и в процессе работы в этом случае ими также будет управлять компонент-родитель, например, Форма или Панель, на которой они находятся.

   Естественно, компонент не может быть родителем для самого себя. Имя компонента-родителя просто присваивается свойству Parent создаваемого динамически компонента.

   Вот общая схема "конструирования" динамически создаваемого компонента:

   var Component: TComponent;//Описать переменную для компонента

   begin
     Component:=TComponent.Create(Owner);//Задать владельца
     Component.Parent:=Parent;//Задать родителя
   end;

   На этом создание компонента можно считать законченным, и он успешно появляется (или "не появляется", если он не визуальный!) в приложении. Остальные свойства будут присвоены ему по умолчанию самой системой Delphi.

   Естественно, значения таких свойств по умолчанию для визуальных компонентов как положение на Форме, ширина, высота "свежесозданного" динамически компонента мало кого устроят. Нужные размеры и положение компонента также придётся задать программисту.

   Давайте для примера динамически создадим многострочный редактор, компонент Memo. Пусть он появляется на Форме по нажатию кнопки:
procedure TForm1.Button1Click(Sender: TObject);
var Memo: TMemo;
begin
  Memo:=TMemo.Create(Form1);
  Memo.Parent:=Form1;
  Memo.Left:=50;
  Memo.Top:=50;
  Memo.Width:=250;
  Memo.Height:=100;
  Memo.Text:='Мама я родился!';
end;

Динамически созданный компонент Memo
   Ребята, не забывайте присваивать (ассоциировать в Инспекторе Объектов) своим кнопкам предлагаемые здесть процедуры. А то потом в комментариях и появляются возгласы: "ничего не работает!"

   Теперь хочу обратить ваше внимание на один нюанс. Создайте новый проект. Создайте-создайте, а то не получите того эффекта, на который я рассчитываю. В новом проекте создавать тот же компонент Memo мы будем в обработчике OnCreate Формы, чтобы Форма появлялась уже с нашим компонентом. Для пустой Формы создайте обработчик события OnCreate и наполните его тем же самым кодом. И что же - при попытке исполнить приложение мы получим от компилятора ошибку!

   А дело вот в чём. Посмотрите на список используемых стандартных модулей в операторе uses:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

   Теперь возьмите в Палитре компонентов компонент Memo или ту же кнопку Button, положите на Форму и попытайтесь запустить приложение. Только что отказывавшееся работать приложение работает как ни в чём не бывало! Опять смотрим на список модулей:

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

   Подчёркиванием я выделил модуль, который автоматически добавил Delphi к списку необходимых модулей. Перед выполнением приложения компилятор просматривает установленные компоненты и добавляет в список uses модули, необходимые для работы этих компонентов. Так что даже если вы полностью сотрёте этот список ( оставьте только "uses Forms;"), Delphi его восстановит в том минимальном виде, который нужен для функционирования компонентов.

   Теперь понятно, почему приложение, создающее Memo через нажате кнопки, сразу заработало. Для работы компонентов Button и Memo необходим один и тот же модуль StdCtrls, описывающий компоненты, расположенные на вкладке Standart. Поэтому, когда мы положили на Форму Button, Delphi добавил его, что обеспечило работу также и Memo.

   Так вот что нужно делать, чтобы подобная ошибка не появлялась. Просто положите на Форму из палитры компонентов компонент, который вы создаёте динамически, и выполните приложение. Всё, компонент теперь можно удалять за ненадобностью - модуль, необходимый для его работы, Delphi затирать не станет! И ваш динамически создаваемый компонент будет работать.

   Теперь возникает вопрос, как можно создать приложение аналогичное первому, где компонент Memo создавался динамически по нажатию кнопки, но чтобы кнопка тоже была создана динамически!

   Динамически создать кнопку мы можем в обработчике OnCreate Формы точно так же как и компонент Memo. Однако она не будет работать - создавать компонент Memo. Естественно, ведь обработчика OnClick для неё мы не создали! Давайте сделаем это.

   Естественно, проще всего создать обработчик для динамически создаваемого компонента, воспользовавшись готовым компонентом из палитры. Создаём для него нужный обработчик, а затем этот компонент просто удаляем. А теперь достаточно присвоить имя созданного обработчика соответствующему свойству динамического компонента. Название этого свойства будет совпадать с названием соответствующего события в Инспекторе Объектов. Например, для события OnClick пишем так:

   Button.OnClick:=Button1Click;

   Естественно, имя обработчика может быть любым, просто в данном случае я воспользовался тем обработчиком, что создал Delphi для кнопки из палитры. Если оно вам не нравится, можно смело переименовать процедуру, только не забудьте изменить её название также и в описании типа Формы.


Обзор компонентов Delphi           В начало урока          Динамическое создание компонентов

Уроки Delphi начинающим

Вопросы и комментарии (11)

Оставить комментарий:

Имя  

Текст комментария