Закрытие дочерних окон при закрытии главного окна

Тема в разделе "LANGS.C", создана пользователем WishMaster, 21 июл 2008.

  1. WishMaster

    WishMaster New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2006
    Сообщения:
    54
    Адрес:
    Ukraine
    Помогите, пожалуйста в решении следующей на первый взгляд простой проблемы. Для демонстрации ее сути создал простенькое приложение. Есть главная форма MainForm (fsMDIForm), в которой можна создавать дочерние формы ChildForm (fsMDIChild). При закрытии отдельно взятой дочерней формы в обработчике события OnCloseQuery у пользователя спрашивается, закрывать ли эту дочернюю форму или оставить открытой. При закрытии главной формы сначала запускаются по очереди обработчики события OnCloseQuery для всех дочерних окон, спрашивают, закрывать ли соответствующее дочернее окно и только в случае подтверждения закрытия ВСЕХ дочерних окон дочерние окна по очереди закрываются, после чего зарывается главная форма. Если же пользователь подтвердил, например, закрытия первых двох дочерних форм, а для третьей нажал "Нет", то ничего не закроется и все три дочерние формы останутся открытыми, что явно не логично.

    На сколько я понял, то при закрытии главной формы события разворачиваются так:
    1) срабатывают по очереди OnCloseQuery дочерних окон;
    2) если после всех OnCloseQuery дочерних окон переменная CanClose остается true, то срабатывает OnCloseQuery главного окна;
    3) если и после этого CanClose == true, то срабатывает событие OnClose ГЛАВНОЙ ФОРМЫ, событие же OnClose дочерних окон при этом не срабатывают.

    Мне же нужна следующая ситуация:
    1) при закрытии главной формы для каждой дочерней формы спрашивается разрешение на ее закрытие;
    2) если для даной дочерней формы пользователь подтвердил закрытие, она сразу закрывается;
    3) если пользователь запретил закрытие дочерней формы, то больше ничего не закрывается вообще.
    По-моему так выглядит логично. Я пробовал в обработчике OnCloseQuery дочерней формы в случае подтверждения закрытия сразу закрывать дочернюю форму, но вылазит ошибка. На сколько я понимаю, пока при попытке закрытия главной формы не будут опрошены все дочерние формы закрывать дочерние формы нельзя. Так ли это? И как быть? Думаю не я первый с таким столкнулся.

    Заранее благодарен за советы :)

    ПС. Код главного окна:

    Код (Text):
    1. TMainForm *MainForm;
    2. //---------------------------------------------------------------------------
    3. __fastcall TMainForm::TMainForm(TComponent* Owner)
    4.         : TForm(Owner)
    5. {
    6. }
    7. //---------------------------------------------------------------------------
    8. void __fastcall TMainForm::N2Click(TObject *Sender)
    9. {
    10.   TChildForm* NewChildForm = new TChildForm(Application);
    11.   NewChildForm->Caption = "Окно " + IntToStr(MDIChildCount);
    12. }
    13. //---------------------------------------------------------------------------
    14.  
    15. void __fastcall TMainForm::N3Click(TObject *Sender)
    16. {
    17.   if (MDIChildCount)
    18.     (dynamic_cast<TChildForm*>(MainForm->ActiveMDIChild))->Close();
    19. }
    Код дочернего окна:

    Код (Text):
    1. TChildForm *ChildForm;
    2. //---------------------------------------------------------------------------
    3. __fastcall TChildForm::TChildForm(TComponent* Owner)
    4.         : TForm(Owner)
    5. {
    6. }
    7. //---------------------------------------------------------------------------
    8.  
    9. void __fastcall TChildForm::FormCloseQuery(TObject *Sender, bool &CanClose)
    10. {
    11.   CanClose = (Application->MessageBox(("Закрыть " + Caption + "?").c_str(), "Внимание", MB_YESNO + MB_ICONWARNING) == IDYES);
    12. }
    13. //---------------------------------------------------------------------------
    14. void __fastcall TChildForm::FormClose(TObject *Sender,
    15.       TCloseAction &Action)
    16. {
    17.   Action = caFree;
    18. }
    Проект прилагается к теме.
     
  2. Vilco

    Vilco Vitaly

    Публикаций:
    0
    Регистрация:
    5 мар 2007
    Сообщения:
    190
    Адрес:
    Nsk, Russia
    Я не знаю, с билдером сильно не сталкивался, но попробуй в обработчике FormCloseQuery вызвать DestroyWnd(), если конечно CanClose == true
     
  3. WishMaster

    WishMaster New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2006
    Сообщения:
    54
    Адрес:
    Ukraine
    Проблему решил, отказавшись от использования события OnCloseQuery дочерних форм.
    Вот код, все работает, как и должно:

    Главная форма:

    Код (Text):
    1. TMainForm *MainForm;
    2. //---------------------------------------------------------------------------
    3. __fastcall TMainForm::TMainForm(TComponent* Owner)
    4.         : TForm(Owner)
    5. {
    6. }
    7. //---------------------------------------------------------------------------
    8. void __fastcall TMainForm::MCreateChildFormClick(TObject *Sender)
    9. {
    10.   TChildForm* NewChildForm = new TChildForm(Application);
    11.   NewChildForm->Caption = "Окно " + IntToStr(MDIChildCount);
    12. }
    13. //---------------------------------------------------------------------------
    14.  
    15. void __fastcall TMainForm::MCloseChildFormClick(TObject *Sender)
    16. {
    17.   if (MDIChildCount)
    18.     (dynamic_cast<TChildForm*>(ActiveMDIChild))->Close();
    19. }
    20. //---------------------------------------------------------------------------
    21.  
    22. void __fastcall TMainForm::FormCloseQuery(TObject *Sender, bool &CanClose)
    23. {
    24.   TCloseAction CurrentAction;
    25.   while (MDIChildCount)
    26.     {
    27.       (dynamic_cast<TChildForm*>(ActiveMDIChild))->FormClose(ActiveMDIChild, CurrentAction);
    28.       if (CurrentAction == caFree) delete ActiveMDIChild;
    29.       else
    30.         {
    31.           CanClose = false;
    32.           return;
    33.         }
    34.     }
    35. }
    Дочерняя форма:

    Код (Text):
    1. TChildForm *ChildForm;
    2. //---------------------------------------------------------------------------
    3. __fastcall TChildForm::TChildForm(TComponent* Owner)
    4.         : TForm(Owner)
    5. {
    6. }
    7. //---------------------------------------------------------------------------
    8.  
    9. void __fastcall TChildForm::FormClose(TObject *Sender,
    10.       TCloseAction &Action)
    11. {
    12.   Action = Application->MessageBox(("Закрыть " + Caption + "?").c_str(), "Внимание", MB_YESNO + MB_ICONWARNING) == IDYES ? caFree : caNone;
    13. }