Суть заметки в двух словах: организация dpr-файла и вынос мозга инициализации приложения в DataModule.
Эту заметку не стоит рассматривать как единственно верный вариант. Просто я хочу поделиться опытом. Я расскажу, как делаю я и как это делается у нас. Ничего особенного. Но самостоятельно к этому приходят не все и не сразу. А делаю я так, потому что описанный ниже подход облегчает сопровождение проектов (особенно, когда их несколько, и все они потихоньку разрастаются).
Итак, первое, что я всегда делаю после установки Delphi – снимаю флаг с пункта меню Auto create forms & data modules. Этот флаг по умолчанию установлен, наверное, как дань традиции. Однако сразу создавать все формы в приложении не есть хорошо. Я считаю, что ресурсы у системы надо выделять по мере необходимости (ну за исключением совсем простых, либо совсем особых случаев).
Затем устанавливаем пакет BaseForms (для VCL). Или не устанавливаем, но я на BaseForms ещё буду ссылаться.
Далее создаём новый проект. И сразу же удаляем только что созданную форму, т.к. она не базовая. Затем создаём датамодуль, форму которого называем DM, а файл – DataModule.pas. Это будет модуль, координирующий инициализацию и завершение приложения. Теперь можно всё сохранить и дать название нашему приложению. К примеру: MyTestProject. (Да, и добавим ещё AppExt в dpr-файл). Теперь dpr-файл выглядит вот так:
program MyTestProject; uses AppExt, Forms, DataModule in 'DataModule.pas' {DM: TBaseDataModule}; {$R *.res} begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TDM, DM); Application.Run; end.
Тут хочу акцентировать внимание на том, что в dpr-файле создаётся только DataModule (DM). Остальные формы будут добавляться в uses, но секция begin – end. затрагиваться не будет.
И вот всё самое интересное выносим в DataModule.OnCreate. Это могут быть: SplashScreen, логгер критических ошибок, чтение пользовательских предпочтений, словарь данных, текстовые ресурсы. Здесь же спрашиваем логин/пароль у пользователя, если мы работаем с БД (и если без подключения к БД работать нет смысла). У меня всё это выглядит примерно так:
procedure TAppDataModule.DataModuleCreate(Sender: TObject); begin CheckParamStr; PrepareGlobalConfig; {$ifdef use_mui} PrepareLanguages; {$endif} CreateSplashScreen; try ShowSplashScreen; PrepareHelp; ProgressMsg(stInitialization); PrepareConnection; ProgressMsg(stDictionary); PrepareDictionary; ProgressMsg(stAuthentication); if QueryConnect then try AfterConnected; ProgressMsg(stLoading); PrepareDataModules; PrepareMainForm; except Connection.Disconnect; raise; end; finally FreeSplashScreen; end; end;
Пару комментариев к коду. Сначала показываем SplashScreen, чтобы пользователю не было “скучно”. Затем загружаем всё необходимое для работы приложения. QueryConnect в наших приложениях – это отображение полей ввода для пароля/логина к БД прям в окне SplashScreen и запуск цикла с Application.ProcessMessages, чтобы пользователь мог их ввести; плюс N-попыток подключения к БД. Если подключиться не удалось – QueryConnect вернёт False и произойдёт нормальное завершение приложения (т.к. Application.MainForm ещё не определён).
PrepareDataModules – создаёт остальные датамодули. У нас их несколько – один хранит в себе ImageList’ы (т.е. все пиктограммы для тулбаров и меню собраны в одном месте, это очень удобно), другой содержит компоненты FastReport’а и механизмы для работы с отчётами, третий – датасеты (ну у нас не датасеты и генерируется оно автоматически, но инициализировать это тоже надо).
PrepareMainForm – создаёт главную форму приложения, ей будет передано управление в Application.Run сразу после выхода из приведённого обработчика.
Ещё Вы можете обратить внимание на то, что датамодуль у нас называется DM, а код выше я (намеренно) представил от имени TAppDataModule (вместо TDM). Это ещё одно упрощение для сопровождения – TAppDataModule содержит набор виртуальных методов (типа AfterConnected и PrepareMainForm) и является общим для группы проектов. А для конкретного проекта (типа MyTestProject) TDM наследуется от TAppDataModule и содержит уникальные для приложения вещи. (К слову сказать, TAppDataModule и остальные датамодули у нас наследуется от базового датамодуля, по аналогии с формами.)
И конечно же есть обработчик DataModule.OnDestroy, я его приводить не буду – понятно, что там содержится код для корректного отключения от БД (если ещё не отключились), сохранение настроек (которые ещё не сохранились), освобождение памяти (которая ещё не освободилась).
5 коммент.:
Мне нравится... Я сам - "примерно так" делаю...
Думаю, что может пригодиться:
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1424
Николай, мне почему-то кажется, что ссылка должна вам понравиться:
http://18delphi.blogspot.ru/2013/10/vcm-mvc.html
Спасибо за ссылки. Обе статьи читал - выходил поиском, когда лепил свои базовые формы и писал MDI-приложение (где-то в 2007м году).
Какой-то отпечаток в сознании они безусловно оставили...
Я без главной формы вообще обхожусь. Это связано со старыми приложениями, написанным как куча независимых модальных окон, появляющихся на фоне не нужного окна с меню.
Просто весь код пишу в дпр файле. Как то так:
Application.Initialize;
Application.Title := 'Title ';
TSomeFrom.show_form;
Это упрощено - если в приложении одна форма. Иначе запускается синглтон который управляет окнами.
Отправить комментарий