В качестве примера - программа 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 показан выше, думаю - не стоит его повторять.