![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Копирование форм [D7, WinXP]
den303_work © (2007-10-08 09:02:00)Доброго всем времени!
Как можно наиболее быстро в рантайм создать форму на основе уже существующей, включая все контролы? Короче, создать полный клон формы.
Пока не придумал ничего лучше, чем пробегаться по списку элементов source-формы и создавать эти элементы на дочерней, но важна скорость создания...
Заранее спасибо :o)
korneley (2007-10-08 13:47:00) [1]Не знаю, может я неправильно понял условия задачи... У меня были ситуации, когда нужно иметь несколько экземпляров одной и той же формы. Со всеми контролами. Делал просто: в дизайн-тайме рисовал, убирал переменную из модуля и автосоздание из проекта. Когда надо - создавал обычным TForm1.Create(), (ну или как там класс назывался) с сохранением ссылки, стало не надо - Free. Всё работало, а может просто повезло :)
den303_work (2007-10-08 11:28:00) [2]
> Slym © (08.10.07 11:10) [12]
Великолепно работает, спасибо большое. Помогла предварительная регистрация классов. Весь код создания экземпляра класса (привожу "потомкам в пример", мож кому понадобится):
var
Stream: TMemoryStream;
begin
FM:=(FindControl(COMHandle) as TMkF_Form); {поиск исходной формы по хэндлу}
RegisterClasses([TLabel]); {регистрация классов}
RegisterClasses([TImage]);
RegisterClasses([TBitBtn]);
Stream:=TMemoryStream.Create;
Stream.WriteComponent(FM);
FMC:=TMkF_Form.CreateNew(Application); {Создание экземпляра формы}
Stream.Position:=0;
Stream.ReadComponent(FMC);
Stream.Free;
FMC.Show;
Сергей М. (2007-10-08 11:23:00) [3]
> надо перед ReadComponent объекты создавать?
Не надо. Файлер сам создаст необходимые компоненты на форме-клоне, лишь бы перед записью формы в поток записываемые компоненты имели owner'ом записываемую форму.
Slym (2007-10-08 11:10:00) [4]FMC:=TMkF_Form.CreateNew(Application);
Stream.Position:=0;
Stream.ReadComponent(FMC);
den303_work (2007-10-08 10:59:00) [5]
> Плохиш © (08.10.07 10:45) [10]
Форма фотоидентификации. Предприятие огромно, в каждый момент времени может сотня людей одновременно пройти. Все формы надо вывести не столько для пользователей, сколько по ТЗ :o) Тем более, что этими формами управляет сервер, а не пользователь.
> Slym © (08.10.07 10:29) [9]
Пытался делать так:
FM:=(FindControl(COMHandle) as TMkF_Form);
Stream:=TMemoryStream.Create;
MkF_Form:=TMkF_Form.Create(nil);
Stream.WriteComponent(FM);
FMC:=TMkF_Form.Create(Application);
Stream.Position:=0;
Stream.ReadComponent(FMC);
В принципе, подходит, но ошибка есть. Что, надо перед ReadComponent объекты создавать?
Плохиш (2007-10-08 10:45:00) [6]
> den303_work © (08.10.07 10:25) [8]
>
> > KSergey © (08.10.07 10:16) [7]
>
> В том то и дело, что этих экземпляров может быть сколько
> угодно. Такая вот своеобразная задача :o)
> Посему заранее не могу создать нужное количество. Приходится
> клонировать.
Одновременнодолжны быть показаны идентичныеформы в бесконечном количестве? Странная задача и бедные пользователи...
Slym (2007-10-08 10:29:00) [7]http://www.delphimaster.ru/cgi-bin/forum.pl?id=1189078540&n=0
den303_work (2007-10-08 10:25:00) [8]
> KSergey © (08.10.07 10:16) [7]
В том то и дело, что этих экземпляров может быть сколько угодно. Такая вот своеобразная задача :o)
Посему заранее не могу создать нужное количество. Приходится клонировать.
Сейчас код такой:
var
i:integer;
l,pl:TLabel;
img,imgc:TImage;
bt,btc:TBitBtn;
obj,objc:TControl;
begin
FM:=(FindControl(COMHandle) as TMkF_Form);
FMC:=TMkF_Form.Create(Application);
with FMC do begin
Height:=FM.Height;
Width:=FM.Width;
{..}
end;
for i:=0 to FM.ControlCount-1 do begin
objc:=FM.Controls[i];
if FM.Controls[i].ClassName='TLabel' then begin
pl:=FM.Controls[i] as TLabel;
l:=TLabel.Create(FMC);
l.Font:=pl.Font;
{..}
obj:=l;
end
else
if FM.Controls[i].ClassName='TImage' then begin
imgc:=FM.Controls[i] as TImage;
img:=TImage.Create(FMC);
img.Transparent:=imgc.Transparent;
{..}
obj:=img;
end
else
if FM.Controls[i].ClassName='TBitBtn' then begin
btc:=FM.Controls[i] as TBitBtn;
bt:=TBitBtn.Create(FMC);
{..}
obj:=bt;
end;
obj.Parent:=FMC;
obj.Top:=objc.Top;
{..}
end;
FMC.Show;
end;
В принципе, по времени укладываюсь, всеь спектр задачи охватываю. Но код ужасен и неоптимален ни разу вообще :o)
KSergey (2007-10-08 10:16:00) [9]> den303_work © (08.10.07 10:03) [6]
> Вид формы и её элементов тянется из xml. Это
> доооолго :o(
> Пошёл сл. путём: при запуске приложения я создаю эту форму,
> а при запросе нужно создать её экземпляр и вывести на экран.
Вот это я не понял: а зачем создавать еще один экземпляр? А если все же надо 2 экземпляра - так может при чтении xml сразу создавать 2 экземпляра? Или 3 (да хоть 10!) А потом просто отобразить нужный, быть может лишь проставив значения необходимым свойствам.
Я все же не понимаю зачем нужно именно копировать на лету имеющийся экземпляр формы.
den303_work (2007-10-08 10:03:00) [10]
> KSergey © (08.10.07 09:53) [4]
Трабла такая: в приложении при определённом событии нужно очень быстро создать и вывести на экран некую форму (макс. 50 мсек.). Вид формы и её элементов тянется из xml. Это доооолго :o(
Пошёл сл. путём: при запуске приложения я создаю эту форму, а при запросе нужно создать её экземпляр и вывести на экран. Получается много быстрее, но я не знаю, как оптимально создать экземпляр формы со всеми элементами и их параметрами.
Извиняюсь за сумбур :o)
ЗЫ:У меня есть хэндл окна source-формы, я знаю её тип (TForm, к примеру).
Сейчас тестовый пример выглядит так:
FM:=(FindControl(COMHandle) as TMkF_Form);
FMC:=TMkF_Form.Create(Application);
with FMC do begin
Height:=FM.Height;
Width:=FM.Width;
{...}
end;
for i:=0 to FM.ControlCount-1 do
if FM.Controls[i].ClassName='TLabel' then begin
pl:=FM.Controls[i] as TLabel;
l:=TLabel.Create(FMC);
l.Parent:=FMC;
l.Caption:=pl.Caption;
{...}
end;
FMC.Show;
Ужасно :o(
KSergey (2007-10-08 09:56:00) [11]В дополнение к предыдущему: ну и чтобы отобразилась все же форма (немодально) - тогда так
with TForm1.Create(Application) do
Show;
KSergey (2007-10-08 09:53:00) [12]> den303_work © (08.10.07 09:48) [3]
> Да, именно экземпляр формы. Но со всеми контролами.
> Либо КАК создать экземпляр формы?
А как создаешь первую?
Вообще, любое кол-во экземпляров форм можно создать простым
TForm1.Create(Application);
например.
Единственное - все создавться со значениями по умолчанию (текст в EdixBox'ах, например, размер и положение формы), но по вопросу не понятно надо ли это копировать. Если надо - то проще всего скопировать нужные свойства в уже созданную форму.
den303_work (2007-10-08 09:48:00) [13]
> clickmaker © (08.10.07 09:37) [1]
Да, именно экземпляр формы. Но со всеми контролами.
Сейчас приходится пробегать по всем контролам на source-форме и создавать такие же с такими же параметрами на новой форме. Очень неэффективно. Есть ли что нибудь типа наследования или assign, чтобы менее затратно решить данную проблему?
Либо КАК создать экземпляр формы?
> Сергей М. © (08.10.07 09:38) [2]
Для построения каждого контрола приходится проверять его класс. Ужасно неоптимально.
Сергей М. (2007-10-08 09:38:00) [14]
> важна скорость создания
Без цикла в том или ином виде все равно не обойтись.
Другой вопрос - насколько оптимально и эффективно у тебя тело цикла ..
clickmaker (2007-10-08 09:37:00) [15]не понял вопроса... просто создать еще один экземпляр формы - это разве не то же самое?