| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Как вы создаете окна в приложении (runtime)? |
| Автор: ama_kid 31.5.2007, 13:39 | ||
| Очень тут меня заинтересовал вопрос, который вроде бы для себя решил уже давно... Ан нет... Суть вопроса в следующем: как вы в своих приложениях создаете необходимые для себя вспомогательные окна в рантайме? Варианты собсно даны выше... Сам я скажу, что когда-то давно, еще на заре изучения мной дельфей, я писал приложение, несложное для меня в данный момент, но тогда опупеть какое сложное. Там было около 10 окошек, которые я создавал с помощью Application.CreateForm в обработчиках меню и кнопок главной формы... И когда я уже его практически закончил, вдруг понадобилось перед вызовом главной формы сделать вызов вспомогательной настроечной формы... Написав что-то типа Application.CreateForm(fmOptions,TfmOptions); перед созданием главной формы я получил то, что и должен был получить - после закрытия того окошка, приложение завершалось. Щас-то я знаю о наличии свойства FMainForm объекта TApplication, а тогда это меня немало удивило... Погуглив проблему, я принял решение создавать его по другому:
И вот не далее как сегодня один из уважаемых мной форумчан по поводу такого кода высказался в отрицательном аспекте. Мне это показалось удивительным, ибо на мой взгляд такой код не несет в себе принципиальных ошибок, использует только разрешенные конструкции и не приводит к утечкам памяти, более того - защищает от них (при корректном использовании). Но мое мнение может быть ошибочным, и не прислушаться к голосу других я не имею права. Что скажет по этому поводу многоуважаемый ALL? P.S. Понимаю, что вопрос не особо принципиальный - поэтому просьба отнестись к данной теме как к разговору об индивидуальных предпочтениях... |
| Автор: Snowy 31.5.2007, 13:53 |
| Первый способ использую для обычных окон. Второй использую исключительно для модальных окошек, которые нужно показать и сразу убить. Добавлено @ 13:56 ama_kid, а кто будет убивать за тебя форму? И зачем пытаться вызывать форму, которая заведомо ещё не создана? |
| Автор: ama_kid 31.5.2007, 13:59 |
| Сама форма себя убивает... Action:=caFree; |
| Автор: Snowy 31.5.2007, 14:12 | ||
| Это не красиво. Код должен быть строгим и логичным, а не вызывать сомнения.
|
| Автор: pseud 31.5.2007, 14:12 | ||||||
| 1. Application.CreateForm(TMainForm, MainForm); использую только для главного окна, иногда для окон, которые присутствуют в приложении в единственном экземпляре и необходимы как и главное коно всегда (например TSettingsForm). И этот код присутствует только в dpr-файле. 2. fmFormTest:=TfmFormTest.Create(Self); Использую во всех остальных случаях. При чем никогда не использую глобальную переменную fmFormTest: TfmFormTest, чтоб не создавать каши, сугубо через локальные перемнные.
иногда даже так
3. Последнее время делаю окна самостоятельные с отображением на таскбаре винды. Т.е. не MDI приложение, не модальное, а что-то типа MSOutlook'а. Работаю через "фабрику форм". Ну и соответсвенно метод фабрики что-то типа:
|
| Автор: ama_kid 31.5.2007, 14:23 |
| Это все прекрасно... Но что делать с формами, которые могут быть в нескольких экземплярах? Или которые должны быть немодальными? А если между формами могут быть взаимосвязи? Понятно, что это - признак плохого проектирования, но я пару раз реально сталкивался с ситуевиной, когда ну никак... вот надо использовать взаимосвязи и все тут... |
| Автор: Bose 31.5.2007, 14:27 | ||||||||
| 1) Application.CreateForm(TfmMain, fmMain); использую в основном для главной формы 2) Все модальные создаю приемерно так:
3) Немодальные формы создаю аналогично
формы освобождаются через
4) Через CreateWindow я ещё не создавал ни одного окна и пока что не планирую. Добавлено через 3 минуты и 28 секунд
В таких случаях лучше делать связи через свойства(properties). Глобальные переменные в таких случаях способны только добавить путаницы. |
| Автор: Snowy 31.5.2007, 14:31 |
| А у таких должен быть Owner. |
| Автор: aktuba 31.5.2007, 14:36 | ||
Или Name, Tag и т.д... |
| Автор: pseud 31.5.2007, 14:43 | ||
Ну и будешь иметь в проекте несколько форм класса TMyForm, но одна из них будет глобальная MyForm, а к остальным будешь обращаться через <поиск окон> . Согласись каша. Никогда не рекомендую делать TMyForm.Create(nil), т.к. если сами ее не удалите, то останется в памяти до перезагрузки винды (IMHO). Указывайте Self, тогда хотя бы объект, который Self позаботиться об уничтожении. Или Application. Как я уже писал - использую "фабрику форм", она и заботиться обо всем. Кстати, если будете указывать Application, то и проще потом искать форму нужную (если не знаете имени), через Application.Components. Если зоздаете Create(MainForm), то через MainForm.Components и т.д. |
| Автор: Snowy 31.5.2007, 14:52 | ||||
pseud, ндя...
Не соглашусь. Help по TScreen табе в руки ;-)
Это плохой способ. Правильный - через TScreen! |
| Автор: Bose 31.5.2007, 15:00 | ||
Я раньше тоже так мучался. Пока не узнал, что через Screen.Forms можно добраться почти до любой формы. Так что... |
| Автор: pseud 31.5.2007, 15:03 | ||
Да я тут погорячился. Согласен. Изучил код своей "фабрики форм" и действительно ее метод GetEntityForm работает со Screen. Давно писал... |
| Автор: ama_kid 31.5.2007, 15:49 |
| Ну это-то не подвергается сомнению Тут я пожалуй добавлю, что в своих приложениях я всегда все за собой подчищаю и все приложения у меня снабжены модулем MemCheck, который матерится ругательными словами, если остался хоть байт упущенной памяти... Пример в топике написан от руки, просто для того, чтобы показать принципиальное понимание мной изначального вопроса, который звучит так - "что в этом неправильного/некорректного/опасного и т.д.?"... |
| Автор: MetalFan 31.5.2007, 15:56 | ||||||
а не проще создать класс-менеджер форм определенного типа, который будет уметь их создавать, убивать, вести их список...
видимо это был я. аналог приведенного в шапке кода
действительно поверг меня в шок... еще бы BSOD вызывали для проверки ;) шучу просто по логике в except секции должен находиться код, который может попытаться проанализировать и исправить возникшие ошибки... он должен выполнять минимум простейших действий, которые сами по себе не могут привести к дальнейшим ошибкам... здесь же получается, что если словили AV, то происходит громадная работа по созданию и отображению формы... которая сама по себе так же может вызвать исключения.... ужас в общем на мой взгляд... в шутку предлагаю модифицировать код:
проблему поможет решить простейший вспомогательный класс-менеджер. ну или на худой случай доп.флаг. но никак не код, который может привести к AV. а может сразу и не привести... |
| Автор: ama_kid 31.5.2007, 17:21 | ||||
|
| Автор: MetalFan 31.5.2007, 22:20 |
потому, что неизвестно, какие данные могут быть повреждены в случае AV. еще раз повторю - "гашение" Access Violation с помощью try..except блока - не есть хорошее решение. ВДУМАЙСЯ в смысл ошибки. AV - это не игрушка. AFAIK в случае возникновения нарушение доступа в драйвере система уходит в bsod... AV - нарушение доступа при чтении или записи в неподготовленную(непредназначенную) для этого область памяти... а что, если часть методов "умершего" экземпляра класса отработает, "успешно" поназапишет чего-нибудь в те части памяти, что используются уже другими экземплярами... и в самом конце вдруг все-таки свалится с AV. ты радостно создаешь новую форму в except блоке... но вдруг у тебя начинают невзначай подглючивать другие формы/классы... или все будет в шоколаде, а приложение у клиента начнет валиться? а? или в след.версии делфи что-то поменяется в методе ShowModal и твое приложение попросту откажется нормально работать... в общем я думаю надо сделать отдельную тему с голосовалкой, в которой спросить, что "корректно ли использовать AV в качестве уведомления об несозданном/убитом экземпляре класса?" я думаю, что ответ "нет" все-таки перевесит... |
| Автор: Igor_thief 18.6.2007, 16:44 |
| Всем очень внимательно надо почитать следующее http://delphi.about.com/od/adptips2005/qt/nilselfapp.htm и ссылки которые есть в статье! Жду комментов статьи? Мне лично не очень понятно почему при создании немодальных форм не стоит передавать в create(self (главную форму)), а лучше передавать Application. Если передать Application, то тогда форму потом не надо освобождать в деструкторе главной формы. Форму уделит Application еще до дестроя главной формы. |