The production of a Dll is generally divided into the following steps:
1 Write a procedure or function in a DLL project
2 Write an Exports keyword and write the name of the procedure below it. There is no need to write parameters and call suffixes.
Two parameters passed
1 The parameter type should be consistent with the parameter type of window C++. Do not use the DELPHI data type.
2 It is best to have a return value [even if it is a procedure] to report the success or failure of the call, or the status. The return value of success or failure is preferably 1 [success] or 0 [failure]. In a word, it is compatible with Windows C++.
3 Declare the suffix with stdcall.
4 Preferably case-sensitive.
5 There is no need to use the far calling suffix, it is just for compatibility with Windows 16-bit programs.
Initialization and exit cleanup of three DLLs [if initialization and exit cleanup are required]
1 DLLPRoc [a Pointer of the SysUtils unit] is the entrance to the DLL. Here you can replace its entry with your function. But your function must meet the following requirements [actually a callback function]. as follows:
procedure DllEnterPoint(dwReason: DWord);far;stdcall;
There are four types of dwReason parameters:
DLL_PROCESS_ATTACH: When the process enters
DLL_PROCESS_DETACH when the process exits
DLL_THREAD_ATTACH when the thread enters
DLL_THREAD_DETACH when the thread exits
In the initialization section write:
DLLProc := @DLLEnterPoint;
DllEnterPoint(DLL_PROCESS_ATTACH);
2 If there is a TdcomConnection component on the Form, use Uses Activex and write CoInitialize (nil) during initialization;
3 Make sure DcomConnection.Connected := False when exiting, and the data set has been closed. Otherwise, the reported address is wrong.
The use of four global variables
In the Widnows 32-bit program, the address spaces of the two applications are not related to each other. Although the DLL is a copy in the memory, the variables are in the address space of each process, so you cannot use the global variables of the dll to transfer data between two applications unless you use a memory image file.
5. Call static loading
1 Client function declaration:
1) Case sensitive.
2) Same as the declaration in the DLL.
Such as: showform(form:Tform);Far;external'yproject_dll.dll';
3) The parameter type passed when calling should be the same as Windows C++.
4) When calling, the DLL must be in the windows search path. The order is: current directory; Path path; windows; widths/system; windows/ssystem32;
Six calls to dynamic loading
1 Create a procedure type [If you are clear about the nature of a procedure type variable being just a pointer, you will know what is going on]. like:
type
mypointer=procedure(form:Tform);Far;external;
var
Hinst:Thandle;
showform:mypointer;
begin
Hinst:=loadlibrary('yproject_dll');//Load a Dll and find it by file name.
showform:=getprocaddress(Hinst,'showform');//Search by function name, case sensitive. This is clear if you know the nature of automation objects.
showform(application.mainform);//Called when finding the function entry pointer.
Freelibrary(Hinst);
end;
7. Create a TForM in the DLL
1 Uses your Form into Dll, and the associated units used by your Form must also be Uses in [This is the most troublesome point, because your Form may Uses many special units or functions]
2 Pass an Application parameter and use it to create the Form.
8. Create a TMDIChildForM in the DLL
1 MDIForm.FormStyle in Dll does not need to be fmMDIChild.
2 Write the following two sentences after CreateForm:
function ShowForm(mainForm:TForm):integer;stdcall
var
Form1: TForm1;
ptr:PLongInt;
begin
ptr:=@(Application.MainForm);//Save the MainForm handle of the dll first, there is no need to release it, just replace it
ptr^:=LongInt(mainForm);//Replace the MainForm of the DLL with the mainForm of the calling program. MainForm is a special WINDOW that specifically manages Forms resources in Application.
//Why not directly Application.MainForm := mainForm, because Application.MainForm is a read-only property
Form1:=TForm1.Create(mainForm);//Create with parameters
end;
Note: The parameter is Application.MainForm of the calling program
Nine examples:
DLL source code:
library Project2;
uses
SysUtils,
Classes,
Dialogs,
Forms,
Unit2 in 'Unit2.pas' {Form2};
{$R *.RES}
var
ccc: Pchar;
procedure OpenForm(mainForm:TForm);stdcall;
var
Form1: TForm1;
ptr:PLongInt;
begin
ptr:=@(Application.MainForm);
ptr^:=LongInt(mainForm);
Form1:=TForm1.Create(mainForm);
end;
procedure InputCCC(Text: Pchar);stdcall;
begin
ccc := Text;
end;
procedure ShowCCC;stdcall;
begin
ShowMessage(String(ccc));
end;
exports
OpenForm;
InputCCC,
ShowCCC;
begin
end.
Caller source code:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure OpenForm(mainForm:TForm);stdcall;External'project2.dll';
procedure ShowCCC;stdcall;External'project2.dll';
procedure InputCCC(Text: Pchar);stdcall;External'project2.dll';
procedure TForm1.Button1Click(Sender: TObject);
var
Text: Pchar;
begin
Text := Pchar(Edit1.Text);
// OpenForm(Application.MainForm);//In order to adjust MDICHILD
InputCCC(Text);//In order to experiment whether the global variables in the DLL are shared between various applications
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ShowCCC;//This shows that the global variables in the WINDOWS 32-bit application DLL are also in the application address space. The 16-bit application may be different, and no experiments have been done.
end;