Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Zemskov_my_sppo1

.pdf
Скачиваний:
30
Добавлен:
18.04.2015
Размер:
595.32 Кб
Скачать

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Рис. 2.5. Вид окна диалога для ввода параметров контрастирования

шаблон процедуры, в который надо вписать нужный код: procedure TForm1.Image1MouseMove(Sender: TObject;

Shift: TShiftState; X, Y: Integer); begin

StatusBar1.Panels[0].Text :=

’(’ + IntToStr(X) + ’, ’ + IntToStr(Y) + ’)’ ;

end;

Здесь X и Y — новые координаты указателя мыши в системе координат объекта, для которого создаётся обработчик, т. е. для картинки Image1.

Запустим программу на выполнение и проверим, отображаются ли координаты. Теперь добавим значения яркости точек:

procedure TForm1.Image1MouseMove(Sender: TObject;

Shift: TShiftState;

X,

Y: Integer);

 

var pix, r, g, b : Integer;

 

 

 

begin

 

 

 

 

StatusBar1.Panels[0].Text

:=

 

 

’(’ + IntToStr(X) +

’, ’ + IntToStr(Y) + ’)’ ;

pix := Image1.Picture.Bitmap.Canvas.Pixels[X,Y] ;

r := (pix and $00ff0000) shr

16;

 

g := (pix and $0000ff00) shr

8;

 

b := (pix and $000000ff);

 

 

 

StatusBar1.Panels[1].Text

:=

’Red = ’

+ IntToStr(r);

StatusBar1.Panels[2].Text

:=

’Green = ’ + IntToStr(g);

StatusBar1.Panels[3].Text

:=

’Blue = ’

+ IntToStr(b);

end;

 

 

 

 

Проверьте, как всё это работает.

 

 

9. Создаём новый диалог. Теперь мы хотим выполнить линейное контрастирование, причём параметры ymin и ymax в формуле (2.1) должны вводиться пользователь после нажатия на кнопку Контрастирование. Для этого надо создать новое окно диалога, на котором разместить два поля ввода и текст подсказки. В Delphi имеется заготовка для простого диалогового окна, на котором уже размещены две кнопки (OK и Cancel). Выполним:

í File í New í Other Dialogs ÚÚ Standard Dialog (Horizontal) .

Зададим в инспекторе объектов имя новой формы (для это щёлкнем по её фону, где нет других объектов): Name := InParam; зададим также текст, который будет отображаться в заголовке:

Caption := Параметры контрастирования.

Чтобы заголовок отображался полностью, возможно, придётся несколько увеличить размеры окна. Разместим на новой форме два объекта типа TEdit: Standard Edit Ú форма (два раза)

и две надписи: Standard Label Ú форма (два раза).

Для надписей Label1 и Label2 в инспекторе объектов зададим свойства: Caption := Мин. яркость:; Caption := Макс. яркость:.

Для полей ввода Edit1 и Edit2 зададим Text := 0; Text := 255. Диалог для ввода параметров контрастирования создан (рис. 2.5).

Переключимся на главную форму (можно воспользоваться менеджером проекта: í View í Project Manager ÚÚ Form1 ) и создадим на неё ещё одну кнопку с надписью Контрастирование. Двойным щелчком по новой кнопке создадим заготовку процедуры обработки нажатия и впишем следующий код:

procedure TForm1.Button3Click(Sender: TObject);

var ymin, ymax, xmin, xmax, i, j, pix, w, h : Integer; begin

if InParam.ShowModal = mrOK then begin // Если было нажато OK

13

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

ymin := StrToInt(InParam.Edit1.Text); ymax := StrToInt(InParam.Edit2.Text);

xmin := $ff;

xmax := $00;

w := Image1.Picture.Width - 1;

h :=

Image1.Picture.Height - 1;

with

Image1.Picture.Bitmap.Canvas do

//Найдём макс. и мин. яркость for j := 0 to h do

for i := 0 to w do begin

pix := Pixels[i,j] and $ff;

if pix > xmax then xmax := pix; if pix < xmin then xmin := pix;

end;

//Рисуем второе изображение, являющееся преобразованием первого:

//сначала копируем первое изображение во второе:

Image2.Picture.Bitmap.Assign(Image1.Picture.Bitmap); // теперь изменяем яркость каждой точки:

with Image2.Picture.Bitmap.Canvas do for j := 0 to h do

for i := 0 to w do begin

//получим яркость текущей точки: pix := Pixels[i,j] and $ff;

pix := round((pix-xmin)/(xmax-xmin)*(ymax-ymin)+ymin); if pix > $ff then pix := $ff;

//запишем новое значение яркости точки:

Pixels[i,j] := (pix shl 16) + (pix shl 8) + pix; if (j mod 10 = 0) and (i=0) then

Application.ProcessMessages;

end;

end;

end;

Здесь мы выводим на экран диалог InParam в модальном режиме (т.е. он будет «держать» фокус ввода, пока пользователь не нажмёт OK или Cancel) и если была нажата кнопка OK, то начинаем выполнять контрастирование, а иначе ничего не делаем.

Проверьте, как всё работает. Попробуйте вводить различные значения параметров, чтобы контрастность становилась то больше, то меньше, чем на исходном изображении. Если исходное изображение уже имело максимально возможный динамический диапазон, то при вводе ymin = 0, ymax = 255 обе картинки будут иметь одинаковый вид.

 

2.4. Варианты заданий

 

Разработать программу для демонстрации работы

10) препарирование (рис. 2.1

и) и фильтр (2.15);

указанных методов обработки изображения:

11) препарирование (рис. 2.1

к) и фильтр (2.14)

1)

линейное контрастирование (2.1) и соляриза-

12)

препарирование (рис. 2.1

з) и фильтр (2.13);

ция (2.2);

13)

препарирование (рис. 2.1

ж) и фильтр (2.12);

2)

препарирование (рис. 2.1 а) и фильтр (2.23);

14)

препарирование (рис. 2.1

е) и фильтр (2.11);

3)

препарирование (рис. 2.1 б) и фильтр (2.22);

15)

препарирование (рис. 2.1

д) и фильтр (2.10);

4)

препарирование (рис. 2.1 в) и фильтр (2.21);

16)

препарирование (рис. 2.1

и) и фильтр (2.9);

5)

препарирование (рис. 2.1 г) и фильтр (2.20);

17)

препарирование (рис. 2.1

г) и фильтр (2.8)

6)

препарирование (рис. 2.1 д) и фильтр (2.19);

 

 

 

7)

препарирование (рис. 2.1 е) и фильтр (2.18);

18)

препарирование (рис. 2.1

в) и фильтр (2.7);

8)

препарирование (рис. 2.1 ж) и фильтр (2.17);

19)

препарирование (рис. 2.1

б) и фильтр (2.6);

9)

препарирование (рис. 2.1 з) и фильтр (2.16);

20)

препарирование (рис. 2.1

а) и фильтр (2.3).

Контрольные вопросы

1.В чем состоит сущность поэлементной обработки изображений?

2.Как определяются параметры преобразования изображения при его линейном контрастировании?

3.Каков механизм появления ложных контуров при применении пилообразного контрастирования? При каких ещё процедурах могут возникать ложные контуры?

4.В чём главное различие между методами поэлементного преобразования и методами фильтрации изображений?

5.Как в Object Pascal осуществляется доступ к полям и методам объекта?

6.Какой метод объекта типа TForm позволяет вывести на экран изображение формы в модальном режиме?

14

Ю.В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

7.Чем растровое изображение отличается от векторного?

8.С помощью какого поля объекта типа TImage можно получить доступ к отдельным точкам (пикселям) растрового изображения?

9.Опишите формат хранения информации о цвете каждого пикселя растрового изображения.

10.Какие методы обработки изображений называют неоднородными? Однородными?

11. Что изменится, если в тексте процедур контрастирования и соляризации вместо условного оператора if pix>$ff then pix:=$ff использовать операцию pix := pix and $ff?

15

Ю.В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

3.Использование библиотек динамической компоновки (DLL)

3.1.Основные сведения о динамических библиотеках

Динамически компонуемые библиотеки (dynamic link libraries) — это программные модули, содержащие код, данные и/или ресурсы, которые могут совместно использоваться несколькими приложениями; они подключаются к программе во время её выполнения (динамически, как только программа затребует ту или иную функцию, находящуюся в библиотеке), а не во время компоновки (статически), хотя второй вариант также возможен. Преимущество динамической компоновки заключается в том, что не требуется включать в программу объектный код часто используемых функций, что существенно сокращает объём кода. Использование DLL-библиотек повышает модульность создаваемых программ, что упрощает процесс их обновления.

Когда несколько приложений используют во время своего выполнения одну и ту же динамическую библиотеку, то в память обычно загружается только одна копия этой библиотеки. Для этого используется файл, отображаемый в память (memory-mapped file). Сначала библиотека загружается в распределяемую память (heap, хип) системы Win32, а затем отображаются в адресное пространство вызывающего процесса. Начало области памяти, с которого располагается образ (image) динамической библиотеки в виртуальном адресном пространстве каждого процесса, определяется предпочтительным базовым адресом (preferred base address), который устанавливается при создании библиотеки с помощью директивы компилятора $IMAGEBASE. Если установленное значение этого адреса перекрывается другими адресными диапазонами, используемыми в данном приложении, то при загрузке библиотеки операционная система будет вынуждена отобразить её в другой участок адресного пространства приложения, а это будет означать, что лишняя копия библиотеки будет загружена с другого (свободного) адреса и поэтому будет занимать уже физическую, а не только виртуальную память системы. По умолчанию базовый адрес всех исполняемых файлов (.exe

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

Ввиде DLL-библиотек реализованы функции API Windows. Например, файл user32.dll содержит функции пользовательского интерфейса, необходимые для работы с окнами и обработки сообщений; gdi32.dll — функции работы с графикой; kernel32.dll (ядро) — функции работы с памятью, управления процессами и потоками.

Динамические библиотеки в Windows обычно имеют расширение .dll, но иногда используются

идругие расширения, например, .drv для драйверов устройств, .sys для системных файлов, .fon для файлов ресурсов шрифтов, которые не содержат исполняемого кода.

Динамические библиотеки могут либо автоматически загружаться в оперативную память при запуске использующего их приложения (неявная загрузка, implicit loading), либо программист должен сам перед первым использованием нужной функции загрузить в память необходимую библиотеку (явная загрузка, explicit loading).

ВDelphi и Borland C++ Builder используются также специальные библиотеки, называемые пакетами (package).

Области применения DLL:

1. Библиотеки, содержащие дополнительные функции (для работы со строками, изображениями, реализущие численные методы и т. п.).

2.Хранилища ресурсов (иконок, рисунков, строковых массивов, меню и т. п.).

3.Библиотеки поддержки (DirectX, ICQAPI — API для ICQ, OpenGL и т. п.).

4.Отдельные части программы (оверлеи).

5.Плагины (Plugins — дополнения к программе, расширяющие её возможности).

6.Разделяемый (sharing) ресурс, используемая

и.dll) равен $400000, значит, если не изменить несколькими программами или процессами.

3.2.Пример создания DLL-библиотеки

ВDelphi имеется мастер создания DLLтель (например, MyDLL). Обычно для контроля за

библиотек ( í File í New í Other New ÚÚ DLL Wizard ). При его запуске будет создан шаблон модуля библиотеки:

включаемыми в проект библиотеками после заголовка каждой библиотеки определяют некоторое имя, обычно совпадающее с названием этой библиотеки:

library Project2;

{$DEFINE MyDLL}

uses SysUtils, Classes;

В результате в программе можно будет использовать

{$R *.res}

директиву условной компиляции:

begin

{$IFDEF MyDLL}

end.

// если имя MyDLL определено

При сохранении проекта имя Project2 будет

...........

заменено новым именем, которое укажет пользова-

{$ELSE} // иначе

 

...........

16

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

{$ENDIF}

или

{$IFNDEF MyDLL}

// если имя MyDLL не определёно

............

{$ELSE} // иначе

............

{$ENDIF}

Для примера создадим динамическую библиотеку для выполнения арифметических действий с комплексными числами. Исходный текст модуля библиотеки приведён в листинге 3.1. Обращаем внимание, что все функции и процедуры, которые должны быть доступны приложениям, использующим динамическую библиотеку, должны быть объявлены с модификатором stdcall (для обеспечения совместимости с функциями API Windows). Кроме того, библиотечный модуль содержит так называемый список экспорта (раздел exports): список переменных, процедур и функций, которые будут доступны дру-

гим приложениям. Кроме имени для каждого экспортируемого объекта в заголовок файла динамической библиотеки компилятор добавляет соответствующий индекс (порядковый номер). При вызове экспортируемых объектов (переменных, процедур, функций) можно использовать как имя, так и индекс (поиск нужного объекта по индексу происходит быстрее, чем по имени). Программист может в явном виде присвоить каждому объекту нужный индекс:

exports AddC index 1, SubC index 2;

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

exports

AddC index 1 name ’ComplexAdd’,

SubC index 2 name ’ComplexSub’;

Внешние имена чувствительны к регистру символов.

3.3. Неявная загрузка DLL-библиотеки

Для импорта (использования) функции из библиотеки в текст программы добавляется строка вида:

function СAdd; external ’COMPLEX.DLL’ name ’ComplexAdd’;

или

function СAdd; external ’COMPLEX.DLL’ index 2;

К сожалению, DLL-библиотеки не могут экспортировать типы, поэтому при создании библиотеки обычно также создаётся интерфейсный модуль (модуль импорта), в нашем примере это модуль CompexInt (листинг 3.2), его имя мы добавили в список подключаемых модулей (предложение uses после заголовка библиотеки). Если этот модуль подключается к библиотеке, в которой объявлено имя Complex, то используется только декларация нового типа TComplex, а если модуль вызывается из другой программы, в которой имя Complex не определено, то подключаются также описания внешних процедур (external). Таким образом, с помощью директив условной компиляции можно подключать один и тот же интерфейсный модуль и к библиотеке, и к использующей эту библиотеку программе. В противном случае нам пришлось бы повторять описания всех типов в интерфейсной части как библиотечного, так и интерфейсного модуля.

В результате компиляции проекта создаётся файл Complex.dll, который вместе с исходным текстом интерфейсного модуля ComplexInt.pas используется в последующем при создании новых программ. Если программист хочет использовать библиотечные функции из программы, написанной на другом языке программирования, то он должен переписать текст интерфейсного модуля на своём языке. Часто при распространении библиотек поставляют интерфейсные модули на нескольких языках (на языке Си это заголовочные файлы с расширением .h, на Си++ это файлы .hpp). Во всех случаях используется один и тот же dll-файл.

Для примера покажем использование внешних функций в другом Delphi-приложении. Создадим новый проект, разместим на форме четыре поля ввода Edit, две надписи Label и одну кнопку Button. Код обработчика нажатия на кнопку приведён в листинге 3.3. В главном модуле приложения необходимо подключить интерфейсный модуль:

uses ....., ComplexInt;

Теперь можно запустить программу на выполнение, ввести действительные и мнимые части двух комплексных чисел и нажать на кнопку Add

(Сложить).

3.4. Явная загрузка динамической библиотеки

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

только тип TComplex). Кроме того, необходимо будет описать процедурный тип (листинг 3.4) и переменную этого типа, в которой будет храниться адрес внешней процедуры (функции). Перед первым использованием внешней функции необходимо загру-

17

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 3.1. Текст библиотечного модуля

library Complex; {$DEFINE Complex} uses

SysUtils, Classes, ComplexInt; {$R *.res}

function AddC(x,y: TComplex): TComplex; stdcall; begin

Result.Re := x.Re + y.Re; Result.Im := x.Im + y.Im;

end;

function SubC(x,y: TComplex): TComplex; stdcall; begin

Result.Re := x.Re - y.Re; Result.Im := x.Im - y.Im;

end;

exports // список экспорта

AddC, SubC;

begin // инициализирующая часть в данном случае пустая end.

Листинг 3.2. Текст интерфейсного модуля

unit ComplexInt; interface

type

TComplex = record Re, Im : Real;

end;

{$IFNDEF Complex}

// если не подключался модуль Complex, то объявляем функции как внешние: function AddC(x,y: TComplex): TComplex; stdcall;

function SubC(x,y: TComplex): TComplex; stdcall; {$ENDIF}

implementation {$IFNDEF Complex}

function AddC; stdcall; external ’COMPLEX.DLL’ name ’AddC’; function SubC; stdcall; external ’COMPLEX.DLL’ name ’SubC’; {$ENDIF}

begin end.

Листинг 3.3. Текст обработчика нажатия на кнопку procedure TForm1.Button1Click(Sender: TObject); var x,y,z : TComplex;

begin

x.Re := StrToFloat(Edit1.Text); x.Im := StrToFloat(Edit2.Text); y.Re := StrToFloat(Edit3.Text); y.Im := StrToFloat(Edit4.Text); z := AddC(x,y);

Label1.Caption := FloatToStr(z.Re);

Label2.Caption := FloatToStr(z.Im); end;

18

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

зить библиотеку с помощью вызова

Handle:=LoadLibrary(’имя.dll’)

где Handle — переменная целого типа (LongWord). После этого надо получить адрес используемой функции:

@Add:=GetProcAddress(Handle, PChar(

LongInt (2) ));

или

@Add:=GetProcAddress(Handle, PChar(

’AddC’ );

После использования библиотеку надо освободить:

FreeLibrary(Handle);

(если библиотеку освободили все приложения, то операционная система выгружает её из памяти).

Листинг 3.4. Пример явной загрузки библиотеки

type

TComplex = record R, I : Real;

end;

TComplexFunc = function (x,y: TComplex): TComplex; stdcall;

........................................

procedure TForm1.Button1Click(Sender: TObject); var

x,y,z : TComplex; Add : TComplexFunc; Handle : LongWord;

begin

x.R := StrToFloat(Edit1.Text); x.I := StrToFloat(Edit2.Text); y.R := StrToFloat(Edit3.Text); y.I := StrToFloat(Edit4.Text);

Handle := LoadLibrary(’Complex.dll’); // Загружаем библиотеку if Handle = 0 then begin // если неудачно

ShowMessage(’Не найдена библиотека Complex.dll’); Halt; // аварийно закончить

end;

@Add:=GetProcAddress(Handle,PChar(’AddC’));

//получили адрес функции;

//вариант:

//@Add:=GetProcAddress(Handle, PChar(LongInt(2)));

z := Add(x,y);

FreeLibrary(Handle); // выгрузили библиотеку Label1.Caption := FloatToStr(z.R); Label2.Caption := FloatToStr(z.I);

end;

3.5.Хранение форм в динамических библиотеках

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

создана раньше.

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

Модуль формы DLLForm, помещенной в DLL, ссылается на стандартный модуль Forms и таким образом получает свой глобальный объект Application,

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

19

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

получающего это сообщение. Вот почему вторым параметром обращения к функции ShowForm в DLL передаётся и в поле CallForm запоминается дескриптор вызывающего окна. Обработчик события onClose формы проверяет это поле и, если оно определено,

посылает вызывающему окну сообщение с индексом WM_User. В вызывающей программе предусмотрен обработчик этого сообщения, в котором реализуются необходимые действия.

Листинг 3.5. DLL-библиотека с формой

library DLLWithForm;

uses SysUtils, Classes, DLLFormU in ’DLLFormU.pas’ {DLLForm}; {$R *.RES}

exports

ShowModalForm, ShowForm, FreeForm; begin

end.

3.6. Варианты заданий

Необходимо выполнить задание, создав три проекта Delphi: а) с использованием неявной загрузки DLL-библиотеки; б) с использованием явной загрузки DLL-библиотеки; в) с хранением формы в DLLбиблиотеке.

1.Библиотека операций над векторами.

2.Библиотека операций над матрицами.

3.Библиотека графических операций над прямыми линиями.

4.Библиотека графических операций над прямоугольниками.

5.Библиотека графических операций над окружностями и кругами.

6.Библиотека графических операций над четырёхугольниками.

7.Библиотека графических операций над трёх-

угольниками.

8.Библиотека операций над графами.

9.Библиотека для выполнения сортировки массивов с использованием различных алгоритмов.

10.Библиотека для выполнения операций над строковыми данными.

11.Библиотека для решения систем линейных алгебраических уравнений с использованием различных алгоритмов.

12.Библиотека для решения дифференциальных уравнений с использованием различных алгоритмов.

13.Библиотека для построения графиков функ-

ций.

14.Библиотека для выполнения различных файловых операций.

20

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 3.6. Описание формы, которая будет храниться в 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

CallForm: THandle; // Дескриптор вызывающей формы 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<>0 then SendMessage(CallForm, wm_User, 0, 0) end;

end.

21

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 3.7. Текст вызывающей программы

unit TestMainU; interface

uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type

TTestMain = class(TForm)

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

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

procedure ButtonlClick(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); public

procedure WMUser(var Msg: TMessage); message WM_USER; end;

var TestMain: TTestMain;

implementation {$R *.DFM}

function ShowModalForm: Integer; External ’DLLWithForm.dll’; procedure ShowForm(Appl, Form: THandle); External ’DLLWithForm.dll’; procedure FreeForm; External ’DLLWithForm’;’

procedure TTestMain.ButtonlClick(Sender: TObject); // Модальный вызов begin

Button2.Enabled := False;

labell.Caption := ’ModalResult = ’ + IntToStr(ShowModalForm); labell.Show; // Показываем результат вызова

Button2.Enabled := True end;

procedure TTestMain.Button2Click(Sender: TObject); // Немодальный вызов begin

Buttonl.Enabled := False;

Button2.Enabled := False;

Button3.Enabled := True; labell.Hide;

ShowForm(Application.Handle, Self.Handle); end;

procedure TTestMain.Button3Click(Sender: TObject); // Закрыть форму begin

FreeForm; Buttonl.Enabled := True; Button2.Enabled := True; Button3.Enabled := False;

end;

procedure TTestMain.WMUser(var Msg: TMessage); // Сообщение из формы DLL о её закрытии

begin Button3.Click

end;

end.

22

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]