tag:blogger.com,1999:blog-5708154677404807103.post7271528091053243985..comments2023-10-31T11:27:33.646+03:00Comments on Delphi Notes: А Вы ещё не используете базовую форму и базовую фрейму в своих Delphi-проектах?Николай Зверевhttp://www.blogger.com/profile/08965247674233981930noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-5708154677404807103.post-86861993119195940762013-01-22T01:08:09.853+04:002013-01-22T01:08:09.853+04:00Дмитрий, спасибо за интересный вопрос. Действитель...<b>Дмитрий</b>, спасибо за интересный вопрос. Действительно, до фреймы сообщение CM_DIALOGKEY может и не дойти. (я этого не знал:)<br /><br />По логике вещей, CM_DIALOGKEY должен бы был попасть сначала на фрейму, если фокус ввода стоит на одном из контролов фреймы. А потом уже на форму.<br />Но в действительности, VCL посылает CM_DIALOGKEY не снизу-вверх, а сверху-вниз, т.е. от формы к дочерним контролам.<br />Однако перед посылкой этого сообщения, VCL посылает ещё одно сообщение - CM_CHILDKEY, вот оно то как раз отсылается в нужном порядке.<br /><br />Откройте Controls.pas и проследите за методами TWinControl.CNKeyDown и TWinControl.CNSysKeyDown, думаю этот код ответит на вопрос.<br /><br />Ещё раз спасибо, я эту замечание включу в одну из следующих заметок.Николай Зверевhttps://www.blogger.com/profile/08965247674233981930noreply@blogger.comtag:blogger.com,1999:blog-5708154677404807103.post-71047335408168209282013-01-21T18:48:02.932+04:002013-01-21T18:48:02.932+04:00PS кстати вопрос как Вы в фрейме
работаете с сообщ...PS кстати вопрос как Вы в фрейме<br />работаете с сообщениями, например такой тривиальный код перехватывающий enter и заставляющий ее работать как Tab (передовать фокус на след.элемент) в форме работает а в фрейме увы нет, т.к обработка сообщений в фрейме не много не такая как в форме. Это существенный подводный камень<br /><br />***<br />procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;<br /> public<br /> { Public declarations }<br /> end;<br /><br />implementation<br /><br />{$R *.dfm}<br /><br />{ TFrShablonFrame }<br /><br />procedure TFrShablonFrame.CMDialogKey(var Message: TCMDialogKey);<br />begin<br /> case Message.CharCode of<br /> VK_RETURN : begin // следующий элемент<br /> Perform(WM_NEXTDLGCTL,0,0);<br /> end;<br /> else<br /> inherited;<br /> end<br />end;<br />***Кузан Дмитрийhttps://www.blogger.com/profile/08411855893021280519noreply@blogger.comtag:blogger.com,1999:blog-5708154677404807103.post-79958009304512126152013-01-17T13:43:01.251+04:002013-01-17T13:43:01.251+04:00Андрей, фрейм можно встроить хоть в форму, хоть в ...<b>Андрей</b>, фрейм можно встроить хоть в форму, хоть в фрейму. Тут ограничений нет, и Delphi тоже позволяет вкладывать фрейму в фрейму. Более того, можно и без фрейм обойтись - ничто не мешает встаривать форму в форму (правда только в рантайме). Поэтому я предпочитаю фреймы - их можно вкладывать друг в друга и в дизайнере.<br /><br />> Не пробовали .. автоматизировать процесс создания..<br />У нас большое кол-во форм/фрейм создаётся автоматически по метаописанию (xml-файл - в нём хранится описание полей таблицы, поля-подстановки и доп. информация для грида/формы редактирования).<br />В теории, я представляю как создавать целые приложения по некоторому описанию, но на практике с этим не сталкивался.<br /><br />> ..фрейм уже легко поместить на базовую форму..<br />Ну фрейм легко поместить на любую форму/фрейму. Но если на форме нет ничего, кроме самой фреймы, то такую форму можно и не создавать в дизайнере, достаточно вызвать что-то типа такого: CreateDialog(AOwner, TFrameClass). Я об этом планирую написать.Николай Зверевhttps://www.blogger.com/profile/08965247674233981930noreply@blogger.comtag:blogger.com,1999:blog-5708154677404807103.post-21642138219242070772013-01-17T10:36:20.379+04:002013-01-17T10:36:20.379+04:00Меня немного смутила фраза "А фрейм уже легко...Меня немного смутила фраза "А фрейм уже легко поместить на базовую форму"... неправильно понял ее смысл. В целом я использую аналогичный подход. <br />Не пробовали пойти дальше и автоматизировать процесс создания таких приложений?<br />ps: В этом плане мне больше нравится Lazarus, т.к. там можно делать вложенные фреймы, что может упростить сопровождение GUI. В Delphi приходится делать компоненты для таких целей..Андрейnoreply@blogger.comtag:blogger.com,1999:blog-5708154677404807103.post-14344192433897894622013-01-16T20:12:21.671+04:002013-01-16T20:12:21.671+04:00>Aleksey Timohin, ... меня не покидает чувство,...>Aleksey Timohin, ... меня не покидает чувство, что в наших проектах много похожего. <br /><br />Подозреваю, что это типичная ситуация для проектов, которые начались в середине 90х и продолжают писаться до сих пор. Менялись только программисты. Кто-то опытнее, кто-то нет. Поэтому такие проекты могут похвастаться отсутствием архитектуры, зоопарком технологий, и обилием копипасты, и кучей ошибок, про которые все знают настолько давно, что уже перестали замечать. Ресурсов нет не только на переписывание всего с нуля, но даже и на полное тестирование.<br /><br /><br />>ВСЕ без исключения формы будут наследоваться от TMyBaseForm, то писать как-то так: (Form1 as TMyBaseForm).DoSomethingBase; быстрее, нежели чем запрашивать интерфейс у объекта... ну мне так показалось.<br />Если все без исключения, то да. <br />Но так не бывает. Т.е. в простых случаях да. Особенно если всё в одном приложении. Но как только начинаешь выносить код из проекта в общие библиотеки, приходится изворачиваться и придумывать как позволить этому коду нормально работать, не перетаскивая туда половину классов проекта. И тут уже приходится думать, либо выносить общий код в базовый класс, либо делать какой-то промежуточный класс Proxy/Connector, либо - интерфейсы. Вот тут кстати очень уместны идеи Dependency Injection/Inversion of Control (Delphi Spring) - и там тоже всё на интерфейсах.<br /><br />К тому же, интерфейсы дают куда больше гибкости. Вместо формы, можно передавать и фрейм и компонент. Главное, чтобы он реализовывал нужный интерфейс.<br /><br />Единственно неприятный момент, это переделывание старых классов (TObject) на работу с интерфейсами (TInterfacedObject). Там можно много граблей словить, если где по ошибке останется обращение к сущности как к объекту. Лучше даже вместо TInterfacedObject использовать TComponent и продолжать самостоятельно следить за памятью.Алексей Тимохинhttps://www.blogger.com/profile/11853041033911520876noreply@blogger.comtag:blogger.com,1999:blog-5708154677404807103.post-53904934090286378672013-01-16T00:32:14.362+04:002013-01-16T00:32:14.362+04:00Спасибо за комментарии.
У меня неделя началась на...Спасибо за комментарии.<br /><br />У меня неделя началась напряжно, но постараюсь что-то начать делать и выкладывать куда-нибудь.<br />Думаю материал предоставить в таком порядке: вот базовая форма, в ней пока ничего нет, вот теперь мы внедрили её в дизайнер Delphi. А потом - наращиваем постепенно функционал базовой формы. А потом и про фрейму.<br /><br /><b>atruhin</b>, банально, да не банально. Почему-то об этом почти никто не пишет, а если пишет - то вскользь. Данный пост можно считать началом мотивации написать что-то конкретное. И, может быть, подстроиться под публику.<br /><br /><b>Андрей</b>, я не совсем понял суть вопроса. Обычно я делаю две вещи: а) фрейму с гридом - для отображения таблиц (список документов, к примеру), б) форму для редактирования конкретной записи. Если это документ, то в этой форме может быть несколько вкладок: "Основные" - шапка документа, "Дополнительные" - табличная часть, которая из себя представляет фрейму с гридом (как в пункте а). Код этой фреймы может вызывать фукнции создания/редактирования записей во внешней форме. Ну типа матрёшки получается. И нюансы надо учитывать, типа делать коммит сразу, или обновлять пакетом, зависит от ситуации, кратко не описать.<br /><br /><b>SnowSonic</b>, спасибо.<br /><br /><b>Aleksey Timohin</b>, читая твои комментарии и посты (и комментарии к постам:), меня не покидает чувство, что в наших проектах много похожего. И набор компонентов, и ведение исходников для двух версий сборок (Delphi7 + Delphi 2010). И базовую форму/фрейму я тоже внедрял чуть ли не первым делом, когда пришёл в компанию, где работаю уже 6 лет.<br />С интерфейсами я не соглашусь. Либо не совсем понял... я тоже думал об интерфейсах, а потом понял, что если у меня ВСЕ без исключения формы будут наследоваться от TMyBaseForm, то писать как-то так: (Form1 as TMyBaseForm).DoSomethingBase; быстрее, нежели чем запрашивать интерфейс у объекта... ну мне так показалось.<br />Кстати в базовой форме у меня есть всё из перечисленного, кроме help-индексов.<br /><br /><b>Кузан Дмитрий</b>, Вы писали о том, что не всё хорошо со шрифтами - в дизайн-тайме одно, в ран-тайме - другое. Я предлагаю такой подход. Пользователь приложения может выбирать шрифт (и его размер) для всего приложения. По умолчанию - подставляется шрифт из темы оформления Windows. Когда форма открывается - загружается её положение на экране, размеры и устанавливается выбранный шрифт для формы. А у всех меток и контролов сказано: ParentFont = True (тем самым мне не надо явно перебирать все контролы и устанавливать у них шрифт).<br />Затем запускается обработчик (Event), в котором программист может дополнительно для нужных меток видоизменить шрифт - сделать его жирным/курсивом, увеличить/уменьшить.<br />Правда в дизайн-тайме, при таком подходе, шрифты менять нельзя. (мне кажется, что это меньшее зло)<br /><br />Ещё я хочу в будущем написать про масштабирование - если у пользователя выбрано в настройках ОС dpi отличное от dpi, в котором "рисовалась" форма, Delphi (по крайней мере старые версии), не корректно масштабирует форму и все контролы в них, может получиться очень криво. На delphikingdom я как-то публиковал свой код в комментариях к http://www.delphikingdom.ru/asp/answer.asp?IDAnswer=48940 от 02-09-2008 04:48<br />ссылка. Там код не претерпел сильных изменений...Николай Зверевhttps://www.blogger.com/profile/08965247674233981930noreply@blogger.comtag:blogger.com,1999:blog-5708154677404807103.post-48288430511769347802013-01-15T20:11:16.025+04:002013-01-15T20:11:16.025+04:00Этот комментарий был удален автором.Кузан Дмитрийhttps://www.blogger.com/profile/08411855893021280519noreply@blogger.comtag:blogger.com,1999:blog-5708154677404807103.post-21410948095177556852013-01-14T17:28:58.860+04:002013-01-14T17:28:58.860+04:00Да. Базовая форма - must have.
Когда я только начи...Да. Базовая форма - must have.<br />Когда я только начинал работать на своей текущей работе, то введение базовых форм было первым с чего я начинал.<br /><br />Правда в моей базовой форме нет никаких GUI-контролов и никакой бизнес логики. И, самое главное, никакого визуального наследования.<br /><br />На данный момент моя базовая форма делает следующее:<br />1) обходит все контролы/компоненты на форме, и унифицирует некоторые свойства<br />2) загружает/сохраняет размеры формы и некоторых свойств<br />3) переводит форму (у меня свой переводчик)<br />4) корректирует шрифты/стили<br />5) выставляет help-index-ы<br />6) объявляет основные методы, которые могут перекрываться в наследниках<br /><br />Причём, почти вся работа делегируется внешнему классу реализующему интерфейс IMyFormProcessor. Типа такого:<br /> ImyControlProcessor = interface(IMyCoreService)<br /> ['{GUID....}']<br /> /// <br /> /// processes all controls and components on form<br /> /// <br /> procedure ProcessForm(aForm:TForm);<br /> /// <br /> /// processes all components on data module<br /> /// <br /> procedure ProcessDataModule(aDataModule:TDataModule);<br /> end;<br /><br /><br />Алексей Тимохинhttps://www.blogger.com/profile/11853041033911520876noreply@blogger.comtag:blogger.com,1999:blog-5708154677404807103.post-5163025478901641202013-01-14T16:21:08.395+04:002013-01-14T16:21:08.395+04:00Прочитал. Жду продолжения. И да, про репозитарий и...Прочитал. Жду продолжения. И да, про репозитарий и его бэкап тоже можно туда включить.SnowSonichttps://www.blogger.com/profile/13703002364212642366noreply@blogger.comtag:blogger.com,1999:blog-5708154677404807103.post-70528930351611536912013-01-14T13:47:36.177+04:002013-01-14T13:47:36.177+04:00Как у вас реализованы документы? Ведь форма докуме...Как у вас реализованы документы? Ведь форма документа может быть с одной стороны формой просмотра табличных частей, с другой стороны - формой редактирования шапки документа.Андрейnoreply@blogger.comtag:blogger.com,1999:blog-5708154677404807103.post-72384349685499688602013-01-14T11:39:54.016+04:002013-01-14T11:39:54.016+04:00То что описано в статье - правильно, но банально. ...То что описано в статье - правильно, но банально. А вот сделать статейку, без лишней воды, про создание визардов для форм, и нюансы помещения форм в репозитарий, было бы не плохоatruhinnoreply@blogger.com