Форум: "Начинающим";
Текущий архив: 2006.10.29;
Скачать: [xml.tar.bz2];
ВнизУничтожение родительской формы Найти похожие ветки
← →
Alex Kryuchkov (2006-10-09 14:19) [0]Добрый день!
Есть МДИ-приложение. Пусть его главная форма называется ФОРМА1.
В нём имеется ФОРМА2, которая вяляется МДИ-потомком ФОРМЫ1.
А на ФОРМЕ2 расположена ФОРМА3, то есть ФОРМА3.parent=ФОРМА2,
ФОРМА3.owner=ФОРМА2,
Пусть на ФОРМЕ3 есть КНОПКА.
По нажатию этой кнопки выполняется уничтожение ФОРМЫ2, т.е
FORM2.Free;
Так вот, если так делать, то получим Access Violation, что естественно, так как ФОРМА2 пытается уничтожить ФОРМУ3, а та как раз выполняет обработку сообщения нажатия на кнопку.
В документации по Делфи написано, что так делать нельзя.
НО!
Если мы перед уничтожением ФОРМЫ3 покажем какой-нибудь месседж, то ошибки не увидим:
procedure TForm3.Button1Click(Sender: TObject);
begin
Showmessage("сообщение");
Form2.Free;
end;
Аналогичный эффект будет, если соответствующим образом переопределить деструктор ФОРМЫ2.
Внимание вопрос
Почему так происходит? И как избежать ошибки без отображения сообщения?
Проблема состоит в том, что имеется достаточно большое приложение, в котором есть похожий код и отказаться от такой схемы нельзя.
← →
Сергей М. © (2006-10-09 14:35) [1]
> ФОРМА2, которая вяляется МДИ-потомком ФОРМЫ1
Это как ?
← →
Shirson © (2006-10-09 14:44) [2]Child можно перевести как "потомок". Получите и распишитесь MDIChild = МДИ-потомок.(а CD-ROM = КД-ПЗУ)
← →
Сергей М. © (2006-10-09 14:51) [3]
> Shirson © (09.10.06 14:44) [2]
Галиматья.
← →
clickmaker © (2006-10-09 15:17) [4]Потомок - это некто, наследующий что-то от родителя.
MDI-child ничего от главной формы не наследует. Он сам по себе, но находится внутри нее. Разные понятия.
← →
Плохиш © (2006-10-09 15:18) [5]
> Alex Kryuchkov (09.10.06 14:19)
> Пусть на ФОРМЕ3 есть КНОПКА.
> По нажатию этой кнопки выполняется уничтожение ФОРМЫ2, т.
> е
> FORM2.Free;
Ужасть, вот дети пошли так и наровят родителей топором прибить.
> А на ФОРМЕ2 расположена ФОРМА3, то есть ФОРМА3.parent=ФОРМА2,
> ФОРМА3.owner=ФОРМА2,
тогда уж,TForm(self.Parent).Release;
> Проблема состоит в том, что имеется достаточно большое приложение,
> в котором есть похожий код и отказаться от такой схемы
> нельзя.
Тогда это не код, а сплошной глюкодром.
← →
Shirson © (2006-10-09 15:23) [6]Сергей М. ты это не мне говори, а автору.
← →
Сергей М. © (2006-10-09 15:30) [7]
> Shirson © (09.10.06 15:23) [6]
У автора непонимание.
А галиматья именно у тебя.
← →
Shirson © (2006-10-09 15:51) [8]Эот был ответ на твой вопрос.
← →
Сергей М. © (2006-10-09 15:54) [9]
> Shirson © (09.10.06 15:51) [8]
Идиотский ответ на вполне резонный вопрос к автору "что такое MDI-потомок"
← →
Shirson © (2006-10-09 15:58) [10]Что в нём идиотского?
Автор написал "ФОРМА2, которая вяляется МДИ-потомком ФОРМЫ1"
Вы спросили "Как это?"
Я вам перевёл "MDIChild = МДИ-потомок"
Что идиотского в моём ответе?
← →
Alex Kryuchkov (2006-10-09 16:07) [11]Что ж господа, кроме абстрактых обсуждений ничего конструктивного в ваших ответах я не заметил.
Но всё равно спасибо за участие
← →
Alex Kryuchkov (2006-10-09 16:08) [12]Кроме того, я категорически не согласен с переводом вопроса в категорию "для начинающих".
По-моему, обработка сообщений и код ВЦЛ (а по сути проблема в нём) - это не вопрос для начинающих
← →
Сергей М. © (2006-10-09 16:10) [13]
> Alex Kryuchkov (09.10.06 16:07) [11]
> ничего конструктивного в ваших ответах я не заметил
Пока не ответишь на вопрос [1], "конструктивного" не жди.
Потому что "MDI-потомок" - это не понятно что.
← →
Сергей М. © (2006-10-09 16:11) [14]
> обработка сообщений и код ВЦЛ (а по сути проблема в нём)
Если так, то в "Начинающие" ты попал совершенно закономерно.
← →
Shirson © (2006-10-09 16:11) [15]Alex Kryuchkov, организуйте "очередь" команд для этого случая, которая обрабатывается в процедурах Form1. При нажатии на кнопку удаления Form2, не происходит именно удаления, а генерится событие, которое обрабатывается в Form1 и из неё удаляется Form2.
Надеюсь, я достаточно наглядно описал свою мысль?
← →
Alex Kryuchkov (2006-10-09 16:52) [16]Уважаемый Shirson!
Спасибо за ответ.
К сожалению, предложенный Вами способ реализовать нельзя.
Дело в том, что приведенный мною здесь пример иллюстрирует работу очень сложного и большого приложения, в котором (возможно) была допущена ошибка проектирования в части обработки сообщений.
Реализация Вашего способа очень трудоемка.
Именно поэтому хотелось бы узнать, как можно решить проблему каким-нибудь "обходным путем"
← →
Alex Kryuchkov (2006-10-09 16:55) [17]Сергей М., Shirson дал совершенно правильный ответ [2] на твой вопрос.
Что теперь ты можешь сказать конструктивного?
← →
clickmaker © (2006-10-09 16:56) [18]procedure TForm3.Button1Click(Sender: TObject);
begin
Form2.Release;
end;
← →
Ketmar © (2006-10-09 16:58) [19]а вообще, имо, тут надо менеджер форм делать. который и будет заведовать убийствами/рождениями. а ему командовать через PostMessage(). %-)
← →
Сергей М. © (2006-10-09 16:59) [20]
> Alex Kryuchkov (09.10.06 16:55) [17]
А что тебе сказать "конструктивного", если MDI тобой упомянут всуе, ибо не имеет НИ малейшего отношения к "проблеме" ?
см. [18]
← →
Alex Kryuchkov (2006-10-09 17:04) [21]Сергей М.,
предложенный в [18] способ работать не будет. Более того, и не работает.
Что ты можешь сказать о том, что АВ не летит, если выводить перед вызовом деструктора сообщение?
Если невнимательно читал вопрос, повторяю еще раз:
procedure TForm3.Button1Click(Sender: TObject);
begin
Showmessage("сообщение");
Form2.Free; //AV нет
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
Form2.Free; //AV есть
end;
← →
Ketmar © (2006-10-09 17:07) [22]>[21] Alex Kryuchkov 9-Oct-2006, 17:04
>предложенный в [18] способ работать не будет.
почему? вообще -- в курсе отличий Free() и Release()? отцы рекомендуют, кстати, именно последний метод. более того, у отцов он работает. может, всё-таки руки как-то не так встали? %-)
← →
MsGuns © (2006-10-09 17:07) [23]В свое время были проблемы с MDI-программированием.
После внимательного прочтения Тексейры и освоения некоторых основных правил построения MDI-интерфейса все проблемы испарились.
Вот основные принципы проектирования MDI:
1. Главная форма (она же является и "владелицей" и "родительницей" всех "дочек посредством своей клиентской области) должна содержать максимум функционала и переменных общего назначения. В том числе элементов управления (кнопки, меню, подменю и т.д. - реализованные через ОБЩИЙ TActionList, TImageList). Обработчики акций должны обращаться к "дочкам" через ActiveMDIForm, определяя их тип либо посылать посредством сообщений.
2. "Дочки" должны работать независимо друг от друга, общаясь только с "мамой". Т.е. если одна "дочка" должна передать другой "дочке" что-либо, то делается это строго через "маму" посредством "маминых" же объектов (переменные, структуры, массивы и т.д.) либо сообщениями.
3. "Дочки" должны содержать только специфический для их класса функционал и минимум элементов управления. Элементы управления могут находиться как на самих "дочках", так и интегрироваться с общим "маминым" управляющим интерфейсом.
4. Если приложение работает с БД, то не должно быть "дочек", разделяющих общие датасеты (не путать с таблицами !)
← →
Ketmar © (2006-10-09 17:14) [24]>[23] MsGuns(c) 9-Oct-2006, 17:07
ну да. примерно это я и имел в виду в [19]. только расписывать так чётко лень. %-)
← →
Shirson © (2006-10-09 17:15) [25]procedure TForm2.FormCreate(Sender: TObject);
begin
Application.CreateForm(TForm3, Form3);
Form3.Parent:=Form2;
Form3.Show;
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
Form2.free; // Form2.Release; тоже функционирует.
end;
Всё работает - форма прилежно умирает, без вскриков.
← →
MsGuns © (2006-10-09 17:15) [26]5. При реализации общего функционала в "маме" исключать обращения к экземплярам кдасса "дочек" (это вообще дурной метод, приводящий к большим проблемам при оиладке и глюкам при работе приложений), активно используя Sender и контроль типа "инициатора", вызвавшего то или иное событие (действие), а также сво-во "мамы" ActiveMDIChild. Это поможет избежать исключений и непоняток при отладке, хоть иногда и приводит к некоторой кажущейся избыточности кода
ЗЫ. Я вообще считаю, что лучше написать 200 "лишних" строк, проверяющих корректность кода, чем в погоне за "оптимальностью" допустить вероятность сбоя - хотя Зотов с Шевченко меня бы за это бы и обложил матюгами ;))
← →
Игорь Шевченко © (2006-10-09 17:19) [27]MsGuns © (09.10.06 17:15) [26]
Я придерживаюсь несколько иных принципов - а именно, что формы (не важно, дочки они или мамы) должны только отображать данные и реагировать на действия пользователя. А логикой (включая логику отображения форм) все-таки должны заниматься специальные классы, которые не подозревают о существовании форм.
← →
Плохиш © (2006-10-09 17:21) [28]
> Shirson © (09.10.06 17:15) [25]
Создай два экземпляра TForm2 и получишь AV с вероятностью 98%.
← →
Ketmar © (2006-10-09 17:21) [29]>[27] Игорь Шевченко(c) 9-Oct-2006, 17:19
ах, если бы в Delphi сразу вделали GC. и написали бы VCL по нормальной схеме "model-controller-view"... мечты, мечты...
← →
Игорь Шевченко © (2006-10-09 17:34) [30]Ketmar © (09.10.06 17:21) [29]
GC собственно ни к чему.
← →
MsGuns © (2006-10-09 17:35) [31]>Игорь Шевченко © (09.10.06 17:19) [27]
>Я придерживаюсь несколько иных принципов - а именно, что формы (не важно, дочки они или мамы) должны только отображать данные и реагировать на действия пользователя. А логикой (включая логику отображения форм) все-таки должны заниматься специальные классы, которые не подозревают о существовании форм.
Ну дык.. Лишнее подтверждение тому, что голубые штаны выдают не только за умный вид ;)))
← →
Игорь Шевченко © (2006-10-09 17:45) [32]MsGuns © (09.10.06 17:35) [31]
> Лишнее подтверждение тому, что голубые штаны выдают не только
> за умный вид
Все определяется литражом пива, а вовсе не видом :)
← →
Германн © (2006-10-09 17:57) [33]
> Все определяется литражом пива, а вовсе не видом :)
Интересно какой литраж в свое время пришлось выставить АП за право ходить в синих? :-)
← →
Alex Kryuchkov (2006-10-09 17:58) [34]Отвечаю на Shirson © (09.10.06 17:15) [25]
Естественно, Ваш код будет работать без ошибок - ведь OWNER у Form3 при таком коде - Application и удаление формы2, если я не ошибаюсь, не вызовет удаления формы3.
В моем же коде такая связь есть и убрать я её не могу (точнее, это очень трудно)
← →
Ketmar © (2006-10-09 18:06) [35]>[30] Игорь Шевченко(c) 9-Oct-2006, 17:34
>GC собственно ни к чему.
можно и без него, конечно. но с ним проще, и багов меньше. %-)
← →
RASkov (2006-10-09 21:35) [36]> пример иллюстрирует работу очень сложного и большого приложения
> была допущена ошибка
> Именно поэтому хотелось бы узнать, как можно решить проблему
> каким-нибудь "обходным путем"procedure TForm3.Button1Click(Sender: TObject);
begin
Showmessage("Извените, форма закрывается!");
Form2.Free;
end;
Лишняя "ошибка" в ошибочном коде, думаю не навредит:)
Ну мож там слип какойнить или еще чего вместо сообщения...
Это - если это не помогает:PostMessage(Handle, CM_RELEASE, 0, 0);
Т.е. Form2.Release;
Я англ не понимаю, но помоему здесь написано то что надо:
Release does not destroy the form until all event handlers of the form and event handlers of components on the form have finished executing. Release also guarantees that all messages in the form"s event queue are processed before the form is released. Any event handlers for the form or its children should use Release instead of Free (Delphi) or delete (C++). Failing to do so can cause a memory access error.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.10.29;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.036 c