Implementation

Обрати внимание, что первое описание процедуры я написал не в разделе type, а до него:

procedure ShowAbout(Handle: THandle)stdcall;

Это не является ошибкой, и ты можешь выбрать любой из этих способов. Я чаще всего объявляю внешние процедуры до раздела var, чтобы их потом легче было найти. Теперь ставим на форму кнопочку и пишем по её событию OnClick следующий код:

procedure TForm1.Button1Click(Sender: TObject); begin ShowAbout(Handle); end;

Запусти пример и убедись в том, что пример работает корректно. Как видишь окно не так уж трудно засунуть в библиотеку, и в нём могут быть свои события и свои процедуры и функции. К тому же окно может создавать дочерние окна по отношению к себе и той же динамической библиотеки.

На компакт диске, в директорииПримерыГлава 18Formты можешь увидеть пример этой программы.

 

18.5. Немодальные окна в динамических библиотеках.

предыдущем примере я поместил в библиотеку модальное окно. А что, если тебе понадобиться показать немодальное окно? Ведь мы показываем окно и

по его закрытию должны освободить память. А как узнать, что окно закрыто? Некоторые ленятся и просто не освобождают память, выделенную под окно. Но это не правильно и просто глупо, потому что показать немодальное окно не намного сложнее.

Давай откроем предыдущий пример и подкорректируем его. Для начала нужно добавить одну экспортную процедуру FreeAbout с индексом 11. Теперь у нас будет экспортироваться две процедуры:

exports ShowAbout index 10; exports FreeAbout index 11;

Теперь переходим в модуль Unit1, где у нас находиться форма динамической библиотеки. Процедуру ShowAbout я превращаю в функцию, которая будет возвращать значение типа LongInt. В качестве возвращаемого значения будет идентификатор окна, по которому мы потом будет его закрывать.

Ещё нужно добавить процедуру FreeAbout с одним параметром типа LongInt.

function ShowAbout(Handle: THandle):LongInt;export;stdcall; procedure FreeAbout(FormRef: LongInt);export;stdcall;

Как я уже говорил, динамические библиотеки не могут хранить переменных. Именно поэтому после создания окна мы должны вернуть идентификатор основной программе, чтобы она хранила эту переменную. Когда нужно будет закрыть окно, мы передадим этот идентификатор библиотеке, и она освободит память, выделенную под окно.

Теперь посмотрим на реализацию функции ShowAbout:

function ShowAbout(Handle: THandle):LongInt;

begin Application.Handle := Handle; Form1:= TForm1.Create(Application); Form1.Show; Result:=LongInt(Form1);

end;

Здесь всё осталось также, за исключением последней строчки. Если раньше мы освобождали память, то сейчас возвращаем окно Form1 приведённую к типу Integer. Если бы мы тут вызвали метод Free, то окно сразу же после появления закрылось бы.

Теперь посмотрим на процедуру FreeAbout:

procedure FreeAbout(FormRef: LongInt); begin if FormRef>0 then TForm1(FormRef).Free; end;

В этой процедуре мы сначала проверяем, если переменная FormRef (идентификатор окна) больше нуля, то окно можно уничтожать, иначе оно могло быть уже уничтожено. Во второй строке я вызываю метод Free нашего окна. Так как переменная FormRef – это числовая переменная и у неё нет методов, то мы должны перевести её обратно к объекту -TForm1(FormRef).

Теперь подкорректируем проект, который использует DLL файл. Для начала подправь объявления процедур библиотеки. Перед разделом typeнапиши следующее: