Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > MDI проложение и Chaild окна


Автор: ALXP 7.6.2008, 11:21
Приветствую! Вот столкнулся с проблемкой.
У мну MDI приложение. Т.е. стало мди.

Я создал просто приложение с основной формой не MDI. И еще много форм тоже отдельных, сразными кнопочками и т.п.

Потом просто свойство основного окна FormStyle поставил в fsMDIForm
А те формы остальные этоже свойство FormStyle поставил в fsMDIChild

 Окна создаю кодом 
Код

if ( !f_frmUserCertif_create ) {
        Application->CreateForm(__classid(TfrmUserCertif), &frmUserCertif);
        f_frmUserCertif_create = true;
        frmUserCertif->FormStyle = fsMDIChild;
        frmUserCertif->Show();
    }else{
    frmUserCertif->SetFocus();
    }

Типа проверяю если есть уже такое созданное окно то просто устанавливаю на него фокус
По нажатии на закрытия окна пишу
Код

    MainForm->f_frmUserCertif_create = false;
    Action = caFree;

 smile  smile  ЭТО ВСЕ РАБОТАЕТ НА УРА. И нет ошибок все гуд.

НО  smile  у мну другая проблемка. Я из одного окна чайлда по нажатию на кнопочку вызываю(создаю) другое окно(форму) которая тоже чайлд для основного. Это тоже срабатывает. НО мне надо чтобы оно становилось Modal для того чайлда из которого был вызов.
ShowModal() в MDI делать нельзя, только Show()

Я не знаю как сделать это. Или просто  smile как сделать чтобы пока этот чайлд работает, все остальные прекращали выполнение и на них нельзя было нажимать

Автор: orthrus 7.6.2008, 12:06
MDIChild нельзя сделать модальным, так что вызывай это окно не как MDIChild но модально.

Автор: Vyacheslav 9.6.2008, 19:42
Cымитируй  работу модального окна.  
При вызове Child окна из друго окна передаешь ему качестве owner окно , которое его вызывает
типа
Код

void __fastcall TChildForm1::Button1Click(TObject *Sender)
{
    new TChildForm2(this);        
}


Задаешь обработчик

Код

void __fastcall TChildForm2::FormDeactivate(TObject *Sender)
{
   TForm* form =  dynamic_cast<TForm*>(Owner);
    // если  owner  -  Child-окно ,  то не даем сменить фокус
    if ( form &&  form->FormStyle == fsMDOChild)
    {
       Show();
    }
}
//-----------------------------------------------------------------------


Не забудь задать обработчики  OnClose для всех child-окон, иначе не сможешь их закрыть 
Код

void __fastcall TChildForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
    Action = caFree;    
}
//---------------------------------------------------------------------------




Добавлено @ 19:47
Кстати вот этого 
Код

        frmUserCertif->FormStyle = fsMDIChild;


в коде делать не рекомендуется. Лучше изменить в инспекторое. В хелпе есть на этот счет рекомендации( С++Builder 6 )
Цитата

Note:    It is not advisable to change FormStyle at runtime.


Чтобы Child-окна при этом не появлялись при запуске нужно убрать их из списка автосоздания
и создвать в коде, как я уже выше показывал
Если указатель на окно не нужен, то просто
Код


 new TChildForm(this); 

 

Если же  он все так для чего то нужен, то

Код


      childForm = new TChildForm(this); 

 
где childForm   - переменная типа  TChildForm

Автор: ALXP 10.6.2008, 08:30
orthrus  это я понимаю и знаю, но прога такова что все окна должны быть в оном контейнере, т.е. внутри одного окна. Такова цель. Вот только стандартные диалоги как MessageBox можно по заданию вызывать как модальные для всей проги  smile 

Vyacheslav  спасибо, но есть большиено. 

Я попробовал как Вы написали. Это работает, если мы будем нажимать на окно родитель.
НО в окне родителе есть таблица и другие элементы, если мы на них нажимаем, то активной становится форма родитель и такое же происходит когда нажимаем на кнопки свернуть развернуть.
Так что этот способ работает, но не так как надо.
 
 smile  Еще одна проблема  smile , у меня код так написан был, что я из формы вызывал другую модально( выполнение той формы из которой был вызов прекращается и управление передается вызванной форме пока она не завершит свое выполнение) , после закрытия модальной формы, я брал с нее некий обьект(переменную) и ориентируясь по этой переменной продолжал выполнение кода.
 
smile но с окнами MDIChaild такое не проходит они выполняются от и до , и нельзя поставить на паузу модальной формой. Вот почему мне и потребовалось чтобы форма вызывалась модально, и одновременно с этим прекращалось выполнение родителя, а продолжалось только по закрытию вызванной модально формы.  smile КАК ЭТО СДЕЛАТЬ?????

..-------------------------------------
А насчет того чтобы сделать неактивными остальные окна  smile 
У меня вот какая задумка появилась. Я понимаю что будет полный бред для некоторых, и не надо орать на меня и бить ногами, просто как вариант. И хочу отзывов.

У мну окон определенное количество 8 штук, они не генерятся случайно. поэтому я в оснойной WinMain могу сделать глобальные переменные для каждой формы типа bool, которые будут показывать создана форма щас или нет. И сделать функцию для тех окон которые должны вызываться типа модально, которая будет просто те окна которые созданы делать неактивными, а при закрытии такой модальной формы делать активными.
..--------------------------------------------
Думаю так будет чуток геморойней, но сработает. Но это не решит проблему паузы в окне вызывателя(родителя)

 Как можно поставить на паузу MDIChaild ? 

Автор: Vyacheslav 10.6.2008, 10:29
Ну можно пойти от обратного сделать следущее. 
Поскольку модальное окно может быть одно, создайте переменную , которое будет указывать на модальное окно и которое будет доступно для всех окон( можно в главвной форме) 
Для каждого окна задайте обработчик

Код

void __fastcall TChildForm1::FormActivate(TObject *Sender)
{
   
     if ( MainForm->ModalForm)
    {
       MainForm->ModalForm->Show();
    }
}


Чтобы передать информацию в момент закрытия окна можно  воспользоваться куче вариантов 
Например  просто в событии OnClose модально окна передать все, что нужно
Я бы сделал базовый класс для Child - окон, в котором бы предусмотрел виртуальную функцию OnModalClose(  TBaseChildForm *  modalForm)

Код

void __fastcall TChildForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
     if ( MainForm->ModalForm == this )
     {
         MainForm->ModalForm = NULL;
         TBaseChildForm * form =  dynamic_cast<  TBaseChildForm *>(Owner);
         form->OnModalClose(this);

     }    
      Action = caFree;    
}



По логике быдо бы лучше предусмотреть событие even, которое будет вызываться у родительского окна на момент закрытия  модального окна



[/code]

Автор: ALXP 10.6.2008, 10:45
 smile  так, сделал переменные флаги и по ним проверяю созданали форма(окно MDIChild) или нет при отображении (модальной)формы(окно MDIChild) и если какая либо форма(окно MDIChild) создана, делаю ее Enabled = false
а по закрытию делаю эти формы(окно MDIChild) наоборот  Enabled = true.

Это работает. Пока у меня активна (модальная)форма все остальные неактивны.
С этой проблемой разобрался.

А со второй проблемой справился (вроде справился) так (пока работает).
В форме родителе у мну есть кнопочка добавить новую запись ,а эта запись бралась из второй (модальной) формы. А сделал так. Создал в окне с кнопочкой переменную флаг(bool) и если нажата кнопочка добавить новую запись, то делаю флаг в true. А в метод OnActivate поместил проверку этого флага. и если да , то записываю запись которую возвращает в глобальную переменную(которая определена в главном окне) (модальная)форма по закрытии. 
Получается что по закрытию (модальной)формы она возвращает и запись мне нужную и делает активными все окна которые были неактивны. Срабатывает тот метод и происходит запись в базу УРА.
Правдо геморно это все флагами делать.

Если кто знает способ проще то поделитесь  smile 

Автор: ALXP 11.6.2008, 07:46
Рано радовался. То что блокирую окна по открытию какой либо формы это ГУД. то что надо.

 smile а Вот со второй проблемкой  smile не ахти.

Вот вопрос опять. МОЖНО ЛИ ПОСТАВИТЬ ВЫПОЛНЕНИЕ ЧАЙЛДА В ПАУЗУ? как поток , остановил запустил? сделать паузу прям посреди выполнения какой либо функции(метода)?

Автор: ALXP 16.6.2008, 16:09
 smile Все справился с задачей. Просто я почемуто не додумался сразу сделать глобальные переменные и для окон которые у меня типа модальные.

теперь видно какое окно модальное работает и могу сделать проверку, если оно есть, то там где надо, ничего не делается, а просто выходит из функции(метода).

Уря. Теперь у мну с маленьким гемороем есть MDI приложение в котором есть ModalChild  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)