Delphi 创建DLL及其调用之详解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第一步: 做 DLL
library CreateDLL;
uses
SysUtils,
Windows, {钩子函数都来自Windows单元}
Messges, {消息WM_LBUTTONDOWN定义在Message单元}
Classes;
{$R *.res}
var
hook : HHOOK; {钩子变量}
{
一般来说,DLL是一种磁盘文件(通常带有DLL扩展名),
它由全局数据、服务函数和资源组成,在运行时被系统加载到进程的虚拟空间中,成为调用进程的一部分。
DLL模块中包含各种导出函数,用于向外界提供服务。
Windows在加载DLL模块时将进程函数调用与DLL文件的导出函数相匹配。
如果与其它DLL之间没有冲突,该文件通常映射到进程虚拟空间的同一地址上。
在Win32环境中,每个进程都复制了自己的读/写全局变量。
如果想要与其它进程共享内存,必须使用内存映射文件或者声明一个共享数据段。
DLL模块需要的堆栈内存都是从运行进程的堆栈中分配出来的。
}
{钩子函数,鼠标消息太多(譬如鼠标移动),必须要有选择,这里选择了鼠标按下}
function MouseHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall
begin
if wParam = WM_LBUTTONDOWN then
begin
MessageBeep(0);
end;
Result := CallNextHookEx(hook, nCode, wParam, lParam);
end;
{建立钩子}
function SetHook: Boolean; stdcall;
begin
hook := SetWindowsHookEx(WH_MOUSE, @MouseHook, HInstance, 0);
Result := hook <> 0;
end;
{释放钩子}
function DelHook: Boolean; stdcall;
begin
Result := UnhookWindowsHookEx(hook);
end;
{按DLL的要求输出函数}
exports
{exports用于输出对象, 它必须被用在接口和实现之间, 可以同时输出多个项, 项与项之间用逗号分开.
如果输出的对象被重载, 则必须给对象起个别名, 并注明参数.}
SetHook name 'SetHook',
DelHook name 'DelHook',
MouseHook name 'MouseHook';
//SetHook, DelHook, MouseHook; {这里没重载,如果不需要改名, 可以直接这样 exports}
begin
end.
第二步: 调用
新建工程后, 保存, 并把刚才制作的 MyHook.dll 复制到这个工程目录下;
{静态加载DLL}
unit SDLL;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;
{DLL中的函数声明}
function SetHook: Boolean; stdcall;
function DelHook: Boolean; stdcall;
var
Form1: TForm1;
implementation
{$R *.dfm}
{DLL中的函数实现,也就是说明来自哪里,原来叫啥名}
function SetHook; external 'CreateDLL.dll' name 'SetHook';
function DelHook; external 'CreateDLL.dll' name 'DelHook';
{
External关键字用于引用一个外部的或是OBJ内的方法X.(方法X是外部的)
procedure X(i:Integer
);external;
如果是从dll或外部程序中引用, 则可以使用以下代码:
function A(FileName: string): string; external 'Demo.dll';
如果被引用的函数被重载, 则必须另外指出引用的名称.
function A(Name: string): string; overload; stdcall; external 'Demo.dll' name 'A1';
function A(Code: Integer): string; overload; stdcall; external 'Demo.dll' name 'A2';
使用External关键字时, 必须注意大小写, 否则将出现错误.
}
{建立钩子}
procedure TForm1.Button1Click(Sender: TObject);
begin
SetHook;
end;
{销毁钩子}
procedure TForm1.Button2Click(Sender: TObject);
begin
DelHook;
end;
end.
{动态引用DLL}
unit DDLL;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{先要定义和DLL中同样参数和返回值类型的函数类型}
type
TDLLFun = function: Boolean; stdcall;
{现在需要的DLL中的函数的格式都是这样,定义一个就够了}
var
h: HWND; {声明一个 DLL 句柄}
SetHook, DelHook: TDLLFun;{声明两个 TDLLFun 变量}
{
动态装入DLL,要用到Windows的三个API函数:Loadlibrary、Freelibrary和GetprocAddress 。
loadlibrary函数用来加载DLL库,其调用格式如下:function loadlobrary (DLLfileName:Pchar): THandle:
当不再需要一个DLL库时,应调用FreeLibrary函数将其释放,其调用格式如下:procedure FreeLibrary (Libmodule:THandle)
Libmodule 为由LoadLibrary调用得到的DLL库句柄。
在用loadlobrary 函数加载某个DLL库和调用FreeLibrary释放该DLL库之间的程序段中, 可以使用该DLL库中的过程和函数,
具体使用方法是:用GetprocAddress函数把DLL库中函数的地址传递给程序中某个函数变量,再用该变量实现DLL函数的调用。
GetprocAddress函数声名如下,function GetprocAddress (Libmodule:THandle:procname:pchar):TFarProc:
}
{载入 DLL 并调用其函数}
procedure TForm1.Button1Click(Sender: TObject);
begin
h := LoadLibrary('CreateDLL.dll'); {载入DLL并获取句柄}
if h<>0 then
begin
SetHook := GetprocAddress(h, 'SetHook');{让 SetHook 指向 DLL中相应的函数}
DelHook := GetprocAddress(h, 'DelHook');{让 DelHook 指向 DLL中相应的函数}
end else ShowMessage('Err');
SetHook; {执行钩子建立函数,这里的SetHook 和它指向的函数是同名的,也可以不同名}
end;
{销毁钩子,并释放 DLL}
procedure TForm1.Button2Click(Sender: TObject);
begin
DelHook; {指行钩子释放函数}
FreeLibrary(h);{释放DLL资源}
end;
end.