Шаг 310.
Создание внутрипроцессных серверов автоматизации. Создание и использование DLL. Модальные формы в DLL (статическое подключение)

    На этом шаге мы рассмотрим особенности использования модальных форм, расположенных в 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 можно взять здесь (433,7 Кб).

    На следующем шаге мы рассмотрим особенности при динамическом подключении DLL.




Предыдущий шаг Содержание Следующий шаг