Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Немодальное окно диалога!


Автор: Rapalex 14.7.2006, 14:27
Создаю немодальный диалог гдето так:
Код

    m_poDlg = new CDlg;
    m_poDlg->Create(this);  // Это моя функция
    m_poDlg->ShowWindow(SW_SHOWNORMAL);


Удаляю так:
Код

    delete m_poDlg;
    m_poDlg = NULL;


И обработчики OnClose и OnDestroy невызываются.

OnDestroy вызвался только когда при открытом немодальном диалоге я нажал на кнопку закрытия главного окна.

Вообще задачя сохранить положение и состояние окна в реестре (это проблем не вызовет).
 

Автор: Dray 14.7.2006, 14:31
Я точно не помню, но вроде немодальное окно при нажатии его крестика не закрывается, а прячится. 

Автор: Rapalex 14.7.2006, 14:43
Ну на счёт крестика у меня проблемма обычно при нажатии на крестика окна у меня вызывалась функция OnCancel и такой расклад вполне нормален.
А щяс почемуто не вызывается (потом задам такой вопрос если что  smile ), я пока поставил кнопку "Отмена" и в ней нодительскому окну посылаю сообщение о просьбе закрыть немодальный диалог и он зарывается набраным мной кодом (см. выше). 

Автор: vvpC 14.7.2006, 16:00
Цитата(Rapalex @  14.7.2006,  14:27 Найти цитируемый пост)
И обработчики OnClose и OnDestroy невызываются.

это обработчики сообщений винды WM_CLOSE и WM_DESTROY и естественно что они не вызываются - они же не посылаются окну.. Немодальные окна следует уничтожають вызовом DestroyWindow
 

Автор: Rapalex 14.7.2006, 16:10
vvpC, попробывал тогда WM_DESTROY приходит, это хорошо, спасибо, а другие альтернативы есть? 

Автор: Earnest 14.7.2006, 16:53
WM_DESTROY всегда посылается перед уничтожением окна. Только вот, если просто делать delete, происходит это в деструкторе CWnd, когда от твоего класса рожки да ножки остались.
Так что vvpC прав: нужно явно вызывать DestroyWindow. Кстати, если бы ты внимательно смотрел сообщения в output-окне, то увидел бы предупреждение, что-то вроде: "Караул! Вызов DestroyWindow в деструкторе CWnd!". Чтобы не писать каждый раз DestroyWindow, можно делать это в деструкторе своего класса. Тогда можно просто писать delete pWnd. 

Автор: Любитель 14.7.2006, 23:31
 smile 
Что и говорить - глупое проектирование MFC. Конструкторы не создают окошки, деструкторы не разрушают  smile 
 

Автор: Dray 15.7.2006, 02:32
Цитата(Любитель @  14.7.2006,  23:31 Найти цитируемый пост)
деструкторы не разрушают

глупо...
Цитата(Любитель @  14.7.2006,  23:31 Найти цитируемый пост)
Конструкторы не создают окошки

не глупо! 

Автор: Earnest 17.7.2006, 08:16
Цитата(Любитель @  15.7.2006,  00:31 Найти цитируемый пост)
Что и говорить - глупое проектирование MFC. Конструкторы не создают окошки, деструкторы не разрушают  

Напиши свой деструктор, который будет разрушать окно. Почему стандартный деструктор C++ должен разрушать какие-то окна? И MFC тут непричем: ее сложно назвать идеалом, но в данном случае - это твоя личная глупость. Нужно просто изучать матчасть. Или писАть на бейсике.
 

Автор: Rapalex 17.7.2006, 11:47
Не надо ссорится.  smile 

Я (с вашей помощью пришол к выводу) в начяле вызывааю функцию DestroyWindow а потом делаю delete указалелю. Теперь принажатии на крестик приходит событие OnClose и тоже самое делаю при нажатии не кнопку "Отмена".

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

Автор: Earnest 17.7.2006, 12:47
Rapalex, внимательнее читай: добавь вызов DestroyWindow в деструктор своего класса окна, и пиши только одну строчку (delete pWnd). 
Есть еще MFC-альтернатива: делать delete this в обработчике PostNcDestroy, как делают многие MFC-классы. Тогда тоже можно будет писать одну строчку (DestroyWindow). Но это не очень хорошо с точки зрения ООП (где-то хранящийся указатель может стал недействительным без видимых причин). Впрочем, раз MFC так делает, то не стоит пытаться быть святее папы римского. Все зависит от контекста: иногда это вполне удобно. 

Автор: Любитель 17.7.2006, 22:14
Цитата(Earnest @  17.7.2006,  08:16 Найти цитируемый пост)
 Почему стандартный деструктор C++ должен разрушать какие-то окна?

Потому что разработчики MFC должны были это предусмотреть ;)

Цитата(Dray @  15.7.2006,  02:32 Найти цитируемый пост)
не глупо!

ПОЧЕМУ??? 

Автор: Dray 17.7.2006, 23:12
Цитата(Любитель @  17.7.2006,  22:14 Найти цитируемый пост)
ПОЧЕМУ??? 

Вдруг надо в экземпляр производнова от окна класса записать какие-нибудь настройки и только потом создать окно. 

Автор: Earnest 19.7.2006, 06:47
Цитата(Любитель @  17.7.2006,  23:14 Найти цитируемый пост)
Потому что разработчики MFC должны были это предусмотреть ;)

А каким образом компилятор может узнать, что твой класс - это окно, которое нужно разрушить? А может, это база данных, от которой надо отсоединиться? А может - словарь, который надо очистить? Они и предусмотрели: написали в документации и поставили в деструктор CWnd предупреждение. 

Автор: Любитель 22.7.2006, 00:47
Цитата

Вдруг надо в экземпляр производнова от окна класса записать какие-нибудь настройки и только потом создать окно

Ну и пусть вызываются всякие виртуальные функции вроде PreCreateWindow. smile 

Цитата

А каким образом компилятор может узнать, что твой класс - это окно, которое нужно разрушить? А может, это база данных, от которой надо отсоединиться? А может - словарь, который надо очистить? Они и предусмотрели: написали в документации и поставили в деструктор CWnd предупреждение

Млин, ну я же не совсем дурак... Я имею в виду, что это должен делать класс CWnd => и все наследованные от него (хотя конструктор наследуемого класса можно конечно и игнорить). Во всех библиотеках делается именно так, по моему, достаточно разумно. Ещё лучше пусть будет метод Create. Безаргументным конструктором он не вызывается, но есть конструктор с аргументами автоматом вызывающий Create. Аналогично можно разрушать окошко когда хотим, но если мы этого не сделали, то пусть деструктор будет добр поработать за нас. Вспомните классы std::fstream - мы можем сразу открыть файл, а можем и не открывать; можем закрыть, если нужно, а можем смело забить на это. Таким образом класс действительно инкапсулирует в себе все нужные операции. MFC-шные классы окошек спроектированы так, будто окошко существует независимо оот объекта. Допустим оно действительно может существовать независимо, но это совсем другая история... Проектируя библиотеку ГУИ надо было позаблтиться о единстве объекта и физического окошка. 

Автор: Dray 22.7.2006, 01:16
Любитель, На самом деле можно найти пример когда кто-нибудь бы пострадал от создания окон в конструкторах. Объект окна создается, но прежде чем создать окно ждет каких-либо данных.
А вот от того как сделано вряд ли кто-нибудь сильно страдает. 

Автор: Earnest 22.7.2006, 08:07
Цитата(Любитель @  22.7.2006,  01:47 Найти цитируемый пост)
Я имею в виду, что это должен делать класс CWnd => и все наследованные от него

Так он это и делает (деструктор CWnd разрушает окно). Но ведь к этому моменту твой класс уже разрушен - сообщение WM_DESTROY посылается, но твоего объекта уже нет, и приходит оно базовому классу, о чем и предупреждается. Это уже С++ - из конструктора-деструктора нельзя вызывать виртуальные функции. Т.е. можно, но получишь не то, что ожидаешь...
Что касается класса fstreem - это совсем другое дело. Ты часто создаешь производные от него классы? Или все таки пользуешься именно fstream? 

Цитата(Любитель @  22.7.2006,  01:47 Найти цитируемый пост)
Проектируя библиотеку ГУИ надо было позаблтиться о единстве объекта и физического окошка.  

Физическое окошко находится вне компетенции MFC. MFC не является шедевром дизайна (вспомните сколько ей лет), она всего лишь тонкая оболочка над WinAPI, чем и ценна, с моей точки зрения.  

Автор: Dray 22.7.2006, 15:37
Цитата(Earnest @  22.7.2006,  08:07 Найти цитируемый пост)
она всего лишь тонкая оболочка над WinAPI, чем и ценна

Вот, да это основное великолепие. Именно этого не могут понять люди переходящие с VCL, за сложностью не видят гибкости. 

Автор: Любитель 23.7.2006, 20:49
Цитата(Dray @  22.7.2006,  01:16 Найти цитируемый пост)
юбитель, На самом деле можно найти пример когда кто-нибудь бы пострадал от создания окон в конструкторах. Объект окна создается, но прежде чем создать окно ждет каких-либо данных.А вот от того как сделано вряд ли кто-нибудь сильно страдает. 

Попробуй найти! В конце концов можно создавать объекты на хипе.

Цитата(Earnest @  22.7.2006,  08:07 Найти цитируемый пост)
Физическое окошко находится вне компетенции MFC. MFC не является шедевром дизайна (вспомните сколько ей лет), она всего лишь тонкая оболочка над WinAPI, чем и ценна, с моей точки зрения.  

Согласен. Из-за привязанности к WinAPI в MFC получается на мой взгляд слабая привязанность к нормальной объектно-ориентированной модели. Это не есть плохо, но есть неприятно...
 

Автор: lemax 2.1.2009, 13:46
НАПОМИНАНИЕ.
В ДИСТРУКТОРЕ ЗАПРЕЩЕН КОД КОТОРЫЙ МОЖЕТ СОЗДАВАТЬ ИСКЛЮЧЕНИЯ

Почему:
При исключении начинает высвобождаться память. А так как память объекта на который указат this , еще не высвобождено, то повторно будет вызываться диструктор (*this).
Может зациклит не по детски.

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

Автор: Earnest 6.1.2009, 17:57
lemax, это в том смысле, что ты еще в июле 2006 впал в анабиоз, и вот только очнулся???
Только дата поста может извинить его ... гм... глубокомыслие smile 

Автор: lemax 8.1.2009, 11:35
Цитата(Earnest @ 6.1.2009,  17:57)
lemax, это в том смысле, что ты еще в июле 2006 впал в анабиоз, и вот только очнулся???
Только дата поста может извинить его ... гм... глубокомыслие smile

А при чем здесь дато поста? Когда я пытаюсь найти решение своей проблемы, то мне по барабану на дату, когда ее решили.

А в этой теме есть кадры, которые порываются возложить на диструктор обязанности, которые ему не свойственны, и это очень опасно. Надо же образумить чуваков. Мало ли кто еще (как я) зайдет сюда лет через 200.

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