Раньше никогда не было потребности, но вот сейчас понадобился такой прекрасный "режим" как Run-Time, тобишь создание компонентов/окон в уже запущенной программе. 1. Начнём с компонентов: Создаю я например компонент TEdit вот таким способом Code: [COLOR=YellowGreen]var[/COLOR] [COLOR=DarkOrange]x: TEdit;[/COLOR] [COLOR=YellowGreen]procedure TForm1.Button1Click(Sender: TObject); begin[/COLOR] [COLOR=DarkOrange]x := TEdit.Create(self); x.Parent := Form1; x.Left := 10; x.Top := 10;[/COLOR] [COLOR=YellowGreen]end;[/COLOR] Если много раз клацать на кнопку, то создаётся много текстовых полей (правда в данной примере они налаживаются друг на друга, то как координаты всегда будут (10; 10), но я проверял, заменив координаты переменными, которые при каждом нажатии увеличивал). И собственно от сюда вытекает вопрос: Какие имена присваиваются второму, третьему и т.д. полям, ведь я указал имя "x" ( var x: TEdit; ) то есть это имя первого поля, а остальные-то не могут быть названы так же Я думал, может x[номер поля], но ничего подобного. --------------------------------------------------------------------------------------------------------- С этим вопросом разобрался, вот ответ: Как положено - разобрался сам, помоги другим. Потому чуток пораскинув мозгами и почитав дополнительную литературу, пришел к выводу, что работать с компонентами не обязательно через массив. Можно сделать по такой схеме: 1. Создаём компонент. 2. Заносим в объект TList указатель на этот компонент. 3. Для обращения к любому из компонентов вытягиваем указатель из TList. Таким образом мы не ограничиваемся размером массива. Покажу на примере (кинем на форму не одну кнопку, а две. Одна будет создавать поля, а другая - поменяет текст в определенном поле): Code: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; a, y: integer; [COLOR=YellowGreen] ListComp: TList;[/COLOR] implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin [COLOR=YellowGreen]ListComp := TList.Create;[/COLOR] a := 10; y := 10; end; procedure TForm1.Button1Click(Sender: TObject); var x: TEdit; begin x := TEdit.Create(self); x.Parent := Form1; x.Top := y; x.Left := a; [COLOR=YellowGreen]ListComp.Add(x);[/COLOR] a := a + 20; y := y + 20; end; [COLOR=YellowGreen]procedure TForm1.Button2Click(Sender: TObject); begin TEdit(CompList.Items[2]).Text := 'lol'; //Эта строка меняет текст в третьем текстовом поле. Номер текстового поля указываем в CompList.Items[номер полня] (счет ведется с нуля). end;[/COLOR] end. Создаём первой кнопкой несколько полей (больше, чем 3) и клацаем вторую кнопку - меняется содержимое третьего поля. 2. Проблема с дочерними MDI окнами: 1. Создаю основную форму ( Form.Style := fsMDIForm ). 2. Создаю MDI форму ( From.Style := fsMDIChild ). 3. В Project - Options перекидываю MDIchild форму в раздел Available forms. 4. По идее на основной форме нужно создать кнопку с кодом: Code: [COLOR=DarkOrange]<имя дочерней формы> := TChildForm.Create(Owner);[/COLOR] Но надо как-то связать основную форму с MIDChild. Пробовал прописать в разделе uses модуль с MIDChild, но нихрена не дало --------------------------------------------------------------------------------------------------------- С этим вопросом тоже разобрался, вот ответ: Такс, с MDI окнами тоже разобрался. Создаём две формы - Form1, Form2. Form1.FormStyle := fsMDIForm; Form2.FormStyle := fsMDIChild; В Unit1, в разделе uses дописываем Unit2: uses ......, Unit2; На Form1 кидаем две кнопки (первая создаёт окна, вторая меняет заголовок определенного ока): Code: procedure TForm1.Button1Click(Sender: TObject); begin Form2 := TForm2.Create(Owner); end; procedure TForm1.Button2Click(Sender: TObject); begin Form1.MDIChildren[2].Caption := 'Woohoo'; [COLOR=YellowGreen]// Номер MDI окна указываем тут MDIChildren[/COLOR][номер окна] end;
Насчет первого вопроса - x это всего лишь название переменной а не компонента. Название компонента можно установить/прочитать так: x.Name Насчет второго не скажу, с MDI никогда не работал, ибо не нужно было Но убери создание, т.к. эта форма у тебя уже в avalable forms значит по идее создается автоматически. Просто "имя дочерней формы".Show или как там для mdi окон Сорри, ступил. Значит так, следующий код показал дочернее mdi окно у меня, при том что окно этой формы в avalaible forms: Form2 := TForm2.Create(self); Form2.Show; где TForm2 - класс вторичной формы и свойства выставлены как у тебя
Это немного не то. Например я таким образом создал 5 полей, как мне изменить свойство Text в 4-ом поле?! Ведь имя я указывал только одно - "х". Это показать лишь одно, а если мне надо создать штук 10 динамично на основе одного класса с одним именем, и получать к ним доступ через свойство MDIChildren[номер]? ---------------------------------------- Добавлено: В общем насколько я понял, в моём примере, runtime заключается в создании неограниченного количества однотипных объектов имеющих одно общее имя, обращение к которым происходит при помощи определенного свойства имеющего структуру массива.
Создавая поле, присваивай ему уникальное имя Name и обращайся к нему по имени procedure TForm1.Button2Click(Sender: TObject); var x : TEdit; begin x := TEdit.Create(self); x.Name := 'Edit1'; x.Parent := self; end; procedure TForm1.Button3Click(Sender: TObject); begin TEdit(FindComponent('Edit1')).Text := 'I''ve found you!'; end; Еще раз повторяю: х - название переменной, а не компонента
Но ведь ты же обращаешься к компоненту именно через имя этой переменной. Я не полный баран в делфи, да и программирую не первый год, просто никогда не работал с runtime.
Если так, то почему не заюзаешь обычный массив? Edits : array of TEdit Я то подумал у тебя нестандартная задача, и предложил нестандартное решение ПС я программирую меньше года
Как написано в книге (которую именно сейчас я держу в руках и листаю), создается неограниченное количество МДИ окон с одним именем, а потом обращение к ним происходит через свойство MDIChildren[номер окна]
В случае с компонентами так и делают - создают массив, но мне интересно, делфи шпарит до посинения при нажатии на кнопку текстовые поля, какие тогда у них имена, как к ним обращаться? С массивом всегда успею сделать
Все это делается через обычные динамические массивы Блин.. есть переменная например edit делая так edit := TEdit.Create(self); ты создаешь компонент и эта переменная указыват на этот компонент. Если ты повторишь эту процедуру - создашь новый компонент и эта переменная будет указывать уже на новый, а старый "потеряется". Откуда дельфе знать, может тебе надоело это поле и ты решил его выкинуть? А вот Name - уникальное, дельфи не даст тебе создать 2 компонента с одним именем. Так что если не хочешь использовать массивы - делай через Name как я тебе написал. Все, вопросов после этого остаться не должно я думаю.
Вот тут-то ты и не прав. Кинь на форму один button: Code: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; a, y: integer; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin a := 10; y := 10; end; procedure TForm1.Button1Click(Sender: TObject); var x: TEdit; begin x := TEdit.Create(self); x.Parent := Form1; x.Top := y; x.Left := a; a := a + 20; y := y + 20; end; end. И клацни раз 5 на кнопку...И ты увидишь 5 текстовых полей, а не 1, которое удаляет предыдущее и пересоздается.
Ты тролль? Где я написал что старый компонент удалится? Потеряется ссылка на него! А конкретнее х будет указывать уже на новый компонент, а к старому ты никак не сможешь обратится, только по имени Почитай про модель объектных ссылок в дельфи
Как положено - разобрался сам, помоги другим. Потому чуток пораскинув мозгами и почитав дополнительную литературу, пришел к выводу, что работать с компонентами не обязательно через массив. Можно сделать по такой схеме: 1. Создаём компонент. 2. Заносим в объект TList указатель на этот компонент. 3. Для обращения к любому из компонентов вытягиваем указатель из TList. Таким образом мы не ограничиваемся размером массива. Покажу на примере чуть выше (кинем на форму не одну кнопку, а две. Одна будет создавать поля, а другая - поменяет текст в определенном поле): Code: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; a, y: integer; [COLOR=YellowGreen] ListComp: TList;[/COLOR] implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin [COLOR=YellowGreen]ListComp := TList.Create;[/COLOR] a := 10; y := 10; end; procedure TForm1.Button1Click(Sender: TObject); var x: TEdit; begin x := TEdit.Create(self); x.Parent := Form1; x.Top := y; x.Left := a; [COLOR=YellowGreen]ListComp.Add(x);[/COLOR] a := a + 20; y := y + 20; end; [COLOR=YellowGreen]procedure TForm1.Button2Click(Sender: TObject); begin TEdit(CompList.Items[2]).Text := 'lol'; //Эта строка меняет текст в третьем текстовом поле. Номер текстового поля указываем в CompList.Items[номер полня] (счет ведется с нуля). end;[/COLOR] end. Создаём первой кнопкой несколько полей (больше, чем 3) и клацаем вторую кнопку - меняется содержимое третьего поля.
Такс, с MDI окнами тоже разобрался. Создаём две формы - Form1, Form2. Form1.FormStyle := fsMDIForm; Form2.FormStyle := fsMDIChild; В Unit1, в разделе uses дописываем Unit2: uses ......, Unit2; На Form1 кидаем две кнопки (первая создаёт окна, вторая меняет заголовок определенного ока): Code: procedure TForm1.Button1Click(Sender: TObject); begin Form2 := TForm2.Create(Owner); end; procedure TForm1.Button2Click(Sender: TObject); begin Form1.MDIChildren[2].Caption := 'Woohoo'; [COLOR=YellowGreen]// Номер MDI окна указываем тут MDIChildren[/COLOR][номер окна] end; Обновил первый пост. Тему можно закрывать.