Сохранение и вызов дочерней формы MDI из DLL
Сначала мы создадим приложение типа MDI:
- Создайте MDI приложение. Вы можете использовать MDI Application Wizard (
File -> New -> Other ->Projects -> MDI Application
). - Удостоверьтесь, что свойство FormStyle главной формы установлено в fsMDIForm.
- Добавьте главное меню в приложение. Создайте в нем один элемент меню, который будет загражать дочернюю форму MDI из пакета.
- Удостоверьтесь, что Вы создаете приложение, используя пакеты времени выполнения. Перейдите в
Project -> Options
, выберите вкладку Packages и отметьте флажок Build with run-time packages. Вы должны, по крайней мере, использовать пакеты rtl и vcl.
Перед написанием кода давайте сначала построим пакет и добавим в него одну дочернюю форму MDI.
- Сначала создайте пакет времени выполнения.
- Добавьте объект TForm в пакет. Удостоверьтесь, что свойство FormStyle установлено в fsMDIChild.
- Добавьте одну экспортируемую процедуру, чтобы создавать экземпляр дочерней формы.
procedure TPackageMDIChildForm.FormClose (Sender: TObject; var Action: TCloseAction); begin // так как это MDI ребенок, удостоверьтесь, // что оно закрывается, когда пользователь // щелкает кнопку закрытия окна. Action := caFree; end; procedure ExecuteChild; begin TPackageMDIChildForm.Create(Application); end; exports // ВАЖНО!! Экспортируемое имя // является чувствительным к РЕГИСТРУ ExecuteChild; end.
Перейдем к MDI приложению...
Вот полный код главной MDI формы:
type // сигнатура процедуры "ExecuteChild" // из Package TExecuteChild = procedure; TMainForm = class(TForm) ... private PackageModule : HModule; ExecuteChild : TExecuteChild; procedure PackageLoad; end; var MainForm: TMainForm; implementation {$R *.dfm} procedure TMainForm.PackageLoad; begin // пробуем загрузить пакет // (полагаем, что он находится в той же самой // папке, что и главное приложение .exe) PackageModule := LoadPackage('MDIPackage.bpl'); // если загружено, пытаемся найти процедуру // ExecuteChild if PackageModule <> 0 then try @ExecuteChild := GetProcAddress(PackageModule, 'ExecuteChild'); except // показать сообщение об ошибке, если неудачно ShowMessage ('Package not found'); end; end; // щелчок меню procedure TMainForm.mnuCallFromDLLClick (Sender: TObject); begin // загружаем пакет if PackageModule = 0 then PackageLoad; // если процедура ExecuteChild //была найдена в пакете, вызываем ее if Assigned(ExecuteChild) then ExecuteChild; end; procedure TMainForm.FormDestroy(Sender: TObject); begin // если пакет был загружен, // убедитесь, что освободили ресурсы if PackageModule <> 0 then UnloadPackage(PackageModule); end;
Вышеупомянутый код динамически загружает (процедура PackageLoad) пакет, как необходимо, когда выбран пункт меню и выгружает пакет, когда приложение завершается.
Наконец, во время выполнения, мы имеем дочернюю MDI форму, загруженную из пакета и прекрасно работающую внутри родительской MDI формы:
Одно важное примечание: когда мы используем пакеты времени выполнения, мы должны поставлять пакеты вместе с главным файлом .exe приложения.
Комментарии