Сохранение и вызов дочерней формы 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 приложения.
Комментарии