В качестве примера - программа Poisk, рассмотренная ранее. Из этой программы удалены подпрограммы-заглушки и лишние элементы интерфейса (TRadioGroup). Добавлен пункт меню: Данные | Новые.
Подпрограммы: RandomData и CalcMax размещены в библиотеке POISKLIB.dll, причем для разнообразия CalcMax преобразована в функцию. Процедура ShowGraphPoints осталась в модуле unPokaz, потому что в ней используется объект - форма, и работа с формами требует особого рассмотрения.
Самое забавное в этом проекте - согласно книге [6] он
НЕ ДОЛЖЕН РАБОТАТЬ (но работает). Подробнее об этом
см в конце страницы
Запускаем Делфи, далее в меню: File | New | Other . Здесь на закладке New щелкаем DLL Wizard. В результате в редакторе создается шаблон файла .dpr и мы начинаем с ним работать. В итоге этот файл имеет вид:
library POISKLIB;
{$DEFINE POISKLIB}
{ Комментарий убрал }
uses
SysUtils,
Classes,
UnPoiskIntface in 'UnPoiskIntface.pas';
procedure RandomData(NumPoints: integer; MinX,MaxX,MinY,MaxY: double;
var Coord: TCoord); StdCall;
var ii: integer;
begin
Randomize;
for ii:=0 to NumPoints-1 do
begin
Coord[ii].X:= MinX + (MaxX-MinX)*random;
Coord[ii].Y:= MinY + (MaxY-MinY)*random;
end;
end;
function CalcMax(NumPoints: integer; MinX,MaxX,MinY,MaxY: double;
var Coord: TCoord; var N1,N2: integer {номера заданных точек}):word; StdCall;
var ii,jj,imax,jmax: integer; Rasst,RMax: double;
begin
RMax:= 0; imax:=0; jmax:=0;
for ii:=1 to NumPoints-1 do
for jj:= ii+1 to NumPoints do
begin
Rasst:= sqrt(sqr(Coord[ii-1].X - Coord[jj-1].X)
+ sqr(Coord[ii-1].Y - Coord[jj-1].Y));
if Rasst > Rmax then
begin
RMax:= Rasst;
imax:= ii-1;
jmax:= jj-1;
end;
end;
N1:= imax;
N2:= jmax;
Result:= 222;
end;
//ShowGraphPOints - недопустимо, т к там есть форма (frmPokaz.ClientWidth)
exports RandomData, CalcMax;
end.
В этот же проект добавляю модуль UnPoiskIntface, который будет интерфейсным для программы, использующей библиотеку POISKLIB. То есть в меню Делфи: File | New | Unit и создаю модуль (при этом многое копирую из модуля unPokaz проекта Poisk) , имеющий вид:
unit UnPoiskIntface;
{ Модуль интерфейса для библиотеки .DLL
(по примеру из книги [6] )
}
interface
type TPointFloat = record
X,Y: single;
end;
TCoord = array of TPointFloat;
{$IFNDEF POISKLIB}
procedure RandomData(NumPoints: integer; MinX,MaxX,MinY,MaxY: double;
var Coord: TCoord); StdCall;
function CalcMax(NumPoints: integer; MinX,MaxX,MinY,MaxY: double;
var Coord: TCoord; var N1,N2: integer {номера заданных точек}):word; StdCall;
{$ENDIF}
implementation
{$IFNDEF POISKLIB}
procedure RandomData; external 'POISKLIB.DLL' name 'RandomData';
function CalcMax; external 'POISKLIB.DLL' name 'CalcMax';
{$ENDIF}
end.
Примечание:Для этого проекта создаю папку \Применяем DLL. В нее копирую файлы проекта Poisk и редактирую эти файлы. Чтобы добавить модуль UnPoiskIntface - копирую UnPoiskIntface.pas из папки, в которой хранится проект POISKLIB (папка \Создаем DLL) в папку \Применяем DLL. Затем в меню Делфи: Project | Add to project - и выбираю UnPoiskIntface.pas . Ниже - см тексты модулей переделанного проекта Poisk:
unit unMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Menus;
type
TfrmMain = class(TForm)
MainMenu1: TMainMenu; Vvod: TMenuItem;
Random: TMenuItem; Solve: TMenuItem;
Quit: TMenuItem; Pokaz: TMenuItem;
Label1: TLabel; edCount: TEdit;
Label2: TLabel; edminX: TEdit;
Label3: TLabel; edmaxX: TEdit;
Label4: TLabel; edminY: TEdit;
Label5: TLabel; edmaxY: TEdit;
btnNew: TMenuItem;
procedure RandomClick(Sender: TObject);
procedure QuitClick(Sender: TObject);
procedure PokazClick(Sender: TObject);
procedure SolveClick(Sender: TObject);
procedure btnNewClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation uses unPokaz, UnPoiskIntface;
{$R *.dfm}
var
NPoints, NN1, NN2: integer;
MinX1,MaxX1,MinY1,MaxY1: double;
Coord1: TCoord;
Buf: word;
procedure TfrmMain.RandomClick(Sender: TObject);
begin
NPoints:= StrToInt(edCount.Text);
MinX1:= StrToFloat(edminX.Text);
MaxX1:= StrToFloat(edmaxX.Text);
MinY1:= StrToFloat(edminY.Text);
MaxY1:= StrToFloat(edmaxY.Text);
if MaxX1 <= MinX1 then
begin
showmessage('MaxX > MinX !');
exit;
end;
if MaxY1 <= MinY1 then
begin
showmessage('MaxY > MinY !');
exit;
end;
SetLength(Coord1, NPoints);
Randomize;
RandomData(NPoints,MinX1,MaxX1,MinY1,MaxY1,Coord1);
Solve.Enabled:= true;
edCount.Enabled:= false;
edminX.Enabled:= false;
edmaxX.Enabled:= false;
edminY.Enabled:= false;
edmaxY.Enabled:= false;
end;
procedure TfrmMain.QuitClick(Sender: TObject);
begin
Application.Terminate;
end;
procedure TfrmMain.PokazClick(Sender: TObject);
begin
ShowGraphPoints(NPoints,MinX1,MaxX1,MinY1,MaxY1,Coord1,0,0);
end;
procedure TfrmMain.SolveClick(Sender: TObject);
begin
Buf:= CalcMax(NPoints,MinX1,MaxX1,MinY1,MaxY1,Coord1,NN1,NN2);
ShowGraphPoints(NPoints,MinX1,MaxX1,MinY1,MaxY1,Coord1,NN1,NN2);
end;
procedure TfrmMain.btnNewClick(Sender: TObject);
begin
edCount.Enabled:= true;
edminX.Enabled:= true;
edmaxX.Enabled:= true;
edminY.Enabled:= true;
edmaxY.Enabled:= true;
Coord1:= nil;
end;
end.
---------------------------------
unit unPokaz;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, UnPoiskIntface;
type
TfrmPokaz = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmPokaz: TfrmPokaz;
procedure ShowGraphPoints(NumPoints: integer; MinX,MaxX,MinY,MaxY: double;
var Coord: TCoord; N1,N2: integer);
implementation uses unMain;
{$R *.dfm}
procedure ShowGraphPoints(NumPoints: integer; MinX,MaxX,MinY,MaxY: double;
var Coord: TCoord; N1,N2: integer);
var ii,XX,YY: integer;
ax,bx,ay,by: double;
{ коэффициенты линейного преобразования реальных координат
в экранные: Хэкр := ax*Хреал + bx; такие, что
Хэкр(Xmin) = 0; Хэкр(Xmax) = ширина формы.
Yэкр := ay*Yреал + by;
Yэкр(Ymin) = высота формы; Yэкр(Ymax) = 0.
a,b - определяются из решения СЛАУ, записанных выше
}
begin
// showmessage('Показ точек - график');
ax:= frmPokaz.ClientWidth/(MaxX-MinX);
bx:= ax*MinX;
ay:= frmPokaz.ClientHeight/(MinY - MaxY);
by:= -ay*MaxY;
with frmPOkaz do
begin
Canvas.Pen.Width:=2;
Canvas.Pen.Color:= clGreen;
Color:= clBlack;
Canvas.FillRect(ClientRect);
Show;
for ii:= 0 to NumPoints - 1 do
begin
XX:= Round(ax*Coord[ii].X + bx);
YY:= Round(ay*Coord[ii].Y + by);
Canvas.Pixels[XX,YY ]:= RGB(200,200,200);
Canvas.Pixels[XX+1,YY ]:= RGB(200,200,0);
Canvas.Pixels[XX+1,YY+1 ]:= RGB(0,200,200);
Canvas.Pixels[XX,YY+1 ]:= RGB(200,0,200);
end;
if N1<>N2 then
begin
XX:= Round(ax*Coord[N1].X + bx);
YY:= Round(ay*Coord[N1].Y + by);
Canvas.Ellipse(XX-5,YY-5,XX+5,YY+5);
XX:= Round(ax*Coord[N2].X + bx);
YY:= Round(ay*Coord[N2].Y + by);
Canvas.Ellipse(XX-5,YY-5,XX+5,YY+5);
end;
end;
end;
end.
Текст модуля UnPoiskIntface показан выше, думаю - не стоит его повторять.