Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Visual C++/MFC/WTL > Немодальное окно диалога! |
Автор: Rapalex 14.7.2006, 14:27 | ||||
Создаю немодальный диалог гдето так:
Удаляю так:
И обработчики OnClose и OnDestroy невызываются. OnDestroy вызвался только когда при открытом немодальном диалоге я нажал на кнопку закрытия главного окна. Вообще задачя сохранить положение и состояние окна в реестре (это проблем не вызовет). |
Автор: Dray 14.7.2006, 14:31 |
Я точно не помню, но вроде немодальное окно при нажатии его крестика не закрывается, а прячится. |
Автор: Rapalex 14.7.2006, 14:43 |
Ну на счёт крестика у меня проблемма обычно при нажатии на крестика окна у меня вызывалась функция OnCancel и такой расклад вполне нормален. А щяс почемуто не вызывается (потом задам такой вопрос если что ![]() |
Автор: vvpC 14.7.2006, 16:00 |
это обработчики сообщений винды 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 |
![]() Что и говорить - глупое проектирование MFC. Конструкторы не создают окошки, деструкторы не разрушают ![]() |
Автор: Dray 15.7.2006, 02:32 |
глупо... не глупо! |
Автор: Rapalex 17.7.2006, 11:47 |
Не надо ссорится. ![]() Я (с вашей помощью пришол к выводу) в начяле вызывааю функцию 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 | ||
Потому что разработчики MFC должны были это предусмотреть ;) ПОЧЕМУ??? |
Автор: Dray 17.7.2006, 23:12 |
Вдруг надо в экземпляр производнова от окна класса записать какие-нибудь настройки и только потом создать окно. |
Автор: Earnest 19.7.2006, 06:47 |
А каким образом компилятор может узнать, что твой класс - это окно, которое нужно разрушить? А может, это база данных, от которой надо отсоединиться? А может - словарь, который надо очистить? Они и предусмотрели: написали в документации и поставили в деструктор CWnd предупреждение. |
Автор: Любитель 22.7.2006, 00:47 | ||||
Ну и пусть вызываются всякие виртуальные функции вроде PreCreateWindow. ![]()
Млин, ну я же не совсем дурак... Я имею в виду, что это должен делать класс CWnd => и все наследованные от него (хотя конструктор наследуемого класса можно конечно и игнорить). Во всех библиотеках делается именно так, по моему, достаточно разумно. Ещё лучше пусть будет метод Create. Безаргументным конструктором он не вызывается, но есть конструктор с аргументами автоматом вызывающий Create. Аналогично можно разрушать окошко когда хотим, но если мы этого не сделали, то пусть деструктор будет добр поработать за нас. Вспомните классы std::fstream - мы можем сразу открыть файл, а можем и не открывать; можем закрыть, если нужно, а можем смело забить на это. Таким образом класс действительно инкапсулирует в себе все нужные операции. MFC-шные классы окошек спроектированы так, будто окошко существует независимо оот объекта. Допустим оно действительно может существовать независимо, но это совсем другая история... Проектируя библиотеку ГУИ надо было позаблтиться о единстве объекта и физического окошка. |
Автор: Dray 22.7.2006, 01:16 |
Любитель, На самом деле можно найти пример когда кто-нибудь бы пострадал от создания окон в конструкторах. Объект окна создается, но прежде чем создать окно ждет каких-либо данных. А вот от того как сделано вряд ли кто-нибудь сильно страдает. |
Автор: Earnest 22.7.2006, 08:07 | ||||
Так он это и делает (деструктор CWnd разрушает окно). Но ведь к этому моменту твой класс уже разрушен - сообщение WM_DESTROY посылается, но твоего объекта уже нет, и приходит оно базовому классу, о чем и предупреждается. Это уже С++ - из конструктора-деструктора нельзя вызывать виртуальные функции. Т.е. можно, но получишь не то, что ожидаешь... Что касается класса fstreem - это совсем другое дело. Ты часто создаешь производные от него классы? Или все таки пользуешься именно fstream?
Физическое окошко находится вне компетенции MFC. MFC не является шедевром дизайна (вспомните сколько ей лет), она всего лишь тонкая оболочка над WinAPI, чем и ценна, с моей точки зрения. |
Автор: Dray 22.7.2006, 15:37 |
Вот, да это основное великолепие. Именно этого не могут понять люди переходящие с VCL, за сложностью не видят гибкости. |
Автор: Любитель 23.7.2006, 20:49 | ||||
Попробуй найти! В конце концов можно создавать объекты на хипе.
Согласен. Из-за привязанности к WinAPI в MFC получается на мой взгляд слабая привязанность к нормальной объектно-ориентированной модели. Это не есть плохо, но есть неприятно... |
Автор: lemax 2.1.2009, 13:46 |
НАПОМИНАНИЕ. В ДИСТРУКТОРЕ ЗАПРЕЩЕН КОД КОТОРЫЙ МОЖЕТ СОЗДАВАТЬ ИСКЛЮЧЕНИЯ Почему: При исключении начинает высвобождаться память. А так как память объекта на который указат this , еще не высвобождено, то повторно будет вызываться диструктор (*this). Может зациклит не по детски. В конструкторе тоже не стоит использовать код, бросающий исключения |
Автор: Earnest 6.1.2009, 17:57 |
lemax, это в том смысле, что ты еще в июле 2006 впал в анабиоз, и вот только очнулся??? Только дата поста может извинить его ... гм... глубокомыслие ![]() |
Автор: lemax 8.1.2009, 11:35 | ||
А при чем здесь дато поста? Когда я пытаюсь найти решение своей проблемы, то мне по барабану на дату, когда ее решили. А в этой теме есть кадры, которые порываются возложить на диструктор обязанности, которые ему не свойственны, и это очень опасно. Надо же образумить чуваков. Мало ли кто еще (как я) зайдет сюда лет через 200. |