13.5. ВКЛЮЧЕНИЕ В БИБЛИОТЕКУ ФОРМ

Несмотря на то, что DLL не имеет собственной формы, с ее помощью можно вызывать формы из связанных с библиотекой модулей. Для этого в библиотеке используется ссылка uses на связанные модули-формы и объявляются экспортируемые из DLL подпрограммы, в которых реализуется вызов соответствующих форм.

В следующем примере иллюстрируется техника включения в DLL формы и использования ее в вызывающей программе.

Текст DLL

library DLLWithform;

uses

SysUtils,

Classes,

DLLformU in 'DLLformU.pas' {DLLform};

{$R *.RES}

exports

ShowModalform, Showform, Freeform;

begin

end.

Текст формы в DLL

 

unit DLLformU;

interface

uses

Windows, Messages, SysUtils,Classes, Graphics,

Controls, forms, Dialogs, StdCtrls, Buttons;

type

TDLLform = class (Tform) BitBtnl: TBitBtn;

BitBtn2: TBitBtn;

procedure formClose(Sender: TObject;

var Action: TCloseAction);

private

{ Private declarations }

Callform: THandle; //Дескриптор вызывающей формы

public

{ Public declarations }

end;

// Объявление экспортируемых подпрограмм

function ShowModalform: Integer;

procedure Showform(aHandle: THandle);

procedure Freeform;

var

DLLform: TDLLform;

implementation

{$R *.DFM}

function ShowModalform: Integer;

// Модальный вызов

begin

Dllform := TDllform.Create(Application);

Result := DLLform.ShowModal;

DLLform.Free;

end;

procedure Showform(Appl, form: THandle);

// Немодальный вызов

begin

Application.Handle := Appl; // Замена объекта

Application Dllform := TDllform.Create(Application);

// Запоминаем дескриптор вызывающего окна для посылки

// ему сообщения о закрытии

Callform := form;

DLLform.Show

end;

procedure Freeform;

// Уничтожение формы

begin

DLLform.Free

end;

procedure TDLLform.formClose(Sender: TObject;

var Action: TCloseAction);

begin

if Callform>O then

SendMessage(Callform, wm_User, 0, 0)

end;

end.

Текст вызывающей программы

unit TestMainU;

interface

uses

Windows, Messages, SysUtils, Classes,

Graphics, Controls, forms, Dialogs, StdCtrls;

type

TTestMain = class (Tform)

Buttoni: TButton; // Открыть в модальном режиме

Button2: TButton; // Открыть в немодальном режиме

Button3: TButton; // Закрыть окно

Label I: TLabel;

procedure ButtonlClick(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure ButtonSClick(Sender: TObject);

private

{ Private declarations } public

{ Public declarations }

procedure WMUser(var Msg: TMessage);

message WM_USER;

end;

var

TestMain: TTestMain;

implementation

{$R *.DFM}

function ShowModalform: Integer;

External 'DLLWithform';

procedure Showform(Appl, form: THandle);

External ' DLLWithform' ;

procedure Freeform;

External 'DLLWithform';

procedure TTestMain.ButtonlClick(Sender: TObject);

// Модальный вызов

begin

Button2.Enabled := False;

label1.Caption := 'ModalResult = '+IntToStr(ShowModalform);

label1.Show; // Показываем результат вызова

Button2.Enabled := True

end;

procedure TTestMain.Button2Click(Sender: TObject);

// Немодальный вызов

begin

Buttoni.Enabled :== False;

Button2.Enabled := False;

Buttons.Enabled := True; label 1.Hide;

Showform(Application.Handle, Self.Handle) ;

end;

procedure TTestMain.Button3Click(Sender: TObject);

// Закрыть форму

begin

Freeform;

Button1.Enabled := True;

Button2.Enabled := True;

Button3.Enabled := False/end;

procedure TTestMain.WMUser(var Msg: TMessage) ;

// Сообщение из формы DLL о ее закрытии

begin

Buttons.Click

end;

end.

Модуль формы DLLform, помещенной в DLL, ссылается на стандартный модуль forms и таким образом получает свой глобальный объект Application, который ничего “не знает” о глобальном объекте вызывающей программы (см. гл. 21). В режиме модального вызова это не имеет особого значения, т. к. модальное окно блокирует работу вызывающей программы. В режиме немодального вызова следует синхронизовать действия объектов, в противном случае минимизация главного окна, например, не приведет к минимизации окна DLL. Синхронизация достигается тем, что дескриптор объекта Application DLL заменяется на соответствующий дескриптор вызывающей программы.

При показе формы в немодальном режиме она может быть закрыта щелчком по собственной системной кнопке закрыть. В этом случае она должна каким-то образом известить вызывающую программу об этом событии. Для этого используется стандартный механизм посылки вызывающей форме Windows-сообщения. Сообщение должно иметь адрес, в роли которого используется дескриптор окна, получающего это сообщение. Вот почему вторым параметром обращения к функции Showform в DLL передается и в поле Callform: запоминается дескриптор вызывающего окна. Обработчик события enclose формы проверяет это поле и, если оно определено, посылает вызывающему окну сообщение с индексом wm_user. В вызывающей программе предусмотрен обработчик этого сообщения, в котором реализуются необходимые действия.