Внешний вид сайта:

Сохранение и вызов дочерней формы MDI из DLL

Давайте создадим одно простое приложение MDI и простой пакет, который будет содержать одну дочернюю форму. Обратите внимание: оба проекта содержатся в одной группе проектов.

Сначала мы создадим приложение типа MDI:

    1. Создайте MDI приложение. Вы можете использовать MDI Application Wizard (File -> New -> Other ->Projects -> MDI Application).
    2. Удостоверьтесь, что свойство FormStyle главной формы установлено в fsMDIForm.
    3. Добавьте главное меню в приложение. Создайте в нем один элемент меню, который будет загражать дочернюю форму MDI из пакета.

Меню на Главной форме для вызова MDI

  1. Удостоверьтесь, что Вы создаете приложение, используя пакеты времени выполнения. Перейдите в 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 формы:

Программа MDI в действии

Одно важное примечание: когда мы используем пакеты времени выполнения, мы должны поставлять пакеты вместе с главным файлом .exe приложения.



Комментарии

Нет комментариев. Ваш будет первым!