Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Игра с формами


Страницы:   1 2 3

Kostafey ©   (2007-04-24 17:19:00) 

Уважаемые Мастера!
Помогите пожалуйста разрешить следующую проблему.
Повторить ее очень просто.
Создается Form1, Form2, Form3.

На Form1размещаются 2 кнопки (вызывающие Form2 -модально и Form3):

procedure TForm1.ButtonForm2ModalCallClick(Sender: TObject);
begin
 Form2.ShowModal;
end;

procedure TForm1.ButtonForm3CallClick(Sender: TObject);
begin
 Form3.Show;
end;


На Form2размещается 1 кнопка (вызывающая Form3):

procedure TForm2.ButtonForm3CallClick(Sender: TObject);
begin
 Form3.Show;
end;


На Form3размещается например Memo

Запускаем.
Жмем на кнопку, вызывающую модально Form2, Затем на Form2 нажимаем кнопку, вызывающую Form3.
Memo, находящееся на Form3 будет работать исправно.

Теперь другая ситуация.
Перезапускаем приложение.
Жмем в Form1 на кнопку, вызывающую Form3 (ее содержимое работеает исправно),
затем на Form1 нажимаем кнопку, вызывающую модально Form2. А в Form2
Вызываем уже открытую Form3. Все! Содержимое Form3, например, Memo работать не будет.
Не будут работать и другие визуальные компоненты формы.

Описанная ситуация точно копирует, ту сложность что возникла у меня.
Притом, даже если предварительно программно закрыть Form3:

procedure TForm2.ButtonForm3CallClick(Sender: TObject);
begin
 Form3.Close;
 Form3.Show;
end;

Ничего не изменится.
Сделать так:

procedure TForm2.ButtonForm3CallClick(Sender: TObject);
begin
 if Form3.Active then Form3.BringToFront
 else Form3.Show;
end;

Тоже бесполезно.

Как же заставить Form3, уже открытую до этого, адекватно работать
при вызове ее из модальной формы?


Leonid Troyanovsky   (2007-04-25 15:53:00) [1]


> Kostafey ©   (25.04.07 03:30) [56]

> (а тем более из модальных)

Вызов немодальных форм из модальных рискован,
т.к. вызываемое может затеряться.
Особенно, если у него не будет своей кнопки на таскбаре.

Модальность - это один из способов сосредоточить
внимание юзера на принимаемом решении.

--
Regards, LVT.


Leonid Troyanovsky   (2007-04-25 15:41:00) [2]


> Kostafey ©   (25.04.07 03:30) [56]

> Все же получается удобнее иметь для немодальных форм глобальные
> указатели,
> будь то, поля главной формы или просто переменные в случае,
>  если каждое окно
> должно быть только в 1 экземпляре.
> Конечно, когда требуется иметь несколько экземпляров окна,
>  тут другого пути нет.
> Но если нужно работать одним экземпляром, то отсутсвие указателя
> все только усложнит.


Во-первых, корректное хранение ссылки в поле формы
(никаких переменных!) не так уж и просто.
Вот пример хранения ссылки на TForm2, которая должна
существовать лишь в одном экземпляре:

type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
 private
   { Private declarations }
   FForm2: TForm;
 public
   { Public declarations }
   procedure Notification(AComponent: TComponent; Operation: TOperation); override;
 end;

implementation

{$R *.dfm}

uses
 unit2;   {у TForm2 сделаем в обработчике OnClose: Action:= caFree}

procedure TForm1.Notification;
begin
 inherited;
 if AComponent = FForm2 then
   if Operation = opRemove then
     FForm2 := nil;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 if not Assigned(FForm2) then
   begin
     FForm2 := TForm2.Create(nil);
     FreeNotification(FForm2);
   end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 if Assigned(FForm2) then
   TForm2(FForm2).Show;
end;


Так что, использование Screen.Forms может быть и проще :)

--
Regards, LVT.


Kostafey   (2007-04-25 03:30:00) [3]

После нескольких эксперементов возник еще один вопрос.

> Мы хотели лишь сказать, что использовать глобальные
> переменные типа Form1..N не следует ни для каких форм.


> В быту называемыми полями (формы).
> Можно даже и вовсе без переменных обойтись, бо
> храняться все ссылки на формы в Screen.Forms.

Все же получается удобнее иметь для немодальных форм глобальные указатели,
будь то, поля главной формы или просто переменные в случае, если каждое окно
должно быть только в 1 экземпляре.
Конечно, когда требуется иметь несколько экземпляров окна, тут другого пути нет.
Но если нужно работать одним экземпляром, то отсутсвие указателя все только усложнит.
Screen.Forms - не слишком удобно.

Два эти фрагмента

 Form3.Close;
 Form3.Free;
 Form3:=TFormSubject.Create(Application);
и
 Form3.Perform(CM_RECREATEWND, 0, 0);

не идентичны, т.к. при Perform(CM_RECREATEWND, 0, 0) окно межет вести себя довольно странно,
например, если до этого оно находилось wsMaximized (run-time настройка), то после Perform(CM_RECREATEWND, 0, 0)
оно уже не вернется в wsNormal.

В таком случае, неужели если вызов немодального окна происходит из немодальных окон,
(а тем более из модальных) то в профессональных программах всегда предусматривают пересоздание окна ?


Kostafey   (2007-04-24 23:34:00) [4]

> См [41] с поправкой в [43]. В общем - ветку с начала :)

Перечитал. Все понял.


> Мы играем в игру угадал/неугадал?

Я лишь хотел убедиться, что понял правильно. Убедился. Правильно.


> Хватит "мусорить"

Последний разок помусорю на этой ветке:
с меня пиво :)))

Ну, как говорится, будете к нас на Колыме (С)


{RASkov}   (2007-04-24 23:15:00) [5]

> [53] Kostafey ©   (24.04.07 22:31)
> Далее мы пересоздаем певую (из Form2) созданную форму как будто и не было ее.
> with TForm2.Create(nil) do Show;
> Правильно ?

Мы играем в игру угадал/неугадал? Хватит "мусорить".... Перечитай ветку с начала. Вместе с F1, здесь все ответы есть на твои вопросы.
Или задавай их более конкретнее. Я не понял последний твой вопрос. А про
> А это
> if Assigned(Form2) then FreeAndNil(Form2);
> мы просто для "очистки совести" написали.

См [41] с поправкой в [43]. В общем - ветку с начала :)


Kostafey   (2007-04-24 22:31:00) [6]

> [52] {RASkov} ©   (24.04.07 22:18)

А-а-а понял.
Дело не в объектах, дело в ссылках на них.
А это
if Assigned(Form2) then FreeAndNil(Form2);
мы просто для "очистки совести" написали.

Далее мы пересоздаем певую (из Form2) созданную форму как будто и не было ее.
with TForm2.Create(nil) do Show;

Правильно ?


{RASkov}   (2007-04-24 22:18:00) [7]

> [50] Kostafey ©   (24.04.07 22:09)

Да-а-а..., не думал я что такой "непонятный" пример приведу.... :)

> нигде локальной переменной Form2 не объявлено,

Вот именно... используем глобальную.

> кроме того
> при разрушении формы она должна исчезнуть с экрана.

А ты разве видишь форму с заголовком F3?

> А у нас "Исходная" Form2 спокойно "висит".

Висит, но ссылка(Form2) на нее "битая" уже...

> И вообще, получается так, что указатели Form2:=TForm2.Create(Self)
> полученные в процедуре обработчика потом теряются.

Именно...

> Если глобальной Form2 нет, то все логично, но непонятно почему она уже уничтожена?

Опять все сначала :(


Kostafey   (2007-04-24 22:09:00) [8]

> Мы "рушим глобальную переменную"....

Вот ключ моего непонимания.
в procedure TForm2.Button1Click(Sender: TObject);
нигде локальной переменной Form2 не объявлено, кроме того
при разрушении формы она должна исчезнуть с экрана.
А у нас "Исходная" Form2 спокойно "висит".
...
И вообще, получается так, что указатели Form2:=TForm2.Create(Self)
полученные в процедуре обработчика потом теряются.


> и в Form1 мы уже не имеет корректной Form2 поэтому Form2.Show
> - AV.

Если глобальной Form2 нет, то все логично, но непонятно почему она уже уничтожена?


Kostafey   (2007-04-24 22:09:00) [9]

> Мы "рушим глобальную переменную"....

Вот ключ моего непонимания.
в procedure TForm2.Button1Click(Sender: TObject);
нигде локальной переменной Form2 не объявлено, кроме того
при разрушении формы она должна исчезнуть с экрана.
А у нас "Исходная" Form2 спокойно "висит".
...
И вообще, получается так, что указатели Form2:=TForm2.Create(Self)
полученные в процедуре обработчика потом теряются.


> и в Form1 мы уже не имеет корректной Form2 поэтому Form2.Show
> - AV.

Если глобальной Form2 нет, то все логично, но непонятно почему она уже уничтожена?


{RASkov}   (2007-04-24 21:38:00) [10]

> Мы рушим последнюю Form2(Form2.Caption:='F3';)?

Мы "рушим глобальную переменную"....
и в Form1 мы уже не имеет корректной Form2 поэтому Form2.Show - AV.


Kostafey   (2007-04-24 21:17:00) [11]

> Когда форма не автосоздаваемая, то ее надо
> создать собс-ручно. Логика прослеживается?
>
> Т.е., создаем объект, пользуем и за ненадобностью - рушим.

Это ясно.
А что же тогда рушит процедура FreeAndNil(Form2); в [37].
Явно не ту форму, кнопка которой сейчас нажимается.
Мы рушим последнюю Form2 (Form2.Caption:='F3';)?

А потом заново (пришелчке на кнопке первой формы) создаем Form2 первоначального варианта ?


{RASkov}   (2007-04-24 21:14:00) [12]

> [45] Kostafey ©   (24.04.07 21:04)
> > якобы показать выполнение следующей строки,.....
>
> Понял, речь шла об F3.

Нет... это не об этом :)

> Почему эта конструкция посыпалась?
> Мол, Form2 теперь много?

Нет, не поэтому... А подумать..... Form2 - это глобальная переменная которую IDE создает автоматом...
Что с ней(Form2) происходит в procedure TForm2.Button1Click и что дает следующее нажатие Button1 на Form1.....AV


Leonid Troyanovsky   (2007-04-24 21:09:00) [13]


> Kostafey ©   (24.04.07 21:04) [45]

> Мол, Form2 теперь много?
>
> procedure TForm1.Button1Click(Sender: TObject);
> begin
> Form2.Show;
>
> Боюсь, это уже выше моего понимания.

Когда форма не автосоздаваемая, то ее надо
создать собс-ручно. Логика прослеживается?

Т.е., создаем объект, пользуем и за ненадобностью - рушим.

--
Regards, LVT.


Kostafey   (2007-04-24 21:04:00) [14]

> Исправь на Form2:=TForm2.Create(Self);
> Не доглядел :(

Да, догадался, спасибо.


> якобы показать выполнение следующей строки,.....

Понял, речь шла об F3.

Я главного не понял. Почему эта конструкция посыпалась?
Мол, Form2 теперь много?

procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Show;

Боюсь, это уже выше моего понимания.


Leonid Troyanovsky   (2007-04-24 21:03:00) [15]


> {RASkov} ©   (24.04.07 20:52) [41]

> Эта строчка собственно и не нужна, вставил ее только потому
> что Form2 в Autocreate и, якобы показать выполнение

Вот, видно, что ты не педагог :)

Педагог же, если преподносит нечто, то должно, видимо,
небо обвалиться, чтобы он отошел от оного даже в
_малейшем_  начертании.

Т.е., палочки д.б. попендикулярны и усё :)
И никаких яковых.

--
Regards, LVT.


{RASkov}   (2007-04-24 20:56:00) [16]

> и, якобы показать выполнение следующей, небудь Form2 в AutoCreate.

якобы показать выполнение следующей строки,.....


{RASkov}   (2007-04-24 20:54:00) [17]

> [40] Kostafey ©   (24.04.07 20:48)
> Form2:=TForm3.Create(Self);

Исправь на Form2:=TForm 2.Create(Self);
Не доглядел :(


{RASkov}   (2007-04-24 20:52:00) [18]

> [39] Leonid Troyanovsky ©   (24.04.07 20:46)
> if Assigned(Form2) then FreeAndNil(Form2);

Эта строчка собственно и не нужна, вставил ее только потому что Form2 в Autocreate и, якобы показать выполнение следующей, небудь Form2 в AutoCreate.


Kostafey   (2007-04-24 20:48:00) [19]

> [37] {RASkov} ©   (24.04.07 20:36)


Form2:=TForm3.Create(Self);
[Oшибкa] Unit2.pas(36): Incompatible types: 'TForm2' and 'TForm3'

Сейчас попробую разобраться...


Leonid Troyanovsky   (2007-04-24 20:46:00) [20]


> {RASkov} ©   (24.04.07 20:36) [37]

> // if Assigned(Form2) then FreeAndNil(Form2);

Не хочу снижать педагогический эффект,
и неохота, собс-но, воспроизводить твой, без сомнения,
полезный пример, но, мимо квотируемого пройти не могу.

Т.е., FreeAndNil тоже костыль, бо, для любых компонентов
механизма Notification вполне, IMHO, достаточно.

Да озаботятся этим все держатели ссылок на компонент.

--
Regards, LVT.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо