На этом шаге мы рассмотрим особенности использования модальных форм, расположенных в DLL, при статическом подключении.
В DLL можно не только выполнять вычисления, но и показывать формы, например диалоговые окна. Для этого следует открыть проект реализации DLL, создать модуль с формой и поместить на нее необходимые элементы управления вместе с обработчиками событий. Далее следует создать экспортируемую функцию, которая выведет диалоговое окно:
var C:array[0..1000] of char; function ExecDialog(AppHandle:THandle; var PictName:PChar):boolean; stdcall; export; var FDialog:TForm1; begin FDialog := nil; PictName := nil; Result := False; //Application.Handle := AppHandle; //В этом случае на панели задач появятся две кнопки try FDialog:=TForm1.Create(Application); if FDialog.ShowModal=mrOK then begin FillMemory(@C[0],1000,0); if length(FDialog.OpenPictureDialog1.FileName)>0 then StrPCopy(C,FDialog.OpenPictureDialog1.FileName); PictName := @C[0]; Result := True; end; FDialog.Release; FDialog := nil; {При динамической загрузке следует использовать метод Free вместо Release!} except On E:exception do begin ShowMessage(E.Message); if Assigned(FDialog) then FDialog.Release; end; end; end;
Данный код вызова диалогового окна следует применять только при статической загрузке DLL. При реализации диалогового окна в DLL следует учитывать, что в отличие от приложений формы в DLL не могут создаваться одновременно с запуском DLL (в случае приложений для этого достаточно установки флажка Auto-Create Form на вкладке Forms диалогового окна, открываемого командой Project | Options). Поэтому форму необходимо создавать динамически, вызывая ее конструктор Create из кода. Соответственно, перед выходом из процедуры, вызывающей форму, необходимо вызвать ее деструктор (в данном примере - FDialog.Release). Далее, следует учитывать, что в DLL создается объект типа TApplication. Поскольку само приложение тоже имеет данный объект, то, если не принимать никаких мер, на экране в панели задач появляются две кнопки - одна для приложения и другая для DLL, создающей диалоговое окно. Это иллюстрирует рисунок 1.
Рис.1. Появление двух кнопок на панели задач при вызове диалогового окна из DLL
При щелчке мышью на кнопке приложения оно активируется, главная форма появляется на экране, но доступ к элементам управления главной формы получить нельзя. Очевидно, такое поведение является некорректным. Поэтому в качестве параметра функции в библиотеке, создающей диалоговое окно, необходимо использовать ссылку на объект TApplication приложения (точнее, на его свойство Handle). Посредством следующего присвоения в DLL уничтожается объект TApplication, и приложение начинает поддерживать рассылку сообщений операционной системы элементам управления, созданным в DLL:
Application.Handle := AppHandle;
При этом на панели задач остается одна кнопка приложения, что вполне корректно. Типичный пример кода основного приложения, вызывающего диалоговое окно из DLL, приведен ниже:
function ExecDialog(AppHandle: THandle; var PictName: PChar): Boolean; stdcall; external 'FirstLib.dll' name 'ExecDialog'; procedure TForm1.Button1Click(Sender: TObject); var P: PChar; S: String; begin if ExecDialog(Application.Handle, P) then begin S := P; Caption := S; end; end;
На следующем шаге мы рассмотрим особенности при динамическом подключении DLL.