Delphi XE4: закрытие внутренней формы пакета приводит к прекращению работы приложения
У меня есть пакет test.bpl в моем приложении, и он имеет форму с именем myPackageForm. после загрузки моего пакета, когда я хочу закрыть myPackageForm, приложение завершает работу.
Инициализация основного проекта:
Application.Initialize;
Application.CreateForm(TMainForm,MainForm);
Application.Run;
MainForm FormCreate:
aPackage := LoadPackage('my bpl path'+test.bpl);
@P_ItemClick := GetProcAddress(aPackage,'ItemClickExcecute');
MainForm ButtonClick:
P_ItemClick(Sender);
testPackage CommandsUnit:
Procedure ItemClickExecute(Sender : TObject)
begin
TmyPackageForm.ShowForm();
end;
exports
ItemClickExecute;
end.
myPackagForm имеет процедуру класса, чтобы показать это:
Class Procedure TmyPackagForm.ShowForm;
begin
if not Assigned(myPackagForm)
myPackagForm := Application.CreateForm(TmyPackagForm ,myPackagForm );
myPackagForm.Show;
end;
А в OnClose Процедура имеет:
Release;
В качестве решения я пробую другую команду:
myPackagForm := TmyPackagForm.Create(Application);
для создания myPackagForm;
Кто-нибудь может знать, что произошло в Delphi XE4 с командой CreateForm для пакетов?
2 ответа
Сэр Руфо получил основы. Первая форма, созданная с помощью вызова CreateForm
становится основной формой. Когда основная форма закрывается, приложение закрывается.
Теперь вы показали два звонка CreateForm
, Один в хост-приложении и один в вашем динамически загруженном пакете. И кажется очевидным, что первым запустится приложение хоста. Итак, как форма в пакете может сбить приложение? Что ж, это может произойти, как сказал сэр Руфо, только если в вашем процессе есть два экземпляра приложения.
Итак, следующий вопрос: как в вашем процессе может быть два экземпляра приложения? Этого не должно быть. Весь смысл пакетов состоит в том, чтобы позволить модулям Delphi быть разделенными между различными модулями. Если вы правильно создали приложение, то у вас будет только один экземпляр TApplication
это разделяется между исполняемым файлом хоста и всеми вашими пакетами.
Итак, единственный разумный вывод, который нужно сделать, - это то, что один из ваших модулей не построен с использованием пакетов времени выполнения. Например, возможно, хост-приложение включает RTL/VCL, статически связанный внутри исполняемого файла. А ваши пакеты ссылаются на пакеты времени выполнения RTL/VCL. Или, возможно, это динамически загруженный пакет, который включает статически связанный RTL/VCL. Хотя IIRC, компилятор предотвращает это.
Что бы ни пошло не так, решение состоит в том, что все ваши модули должны быть собраны с использованием пакетов времени выполнения. Все библиотеки RTL / VCL должны быть связаны через пакеты времени выполнения и не должны быть связаны статически.
Итак, замена Application.CreateForm
с TMyPackageForm.Create
просто подавляет более широкую проблему. Очень важно, чтобы в вашем приложении был только один экземпляр RTL/VCL. Добейтесь этого, используя пакеты времени выполнения во всех ваших модулях.
Это, безусловно, тот случай, когда TMyPackageForm.Create
это правильный способ создать форму в вашем пакете. Я использую только Application.CreateForm
для основной формы. Я никогда не использую это где-нибудь еще. Но не пытайтесь решить вашу непосредственную проблему исключительно, удалив Application.CreateForm
из вашей посылки. Исправьте ссылку на RTL/VCL.
TApplication.CreateForm
не только создать форму, но и сделать первую форму, созданную этим методом, TApplication.MainForm
,
А закрытие MainForm приводит к закрытию приложения.
ОБНОВИТЬ
У вас 2 TApplication
экземпляры внутри вашего приложения.
- ваше нормальное приложение
- внутри BPL
Таким образом, ваша форма внутри BPL станет главной формой вашего BPL. Application
и закрытие этой формы будет выполнять PostQuitMessage(0)
в контексте вашего основного процесса приложения, и это заставляет все приложение выйти.