Урок 51 - Динамическое создание компонентов, часть (2/2)
В этом уроке мы узнаем ошибках которые могут возникать в процессе работы.
Я хочу обратить ваше внимание на один нюанс. Создайте новый проект. В новом проекте создавать тот же компонент 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 его восстановит в том минимальном виде, который нужен для функционирования компонентов.
Поэтому естественно, что мы получили ошибку в предыдущем варианте - не хватало нужных модулей. Теперь смело жмите Run!
Также становится понятно, почему приложение, создающее Memo через нажатие кнопки, сразу заработало. Для работы компонентов Button и Memo необходим один и тот же модуль StdCtrls, описывающий компоненты, расположенные на вкладке Standart. Поэтому, когда мы положили на Форму компонент Button, Delphi добавил этот модуль, что обеспечило работу также и Memo.
Так вот что нужно делать, чтобы подобная ошибка не появлялась. Просто положите на Форму из палитры компонентов компонент, который вы создаёте динамически, и жмите Run. Всё, после компиляции компонент можно удалять за ненадобностью - модуль, необходимый для его работы, Delphi затирать не станет! И ваш динамически создаваемый компонент будет работать.
Можно, конечно, обойтись и без добавления на Форму и последующего удаления компонентов, которые мы в программе будем создавать динамически. Посмотрите - при наведении мышки на любой компонент в Палитре Компонентов всплывает подсказка с названием модуля, в котором он описан. Добавьте это название в список uses, и всё! Но если ошибётесь в какой буковке - пеняйте тогда на себя.
Теперь возникает вопрос, как можно создать приложение аналогичное первому, где компонент Memo создавался динамически по нажатию кнопки, но чтобы кнопка тоже была создана динамически!
Динамически создать кнопку мы можем в обработчике OnCreate Формы, точно так же, как и компонент Memo. Однако она не будет работать - создавать компонент Memo. Естественно, ведь обработчика OnClick для неё мы не создали! Давайте сделаем это.
Естественно, проще всего создать обработчик для динамически создаваемого компонента, воспользовавшись готовым компонентом из палитры. Создаём для него нужный обработчик, а затем этот компонент просто удаляем. А теперь достаточно присвоить имя созданного обработчика соответствующему свойству динамического компонента. Название этого свойства будет совпадать с названием соответствующего события в Инспекторе Объектов. Например, для события OnClick пишем так:
Button.OnClick:=Button1Click;Естественно, имя обработчика может быть любым, просто в данном случае я воспользовался тем обработчиком, что создал Delphi для кнопки из палитры. Если оно вам не нравится, можно смело переименовать процедуру, только не забудьте изменить её название также и в описании типа Формы.
Теперь мы умеем создавать компоненты динамически, и можем наделать компонентов столько, сколько нам требуется. Но такие уж они, динамически создаваемые компоненты, что надобность в них как появляется, так и исчезает - динамически! Иногда нужно и уничтожить компонент. Для уничтожения компонента есть простой метод: Free.
Component.Free;Вот и всё. Все ресурсы, выделенные для функционирования компонента, будут освобождены. Останется только созданная переменная, указывающая на уже несуществующий в памяти объект. Её тоже неплохо бы уничтожить - "разименовать", присвоив nil. Есть процедура, выполняющая оба эти действия, и уничтожение объекта, и разименование переменной: FreeAndNil:
FreeAndNil(Component);И это относится не только к динамически созданному - к любому компоненту и объекту в памяти.
Удачи!
Встретимся в следующем уроке!