![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Многократно копировать форму в MDI приложении [D7, XP]
anvolkov © (2009-06-07 17:37:00)Прошу вашего совета в таком вопросе.
Имеется MDI программа. Имеется форма, к примеру - накладная.
Нужно открывать ее не 1 раз, как это получается, а иметь возможность открывать сколько угодно ее копий, т.е. просматривать одновременно много разных накладных (как в 1С)
В документации так и не понял как это сделать.
Делать через классы не смогу, т.к. задолбаюсь прописывать в коде все расположения кнопок, все размеры, связи и т.д.
Если можно дублировать уже созданную в конструкторе форму - подскажите маленьким примерчиком, если не сложно...
Юрий Зотов (2009-06-08 14:48:00) [1]> Игорь Шевченко © (08.06.09 14:40) [25]
Ах, да, конечно.
LOL
Игорь Шевченко (2009-06-08 14:40:00) [2]Юрий Зотов © (08.06.09 14:28) [23]
Я вообще-то про Show говорил, что понятнее, а не про изменение стиля. Это к вопросу о RecreateWnd. Даже уточнил, в посте [18]
> А комментарий:
> // Вызов Show для child-форм не нужен, они становятся видимыми
> сами.
> в пять раз понятнее.
>
> И, что главное - в миллион раз полезнее.
Неубедительно.
Юрий Зотов (2009-06-08 14:34:00) [3]> Игорь Шевченко © (08.06.09 14:15) [22]
> код с созданием формы и вызовом Show - понятнее.
А комментарий:
// Вызов Show для child-форм не нужен, они становятся видимыми сами.
в пять раз понятнее.
И, что главное - в миллион раз полезнее.
Юрий Зотов (2009-06-08 14:28:00) [4]> Игорь Шевченко © (08.06.09 14:15) [22]
> И все-таки, откуда RecreateWnd-то взялся ?
Игорь, не ожидал. Просто убил. При изменении оконного стиля формы надо пересоздать само ее окно, или нет?
procedure TForm1.FormDblClick(Sender: TObject);
begin
TForm2.Create(Self).FormStyle := fsMDIChild
end;
Изначально TForm1 - fsMDIForm, TForm2 - fsNormal. При изменении TForm2.FormStyle метод RecreateWnd вызывается автоматически, причем аж дважды. Вызывать его в третий раз вручную можно (и, якобы, наглядно) - но не нужно.
Это иллюстрация к твоей "наглядности".
Игорь Шевченко (2009-06-08 14:15:00) [5]Юрий Зотов © (08.06.09 13:45) [21]
Представь себе, код с созданием формы и вызовом Show - понятнее.
А что до лишних вызовов, то как только ты используешь AnsiString по сравнению с array of char, у тебя генерируется столько вызовов, что по сравнению с ними перечисленное тобой выглядит незначительным.
И все-таки, откуда RecreateWnd-то взялся ? :)
Юрий Зотов (2009-06-08 13:45:00) [6]> Игорь Шевченко © (08.06.09 13:01) [20]
> if FVisible <> Value then
Это и козе было понятно, практически все сеттеры так работают. Итого имеем лишнего:
- вызов TCustomForm.Show
- вызов TCustomForm.SetVisible
- проверка Visible <> Value в TCustomForm.SetVisible
- вызов TControl.SetVisible
- проверка FVisible <> Value в TControl.SetVisible
- 2 раза RET
И, кроме того:
- вызов TControl.BringToFront
- вызов TControl.SetZOrder
- проверка FParent <> nil в TControl.SetZOrder
- 2 раза Ret
Плюс обращения к полям объектов (загрузка в регистры и пр.), которых в этой цепочке тоже участвует немало.
И зачем все это? Достаточно просто знать, что child-формы невидимыми не бывают - и никакой "наглядности" уже не потребуется. Кстати, знать это не только достаточно, но и необходимо. А для совсем уж особых чайников достаточно перед вызовом конструктора child-формы написать комментарий:
// Вызов Show для child-форм не нужен, они становятся видимыми сами.
В общем, так - спорить тут не о чем. Если тебе нравится делать на фиг не нужные вызовы - вызывай хоть 100 раз. Только процитирую твои же слова: "у меня при взгляде на подобный код возникают сомнения в компетентности написавшего его программиста".
Игорь Шевченко (2009-06-08 13:01:00) [7]Юрий Зотов © (08.06.09 12:56) [19]
Отслеживаю:
procedure TCustomForm.SetVisible(Value: Boolean);
begin
if fsCreating in FFormState then
if Value then
Include(FFormState, fsVisible) else
Exclude(FFormState, fsVisible)
else
begin
if Value and (Visible <> Value) then SetWindowToMonitor;
inherited Visible := Value;
end;
end;
procedure TControl.SetVisible(Value: Boolean);
begin
if FVisible <> Value then begin
VisibleChanging;
FVisible := Value;
Perform(CM_VISIBLECHANGED, Ord(Value), 0);
RequestAlign;
end;
end;
Как ты пришел к своим строкам ?
Юрий Зотов (2009-06-08 12:56:00) [8]Самое непосредственное.
Как ты знаешь, по умолчанию формы имеют Visible = False. И если child-форма становится видимой "автоматически", значит показ child-форм происходит так же "автоматически", где-то в недрах кода VCL. И даже без особого копания в этих недрах ясно, что показ формы тащит за собой неслабую цепочку исполняемого кода.
Спрашивается - зачем же вызывать эту же цепочку второй раз?
procedure TCustomForm.Show;
begin
Visible := True;
BringToFront;
end;
Отследи, к чему это приводит, включая вызов унаследованных методов. Не слишком ли дорогая цена мнимой "наглядности"?
Игорь Шевченко (2009-06-08 10:42:00) [9]
> FormStyle := ...;
> RecreateWnd; // Который УЖЕ был вызван сеттером, но так
> ведь понятнее?
Я надеюсь, приведенный код к TCustomForm.Show не имеет отношения ?
Юрий Зотов (2009-06-08 10:13:00) [10]Вызывать ненужный метод ради "понятности"? Не понимаю.
FormStyle := ...;
RecreateWnd; // Который УЖЕ был вызван сеттером, но так ведь понятнее?
Германн (2009-06-08 00:39:00) [11]
> Игорь Шевченко © (07.06.09 20:38) [12]
> Сергей М. © (07.06.09 22:03) [13]
>
>
> > Может быть он и избыточен, зато код более понятен
>
>
> Бесспорно.
Увы не соглашусь.
Будучи сей код распечатан на бумаге (в т.ч. на электронной) - тогда (и иногда) он более понятен (некоторым :).
Игорь Шевченко (2009-06-07 23:02:00) [12]
> Но факт этот знать непременно нужно, согласись ?
Соглашаюсь :)
Нат (2009-06-07 23:02:00) [13]Отдельный писк - попытка изменить тип из mdichild, установленный в дизайнере, на Нормал в событии формы OnCreate. :)
Сергей М. (2009-06-07 22:03:00) [14]
> Может быть он и избыточен, зато код более понятен
Бесспорно.
Но факт этот знать непременно нужно, согласись ?
Ведь вторая строчка хит-парада вопросов про дельфийские MDIChild-формы - "а почему я ее хАйдю-клОзю, а она, зараза, уперлась и не хочет закрываться ?"
Игорь Шевченко (2009-06-07 20:38:00) [15]
> создание таких форм автоматически подразумевает их визуализацию,
> так что явный вызов тобой метода Show избыточен
Может быть он и избыточен, зато код более понятен
anvolkov (2009-06-07 19:09:00) [16]Спасибо за советы. Буду крутить, пробовать. :)
Нат (2009-06-07 19:06:00) [17]Специально для правильно реакции объектов в событиях и методах объектов используется переменная Self, а также передается ссылка на объект
procedure BitBtn1Click(Sender: TObject);
Сергей М. (2009-06-07 19:05:00) [18]
> show как раз и задумывался, чтобы открывать окна
Show в переводе с нерусского - это "показать", а не "открыть".
"Открыть" в переводе с того же нерусского - это Open, но никак не Show.
Запомни: дельфийские MDIChild-формы немогут быть невидимыми, т.е. их создание (Create) безусловно влечет за собой их визуализацию (Show), то бишь создание таких форм автоматически подразумевает их визуализацию, так что явный вызов тобой метода Show избыточен, о чем и было важное замечание в [6].
Юрий Зотов (2009-06-07 18:52:00) [19]> anvolkov © (07.06.09 18:41) [7]
Андрей, в каталоге Delphi\Demos\Doc\TextEdit лежит пример проекта с MDI-Child формами. Если Вы его откомпилируете, запустите, посмотрите, как он работает, а потом посмотрите, как он написан, то...
...то таких конфузов, как в этой ветке, я надеюсь, Вы больше не допустите.
anvolkov (2009-06-07 18:41:00) [20]
> И Show для child-форм - лишнее.
так show как раз и задумывался, чтобы открывать окна накладных, а пользователь поработав с ними - будет закрывать и освобождать эти формы.
Т.е. пусть живет одна форма - оригинал.
> А лучше всего эту переменную сразу удалить. Надежнее будет.
хм... а если на форме куча процедур обработки различных объектов? и все они управляются form2.
может, как-то можно объявить класс, включить в него готовую форму из конструктора, прописать обработчики и просто создавать?