Язык программирования Delphi. Компоненты в рантайме:
Сегодня я написал маленький примерчик, который ответит сразу на два поставленных мне вопроса: как создавать компоненты в рантайме и как ими управлять. На оба я отвечал автору по e-mail и в обоих случаях адрес отправителя оказывался ошибочным и ответ не находил своего получателя. Возможно таким образом мои читатели увидят ответ на свой вопрос. А в будущем, указывайте правильный e-mail.
Рис 1. Форма
Что такое рантайм? Твоя прога может находиться в двух состояниях - дезайнтайм (время создания проекта) и реалтайм (время выполнения проекта). Мы сегодня будем создавать компоненты не рисованием на форме, а чистым кодом уже во время выполнения проги.
Создай новый проект и брось на него два компонента TLabel. Всё остальное будем делать ручками.
Для начала, в разделе private объявим переменную CompList типа TList. TList - это "объект-контейнер", который может хранить в себе кучу других. Точнее сказать, он хранит только ссылки, но это не главное. Главное - TList позволяет хорошо управлять хранящимися в нём объектами.
На событие OnCreate напиши:
procedure TForm1.FormCreate(Sender: TObject);
begin
CompList:=TList.Create;
end;
Здесь мы инициализируем нашу переменную CompList с помощью объекта TList. Во время инициализации выделяется память под нашу переменную.
Сразу же на событие OnDestroy пишем:
procedure TForm1.FormDestroy(Sender: TObject);
begin
CompList.Free;
end;
Здесь мы освобождаем выделенную память для переменной CompList.
Теперь в обработчике нажатия мышкой напишем:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
TempPanel:TPanel;//Объявляю переменную для панели
begin
//Создаю панель. В скобках у Create указан будущий владелец
TempPanel:=TPanel.Create(Form1);
TempPanel.Left:=X; //Устанавливаю левую и правую координату
TempPanel.Top:=Y; //в X и Y позицию, где нажата кнопка мыши
TempPanel.Width:=20; //Устанавливаю ширину
TempPanel.Height:=20; //Устанавливаю высоту
//Далее устанавливаю обработчик нажатия на эту панель
TempPanel.OnMouseDown:=PanelMouseDown;
//Добавляю панель в контейнер CompList (CompList.Add)
//и сохраняю результат в TempPanel.Tag
TempPanel.Tag:=CompList.Add(TempPanel);
Form1.InsertControl(TempPanel); //Вставляю панель на форму
end;
Что это за свойство Tag у компонента TPanel? Это просто целое значение, которое ты можешь использовать по своему усмотрению. Я засовываю в TempPanel.Tag индекс панели в контейнере CompList, который мне возвращается при добавлении панели в контейнер. Это абсолютно не влияет на сам компонент, а мне этот индекс пригодится.
Теперь об обработчике TempPanel.OnMouseDown. Я туда засунул имя функции PanelMouseDown. Но такой функции нет среди стандартных функция и среди моего проекта. Поэтому мы должны её создать сами. Как это сделать эффективно? Вот тебе мой совет:
Мы создаём обработчик для TPanel, поэтому временно поставь один экземпляр на форму в произвольное место.
Создай для него обработчик на OnMouseDown и переименуй его в PanelMouseDown.
Напиши нужный текст (я его покажу ниже) и можно удалять временно созданный на форме экземпляр TPanel.
Таким образом, ты можешь быть уверен, что ошибок не будет, потому что Delphi сама пропишет функцию PanelMouseDown где надо.
Если захочешь объявлять эту функцию вручную, то напиши в разделе private:
Здесь две строки. Обе строки выполняют одно и тоже, но по разному. Обе строки записывают в свой ТLabel левую позицию панели, по которой ты щёлкнул.
Первая строка, чтобы получить левую позицию панели использует CompList, а вторая работает с панелью напрямую. Рассмотрим сначала вторую строку. В ней основным является выражение "TPanel(Sender).Left". Sender - передаётся нам функцией PanelMouseDown. В нём записан указатель на объект, который сгенерировал событие OnMouseDown. В нашем случае это будет указатель на панель, по которой ты щёлкнул. Так как мы точно уверены, что это панель, то мы так и показываем TPanel(Sender). Этим мы приводим Sender к TPanel и теперь можешь использовать все свойства и методы панели, для примера нам достаточно свойства Left. Если бы мы знали точное имя панели, то этого писать не пришлось бы. Но это невозможно, потому что все панели у нас используют один обработчик нажатия мышкой. Получив значение левой позиции, мы переводим целое значение левой позиции в строку с помощью IntToStr.
Первоя строка очень похожа на вторую, только внутри TPanel() мы используем не Sender, а "CompList.Items[TPanel(Sender).Tag]", т.е. значение из конейнера. Чтобы получить первое значение из контейнера, нужно написать CompList.Items[0], для второго CompList.Items[1], для третьего CompList.Items[2] и т.д. Но по какой именно панели произведён щелчёк? Чтобы это узнать я пишу TPanel(Sender).Tag, то есть получаю свойство Tag (там хранятся индекс панели) панели сгенерировавшей событие. Далее, всё происходит так же.
Запусти пример и пощёлкай по форме. По каждому щелчку будут создаватся панели. Потом попробуй пощёлкать по самим панелям. На двух TLabel будут появляться значения левой позиции панель, по которым ты щёлкал.