Компоненты Delphi

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




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




 Это важно:
   Метод 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
   Ребята, не забывайте присваивать (ассоциировать в Инспекторе Объектов) своим кнопкам предлагаемые здесь процедуры. А то потом в комментариях и появляются возгласы: "ничего не работает!"

   Есть ещё свойство Name! По умолчанию Delphi присвоит ему типовое имя с присвоением очередного порядкового номера: Memo1. Программист при создании компонента также может присвоить свойству Name нужное значение, например:

  Memo.Name:='DynamicallyCreatedMemo';

  К данному компоненту можно обращаться как по этому имени, так и с указанием переменной, с помощью которой он был создан: 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 его восстановит в том минимальном виде, который нужен для функционирования компонентов.

   Поэтому естественно, что мы получили ошибку в предыдущем варианте - не хватало нужных модулей. Теперь смело жмите 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);

   И это относится не только к динамически созданному - к любому компоненту и объекту в памяти.



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


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




Вопросы и комментарии (64)      Решение задач в Delphi

Андрей, добавлено 17.01.12, 02:19:46 
Большое спасибо за информацию - очень помогла мне при написании моей программы!
Николай, добавлено 20.01.12, 20:13:40 
Хорошая статья для новичка!
вика, добавлено 20.01.12, 23:58:25 
отлично!
Оля, добавлено 4.02.12, 15:38:12 
Здравствуйте, у меня вопрос, как сделать матрицу из компонентов Edit, причем количество строк и столбцов задается вручную.. Я смогла вывести определенное количество Edit-ов в строку, а вот при переходе на 2,3,4-ю строчку я застопорилась, не могу сообразить как это сделать, мой код выглядит так: А - это количество столбцов..
 
var
  Form4: TForm4;
  edit : TEdit;
  n : integer =0;
  n1: Integer =3;

implementation

uses Unit1;

{$R *.dfm}

procedure TForm4.Image3Click(Sender: TObject);
var i:Integer;
  a:Integer;
begin
  Label3.Visible:=True;
  A:=StrToInt(Edit1.text);
  for i := 1 to a do
  begin
  edit := TEdit.Create(Form4);
  edit.Parent := self;
  edit.Name := 'Edit' + IntToStr(n1);
  edit.Left := 90+n;
  edit.Top := 150;
  edit.Height:=33;
  edit.Width:=45;
  edit.Text:='0';
  n := n +90;
  Inc(n1);
  End;
End.

Автор, добавлено 4.02.12, 16:58:33 
Вы создаёте несколько компонентов: Edit1, Edit2 и так далее. Если вы хотите, чтобы эти компоненты были выстроены в несколько строк, то нужно два вложенных цикла. Добавьте перед вашим ещё один:

B:=StrToInt(Edit2.text);
for j:=0 to B-1 do

и в цикле измените

edit.Top := 150+j*50;// 50 - расстояние между строками (выберите сами)
Оля, добавлено 4.02.12, 17:45:19 
Спасибо большое.. вот бывает же, вроде тоже самое делала) только в одном месте ошиблась) в месте Edit.Top . Огромное спасибо)
Оля, добавлено 4.02.12, 18:17:29 
Можно вас еще немного побеспокоить.. когда пишешь edit.Top := 150+j*50; он edit лесенкой строит, а не друг под другом..
Автор, добавлено 4.02.12, 18:42:29 
А это потому что у вас Left привязан не к переменной цикла, а к какой-то n. Замените
Edit.Left:=90*i;

n вообще не нужен, уберите его.
Оля, добавлено 4.02.12, 18:49:17 
Я его писала для того чтобы он расстояние друг от друга делал, а не лепил их вместе.. а когда ставишь i, то получается что он их друг на друга накладывает
Автор, добавлено 4.02.12, 19:11:54 
Ничего подобного. Отписались, и даже наверное не попробовали:

procedure TForm1.Button1Click(Sender: TObject);
var i, j:Integer;
  a, b:Integer;
begin
  Label3.Visible:=True;
  A:=5{StrToInt(Edit1.text)};
  B:=3;
  for j := 0 to b-1 do
  for i := 1 to a do
  begin
  edit := TEdit.Create(Form1);
  edit.Parent := self;
  edit.Name := 'Edit' + IntToStr(n1);
  edit.Left := 90*i{+n};
  edit.Top := 150+j*50;;
  edit.Height:=33;
  edit.Width:=45;
  edit.Text:='0';
// n := n +90;
  Inc(n1);
  End;
end;

Это обработчик нажатия на кнопку, ну да какая разница. n не используется.
Оля, добавлено 4.02.12, 19:34:27 
То что пробовала это правда, но не могу понять, вроде проверила все тоже самое что и у Вас было. Не поняла в чем разница, скопировала Ваш текст, работает.. Извините за беспокойство, спасибо за помощь!
Игорь, добавлено 18.03.12, 02:02:45 
Спасибо за хорошую статью. У меня вопрос. Как уничтожить визуальный компонент, так чтобы он исчез с формы?
Автор, добавлено 18.03.12, 07:12:07 

Component.Free;

Надо бы добавить в текст статьи. Спасибо!
Аноним, добавлено 5.04.12, 08:45:00 
Добрый день. Нужна помощь в следующей ситуации.
На Form1 в процессе проектирования создаетя Edit1 и Edit2. Далее по нажатию кнопки динамически создаются Edit3, Edit4 и т.д.


Procedure TForm1.Button1Click (Sender: TObject);
var Edit: TEdit;
begin
  Edit:=TEdit.Create(Form1);
  Edit.Parent:=Form1;
  Button1.Top:=Button1.Top+40;
  Edit.left:=50;
  Edit.top:=Button1.Top-40;
  Edit.Width:=200;
  Edit.Height:=25;
  k:=k+1; {k:integer; k:=2 задается ранее}
  Edit.text:='Игрок'+IntToStr(k);
end;

После в Form2:

StringGrid1.Cells[1,0]:=Form1.Edit1.Text;
StringGrid1.Cells[2,0]:=Form1.Edit2.Text;

Подскажите, пожалуйста, как задать другим ячейкам содержание Text динамически созданных Edit3, Edit4,... из Form1?
Автор, добавлено 5.04.12, 09:03:42 
Не вижу разницы с первыми эдитами. Имена им присваиваются Delphi по умолчанию порядковые: Edit3, 4, 5 и т.д. причём у вас этот номер равен k.

Но вам, кстати, вообще не нужно содержание этих едитов, т.к. оно заранее задано: Игрок3, 4, 5 и т.д. (если я правильно понял). Можно просто:

Stringgrid1.Cells[k, 0]:='Игрок'+IntToStr(k);

Но я в таких случаях создаю не отдиночный Edit, а глобальный динамический массив типа TEdit:

var Edit: Array of TEdit;

k:=k+1;
SetLength(Edit, k-2);
Edit[k-1]:=TEdit.Create(Form1);//т.к. динамический массив адресуется с нуля

И так далее. Теперь просто получить доступ к любому Edit'у: его номер будет k-3.
Аноним, добавлено 5.04.12, 10:46:38 
Дело в том, что содержание этих динамически созданных эдитов нужно, т.к. изначальное их содержание это имена игроков по умолчанию, которые в процессе работы первой формы пользователь изменяет (может изменить). При этом пользователь и задает колличество игроков (к), минимум может учавствовать 2 игрока (по этому 1й и 2й эдиты созданы статически), дополнительные игроки добавляются по необходимости нажатием кнопки Button1. Затем окно "обзывания игроков" закрывается и появляется окно Form2.
Проблема в том, что когда я присваиваю ячейкам СтрингГрид второй формы содержание эдитов с первой формы, первые два присваиваются без проблем, а остальные не знаю как. Пытаясь присвоить так же как и первые два, компилятор выдает ошибку. Может их (динамические эдиты 3й 4й и т.д.) надо как-то описать в Unit2?
Автор, добавлено 5.04.12, 10:57:53 
Ну я же написал: создавайте динамический массив эдитов, их адресация будет Edit[k-3]
Дмитрий, добавлено 11.04.12, 09:36:43 
Зачетно, как раз это и искал. Спасибо
Автор, добавлено 11.04.12, 09:57:56 
Да, читаю и самому нравится!
Вадим Мошев, добавлено 13.04.12, 14:25:26 
Хочется внести небольшое предложение по поводу вот чего. СмотрИте, у вас написано "Так вот что нужно делать, чтобы подобная ошибка не появлялась. Просто положите на Форму из палитры компонентов компонент, который вы создаёте динамически, и жмите Run. Всё, после компиляции компонент можно удалять за ненадобностью - модуль, необходимый для его работы, Delphi затирать не станет! И ваш динамически создаваемый компонент будет работать.".

Зачем так извращаться? Ведь можно просто навести указатель мыши на нужный компонент из палитры компонентов, рядом с названием в скобочках появится название модуля, например, Memo (StdCtrls). [могу ошибаться, конечно, но в Delphi 7 так и есть].

Автор, добавлено 13.04.12, 14:45:28 

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

Но ваше предложение означает, что что-то нужно будет написать ручками, отсюда появляется возможность ошибки. А так эта возможность исключена. Всё же сайт для новичков.

В общем, сделаем так: выбор будет за читателем.
Вадим Мошев, добавлено 14.04.12, 12:06:31 
Кстати, Андрей, извините за тон предыдущего сообщения, я не хотел вас обидеть...
Автор, добавлено 14.04.12, 12:22:11 
Без проблем! За окном хорошая погода - это важнее :)
Андрей, добавлено 14.04.12, 13:55:47 
У меня вопрос: я создаю игру сапера на делфи и такая проблема у меня при создании динамических кнопок они появлются в верхнем углу формы а мне нужно их перенести на центр как это сделать?Вот код:

procedure TForm1.FormCreate(Sender: TObject);
var
  ButtonCreName : String;
  i, j,k : Integer;
  VarLeft, VarTop : Integer;
  MasButton: array[1..15,1..15] of TButton;
begin
  i := 0;
  j := 1;
  k:=0;
  VarLeft := 15;
  VarTop := 15;
  for i:=1 to 15 do
  for j:=1 to 15 do begin
  inc(k);
  ButtonCreName := 'Button_' + IntToStr(k);
  MasButton[i, j] := TButton.Create(Self);
  With MasButton[i, j] do begin
  Parent := Form1;
  Caption := 'O';
  Left := VarLeft*i;
  Top := VarTop * j;
  Width := 15;
  Height := 15;
  Visible := True;
  Name:=ButtonCreName;
  end;
  end;
  end;
procedure TForm1.Button2Click(Sender: TObject);
var
  ButtonCreName : String;
  i, j,k : Integer;
  VarLeft, VarTop : Integer;
  MasButton: array[1..15,1..15] of TButton;
begin
  i := 0;
  j := 1;
  k:=0;
  VarLeft := 15;
  VarTop := 15;
  for i:=1 to 15 do
  for j:=1 to 15 do begin
  inc(k);
  ButtonCreName := 'Button_' + IntToStr(k);
  MasButton[i, j] := TButton.Create(Self);
  With MasButton[i, j] do begin
  Parent := Form1;
  Caption := 'O';
  Left := VarLeft*i;
  Top := VarTop * j;
  Width := 15;
  Height := 15;
  Visible := True;
  Name:=ButtonCreName;
  end;
  end;
  end;

Автор, добавлено 14.04.12, 14:19:31 
Введите переменные Xo и Yo и прибавляйте к кординатам кнопок:

  With MasButton[i, j] do begin

  Left := VarLeft*i+Xo;
  Top := VarTop * j+Yo;

Значения подберите экспериментально или вычислите...

Аноним, добавлено 14.04.12, 14:36:53 
спасибо сечас попробую
Виталий, добавлено 14.10.12, 20:02:19 
Ошибка при нажатии на кнопку: A component named Button1 already exists
Автор, добавлено 14.10.12, 23:23:00 
Утром вернусь, проверю что у вас не так, тогда отвечу.
Автор, добавлено 15.10.12, 09:04:55 
Всё ясно. У вас на Форме уже есть компонент с именем Button1, и другой компонент с таким же именем вы динамически создать не сможете.
Иван, добавлено 14.04.13, 10:28:37 
Я создаю тест на Delphi (для проверки знаний), читается вопрос из файла, читаются варианты ответа и в зависимости от их количества динамически создаются компоненты memo и заносятся в динамический массив. При нажатии кнопки идет проверка ответов и компоненты удаляются. Проблема в том, что в какой-то момент они перестают удаляться и остаются на форме.
Автор, добавлено 14.04.13, 15:36:05 
Как удаляете? Можно ведь удалять как компоненты Формы, а можно как переменные...
Ямиль, добавлено 15.04.13, 05:45:56 
Огромное спасибо !!!!!!
иван, добавлено 15.04.13, 10:08:11 
как компонент, храниться в массиве компонентов
Автор, добавлено 15.04.13, 10:56:51 
Опубликуйте ваши процедуры создания и удаления, посмотрим. А так не угадаешь.

Иван, добавлено 15.04.13, 15:03:22 
Вот они:
//********************************************************
//Процедура удаления компонентов
//********************************************************
procedure Tstudent.BitBtn3Click(Sender: TObject);
var
  i:Integer;
begin
 
 
  for i:=0 to Length(checks)-1 do
  checks[i].free;// checks - Глобальный массив типа Tcheckbox (динамический)
  checks:=nil;


  for i:=0 to Length(mems)-1 do
  mems[i].free;//mems - Глобальный массив типа Tmemo (динамический)
  mems:=nil;

  test; //вызов процедуры для создания новых компонентов

end;

//********************************************
//Создание мемо и занеесение их в массив
//Создание чекбоксов и занесение их в массив
//********************************************
Procedure tstudent.testcreate;
var
 memo:Tmemo;
 check:Tcheckbox;
 s:string;
 i,k,left:integer;
begin
  k:=0;
  setlength(mems,1);//Расширяем массивы на еденицу
  setlength(checks,1);//****************************
  memo:=Tmemo.create(self);//Создаем компоненты и заносим их в массивы
  memo.Parent:=groupbox2;//
  memo.Hide;//
  mems[k]:=memo;//
  check:=Tcheckbox.Create(self);//
  check.Parent:=groupbox2;//
  check.Hide;//
  checks[k]:=check;//*************************************
  tabbedNotebook1.PageIndex:=2;
  for i:=1 to length(quest.Answer) do//Извлечение текста и запись его в нужный memo
  begin
  if quest.Answer[i]<>'%' then
  if quest.Answer[i]<>'|' then
  s:=s+quest.answer[i]
  else
  begin
  mems[k].Lines.Add(s);
  s:='';
  end
  else
  begin
  inc(k);
  setlength(mems,length(mems)+1);
  setlength(checks,length(checks)+1);
  memo:=Tmemo.Create(groupbox2);
  memo.Parent:=groupbox2;
  memo.Hide;
  mems[k]:=memo;
  check:=Tcheckbox.Create(groupbox2);
  check.Parent:=groupbox2;
  check.Hide;
  checks[k]:=check;
  end;//***************************************************************************
  end;
  k:=0;//Дальше идет просто размещение в нужных местах
  left:=50;
  for i:=0 to length(mems) - 2 do
  begin
  if (i = 8) or (i=16) then
  k:=0;
  if (i>=8) and (i<17) then
  left:=300;
  if i>17 then
  left:=500;
  mems[i].Left:=left;
  mems[i].Height:=45;
  mems[i].top:=k*45+15;
  mems[i].Show;
  checks[i].Top:=k*45+15;
  checks[i].Width:=15;
  checks[i].Left:=left-25;
  checks[i].Show;
  inc(k);
  end;//***************************************************
end;
Иван, добавлено 15.04.13, 15:54:55 
При пошаговом выполнении видно как удаляются checkbox-ы, обнуляется массив все хорошо, при переходе на следующую строчку все checkbox-ы появляются

Алексей, добавлено 3.08.13, 14:45:54 
Уважаемый Автор, подскажите можно ли назначить динамически созданному RichEdit[x] событие OnResizeRequest, для обычно созданного RichEdit1 в событии OnResizeRequest(Sender: TObject; Rect:TRect), Rect-размеры поля RichEdit1
Автор, добавлено 3.08.13, 15:05:18 
Можно, а в чём проблема, что не получается? Для динамически созданного Reсt будет его поле...
Алексей, добавлено 6.08.13, 00:55:14 
Все получилось, спасибо, не внимательно прочитал выше изложенный текст, сделал как вы написали: создал RichEdit2, назначил ему событие OnResizeRequest2, и удалил RichEdit2, а его событие назначил динамически создаваемым RichEdit[x], просто до этого я делал так: RichEdit[x].OnResizeRequest:=Res(); и описывал в Privat procedure Res(Sender: TObject; Rect:TRect); это вызывает ошибку наверное т.к. в Res() я не передаю парамерт Rect... я так понял мой вариант работает только когда на событие назначается процедура в которую передается один параметр Sender, напр OnClick.
Алексей, добавлено 6.08.13, 01:46:57 
Уважаемый Автор, прошу помощи, пишу проект для себя, такого плана: ресторанное меню в нем два поля (и панель управления) слева меню в виде дерева, справа (при выборе слева) открывается содержание блюда в котором и текст и картинки и желательно видео ролики, работает меню в режиме просмот и редактирования (для администратора), задача моя такая: надо чтобы всё меню хранилось в одном файле, и все блоки (блюда) файла были доступны для просмотра редактирования, перезаписи.
Такой вопрос: какие компаненты использовать?
Для вывода содержания меню наверное TTreeView или TListView,
самое трудное для просмотра/редактирования блюда, как я вижу содержание блюда должно быть похоже на веб страницу, пролистываешь ее вверх вних, читаешь и смотришь картинки и видео, пришел администратор нажал редактирование ввел пароль и можно изменять текст, загружать другие картинки и видео и соответственно перезаписать это блюдо, какой сюда компанент для просмотра/редактирования содержания блюда TRichEdit в который вставлять фото и видео или собирать из нескольких компанентов TRichEdit,TImage или TWebBrowser.
Все это не по теме!
Если можете помогите в каком направлении копать, заранее спасибо.
Андрей, добавлено 7.11.13, 11:56:31 
Как мне сохранить динамичиске создан объект на форме чтобы использовать его в следующий запуск программы ?
Автор, добавлено 7.11.13, 12:05:23 
Динамически созданный объект он на то и динамически созданный, чтобы не сохраняться, а каждый раз создаваться заново. Иначе используйте обычный объект, из палитры компонентов.

Возможно, я вас не совсем понял. В таком случае, приведите пример того, что вы имеете в виду.
Андрей, добавлено 7.11.13, 13:52:01 
Мне нужно чтобь при выполнении программы создавался объект и сохранялся при закрытии программы ,чтобы можно было его использовать постоянно.
Типа мне нужно добавить Label ,а текст и место положение задавать при выполнении программы , но чтобь когда програма закончится он был там где создавалса
Андрей, добавлено 7.11.13, 13:54:00 
Когда я открою заново програму Лейбел был там где его создали при прошлом выполнении программы
Автор, добавлено 7.11.13, 14:08:37 
Параметры программы, в том числе расположение компонентов, значение переменных, текст и другие вещи нужно при закрытии сохранять в файл, а при последующем открытии считывать этот файл, и присваивать переменным эти значения. Для чего, вы думаете, существуют файлы типа *.ini? Ну да тип файла неважен. Структура файла это запись типа

Tini = Record
  Left, Top: Integer;
  Caption: String[100];//100 - максимальная длина текста в Label
end;


Создаём глобальные переменную и файловую переменную:

var
  Ini: Tini;
  Fini: File of Tini;

При закрытии программы (обработчик OnClose) пишем:

begin
ini.Left:=Label.Left;
ini.Top:=Label.Top;
ini.Caption:=Label.Caption;
AssignFile(Fini, 'label.ini');
Rewrite(Fini, ini);
end;

А при открытии программы в обработчике OnCreate Формы пишем:

begin
//создаём Label:
Label:=TLabel.Create(Form1);
Label.Parent:=Form1;
//считываем файл (вначале проверив на его существование):
if FileExists('label.ini') then
  begin
  AssignFile(Fini, 'label.ini');
  Reset(Fini);
  Read(Fini, ini);
//присваиваем значения:
  Label.Left:=ini.Left;
  Label.Top:=ini.Top;
  Label.Caption:=ini.Caption;
  end;
end;


Андрей, добавлено 7.11.13, 14:24:09 
Я так и думал просто не знал как ето сделать . Большое Спасибо !!!!

Автор, добавлено 7.11.13, 14:39:41 
Пожалуйста. Но я тут подумал, что создавать Label нужно не сразу, а перед if FileExists('label.ini') then . А сохранять параметры не при закрытии программы, а в той процедуре, где эти значения присваиваются созданной Label, иначе при каждом закрытии программы файл будет пересоздаваться, а если параметры больше не меняются, то какой смысл...
Андрей , добавлено 7.11.13, 14:46:43 
О спасибо и за ето )
Автор, добавлено 7.11.13, 14:53:18 
А-а-а, блин, не перед FileExists а после. То есть если файл существует, то нужно создать Label, а если не существует, то вся эта конструкция пропускается.
Александр, добавлено 2.12.13, 18:19:34 
Помогите создать динамический объект из dll при нажатии на кнопку
Автор, добавлено 2.12.13, 20:52:01 
А какие самостоятельные результаты? В смысле, сам пробовал? Что не выходит?
Святослав, добавлено 5.01.14, 21:33:04 
Как сделать, чтобы созданные объекты оставались и при следующем заходе в программу
Святослав, добавлено 5.01.14, 21:35:06 
Как сделать, чтобы созданные объекты оставались и при следующем заходе в программу
Автор, добавлено 5.01.14, 23:39:03 
Никак. Но соответствующего эффекта добиться можно. Нужно сохранять в файл перечень объектов которые должны быть созданы, при старте программы считывать этот файл, и пересоздавать их заново. Конечно, объём сохраняемой информации большой, но иначе нельзя.
Александр, добавлено 9.01.14, 01:50:48 
Автор, а можно динамически созданной кнопки применить событие открывание вот так:
button[n].OnClick:=Button1Click(n);
?
Александр, добавлено 9.01.14, 01:53:40 
Автор, а можно динамически созданной кнопки применить событие открывания вот так:
button[n].OnClick:=closepanel(n);
?
P.S. "closepanel(n:byte)" это уже созданная процедура
Автор, добавлено 9.01.14, 06:04:48 
Нет, так нельзя, потому что не совпадают параметры. В процедуре OnClick используется параметр Sender. Но можно создать для OnClick стандартную процедуру, в которой будет вызываться ваша процедура.
Антон, добавлено 2.02.14, 16:39:12 
Здравствуйте. При написании программы столкнулся со следующей проблемой:
При открытии формы на ней динамически в цикле создаются несколько компонентов Memo, рядом с каждым из них - кнопки Button.
Кнопки необходимы для удаления соответствующих им Memo.
Но сам механизм удаления реализовать немогу. Не знаю даже как подступиться.
Ведь если я буду по событию OnClick вызывать процедуру Component.Free удалится последний созданный Memo, а не соответствующий нажатой кнопке.
Как же объяснить программе, какой Memo надо удалять?
Заранее спасибо.
Автор, добавлено 2.02.14, 17:27:06 
А почитайте про параметр Sender! Страница так и называется: sender.php
Но при создании нужно каждой паре Memo-кнопка присваивать свой уникальный параметр Tag. По нему и определим что удалять. Можно, конечно, непосредственно имя компонента определять - без разницы, но по Tag удобнее. У вас, возможно, компоненты создаются как элементы массива (я бы так делал). Вот и присваивайте индекс параметру Tag. Потом смотрите (Sender as TButton).Tag - это будет индекс элемента массива, и удаляете этот элемент.
Антон, добавлено 2.02.14, 18:00:47 
Большущее, вам спасибо. И за Sender и за идею с массивом, как-то раньше до этого не додумался.
Святослав, добавлено 16.02.14, 19:38:27 
Здравствуйте! А как можно сохранить в ini файл неизвестное количество динамически созданных объектов(объекты однотипны TEdit)
Автор, добавлено 16.02.14, 22:08:28 
Точно также как и один, просто неизвестно сколько раз.
Макс, добавлено 21.02.14, 22:17:42 
можете подсказать, как создать массив из пяти объектов label, расположенных друг под другом, при нажатии кнопки. Как именно создать и объявить этот массив
Автор, добавлено 21.02.14, 22:34:16 
Обычный массив:

var LabArray: Array[1..5] of TLabel;

procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
 Xo, Yo, Sdvig: Integer;
begin
Xo:=10;
Yo:=10;
Sdvig:=20;
for i:=1 to High(LabArray) do
  begin
  LabArray[i]:=TLabel.Create(Form1);
  LabArray[i].Parent:=Form1;
//Далее задаём координаты
  LabArray[i].Left:=Xo;
  LabArray[i].Top:=Yo+(i-1)*Sdvig;
  end;
end;

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

Имя  

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