• Delphi中dll的使用(转)


    Windows 的执行文件可以划分为两种形式程序和动态连接库 (DLLs)。一般程序运行是用.EXE文件,但应用程序有时也可以调用存储在DLL的函数。  
    当我们调用Windows 中的API 函数的时候,实际上就是调用存储在DLL 中的函数。  
    在如下几种情况下,调用DLL 是合理的:  
    1) 不同的程序使用相同的DLL ,这样只需要将DLL 在内存中装载一次,节省了内存的开销。  
    2) 当某些内容需要升级的时候,如果使用DLL 只需要改变DLL 就可以了,而不需要把整个程序都进行变动。  
    3) 由于DLL 是独立于语言的,所以,当不同语言习惯的人  
    共同开发一个大型项目的时候,使用DLL 便于程序系统的交流,当然,Delphi开发的DLL 也可以在诸如Visual BASIC,C++ 等系统中使用。  
    下面通过几个例子,说明Delphi开发动态连接库的方法和规范。  
    第一节 动态连接库的构建和调用方法  
    一、动态连接库构建 File---New---Other---DLL Wizard  
    这就创建了一个动态连接库的基本模块  
    library Project2; uses  
    SysUtils,  
    Classes;  
    {$R *.res}  
    begin  
    end.  
    把工程名改为Mydll,并写入必要的函数  
    library mydll;  
    uses  
    SysUtils,Classes,Dialogs,windows;  
    function Triple(N:Integer):integer;stdcall;  
    begin  
    result:=N+3;  
    end;  
    function Double(N:Integer):integer;stdcall;  
    begin  
    result:=N+2;  
    end;  
    function Triple1(N:Integer):integer;stdcall;  
    begin  
    showmessage(’计算N+3’);  
    result:=N+3;  
    end;  
    function Double1(N:Integer):integer;stdcall;  
    begin  
    messagebox(0,’计算N+2’,’计算N+2’,mb_ok);  
    result:=N+2;  
    end;  
    exports  
    Triple name ’Tr’,  
    Double name ’Do’,  
    Triple1 name ’TrM’,  
    Double1 name ’DoM’;  
    Triple,Double,Triple1,Double1;  
    {$R *.RES}  
    begin  
    end.  
    其中函数:Triple:把传入值加三  
    Double:把传入值加二  
    Triple1:把传入值加三并显示提示  
    Double1:把传入值加二并显示提示  
    从这个例子中可以看出DLL 程序的几个规则:  
    1) 在DLL 程序中,输出函数必须被声明为stdcall,以使用标准的Win32 参数传递技术来代替优化的Register。  
    (说明:在Delphi中Register方式是缺省的调用约定,这个约定尽量采用寄存器来传递参数,传递次序从左到右,最多可用到3个CPU 的寄存器,如果参数多于3 个,剩下的就通过栈来传送,使用寄存器传送可保证参数传递的速度最快。  
    而stdcall 方式是通过Windows 的标准调用来传递参数,传递秩序从左到右,这种方式适合调用Windows 的API ,在DLL 中,当然要使用这种方式)。  
    2)所有的输出函数都必须列在exports子句下面,这使的子例程在DLL外部就可以看到。

    exports  
    Triple name ’Tr’,  
    Double name ’Do’,  
    Triple1 name ’TrM’,  
    Double1 name ’DoM’;  
    列出了用户使用这个函数的接口名字。虽然别名不是必须的,但最好给个别名,以便用户程序更容易找到这个函数,同时还要指出Delphi 6.0取消了Delphi 5.0中允许使用的index ,如果还用Index指明接口名字,Delphi 6.0中将提示错误。  
    实例中给出了两种提示方法,主要想说明一个问题:  
    showmessage(’’),是VCL 提供的函数,由于多次编译VCL,做出的程序会比较大。  
    而messagebox(0,’’,’’,mb_ok) 是Windows提供的API 函数,做出的程序会比较小。  
    这就是说,编写DLL 程序的时候,要尽量避免多次编译VCL 。作为一个实例,这里把两种方法都列出来了。  
    保存  
    编译:Projrct---Build Mydll  
    这就完成了一个简单的动态连接库的编写。  
    二、动态连接库的调用  
    首先在implementation下做调用声明  
    const  
    gdi32=’mydll.dll’;  
    function triple(n:integer):integer;stdcall;external gdi32 name ’Tr’;  
    function Double(N:Integer):integer;stdcall;external gdi32 name ’Do’;  
    function triple1(n:integer):integer;stdcall;external gdi32 name ’TrM’;  
    function Double1(N:Integer):integer;stdcall;external gdi32 name ’DoM’;  
    以后程序中就可以作为普通的函数使用了,例如:  
    procedure TForm1.Button1Click(Sender: TObject);  
    var N:integer;  
    begin  
    N:=updown1.position;  
    edit1.text:=inttostr(triple(N));  
    end;  
    第二节 DLL 中的Delphi窗体  
    一、在DLL 中放置窗的的方法  
    在DLL 中,除了放置标准的函数和过程以外,也可以放置已经做好的的delphi窗体,也可以把做好的窗体供其它程序使用,方法是:  
    1)首先按普通方法制作窗体,不过在interface区域,对接口函数做如下声明  
    function Createform(capt:string):string;stdcall;  
    2)在implementation下加入接口函数  
    function Createform(capt:string):string;stdcall;  
    var Form1: TForm1;  
    begin  
    form1:=Tform1.Create(application);  
    form1.show;  
    form1.caption:=capt;  
    end;  
    3)制作DLL 动态连接库,但要声明:  
    uses  
    unit1 in ’unit1.pas’;  
    exports  
    {写入接口标示符}  
    Createform name ’Myform’;  
    4)调用窗体的程序按普通方法制作,但是 在implementation下首先声明要调用的DLL函数  
    const  
    gdi32=’myFormdll.dll’;  
    function Createform(capt:string):string;stdcall;external gdi32 name ’Myform’;

    procedure TForm3.Button1Click(Sender: TObject);  
    var n,m:string;  
    begin  
    m:=’我的窗体’;  
    Createform(m);var n,m:string;  
    end;  
    二、DLL 中的调用窗体时的数据传递  

    在窗体调用时,可以用普通的函数方法传递数据,下面举个例子。  
    1)建立窗体  
    做一个改变颜色窗体,放在DLL 中,可以用普通的方法来做,但要作如下声明:  
    function mycolor(col:longint):longint;stdcall;  
    function Getcolor:longint;stdcall;  
    其中,mycolor为构造窗体;Getcolor为传递颜色数据。  
    在implementation区声明一个窗体内全局的变量  
    var color1:longint;  
    下面写出相应的程序  
    function mycolor(col:longint):longint;stdcall;  
    var Form1: TForm1;  
    begin  
    form1:=Tform1.Create(application);  
    form1.show;  
    form1.panel1.Color:=col;  
    form1.edit1.Text:=inttostr(form1.panel1.Color);  
    result:=color1;  
    end;  
    function Getcolor:longint;stdcall;  
    begin  
    result:=color1;  
    end;  
    procedure TForm1.ScrollBar1Change(Sender: TObject);  
    begin  
    panel2.Color:=RGB(ScrollBar1.Position,ScrollBar2.Position,ScrollBar3.Position);  
    edit2.Text:=inttostr(panel2.Color);  
    color1:=panel2.Color;  
    end;  
    procedure TForm1.Button2Click(Sender: TObject);  
    begin  
    Free; //析构Form1  
    end;  
    2)建立动态连接库  
    运行成功后,再建立动态连接库:  
    library FormDLL;  
    {从文件调入}  
    uses  
    unit1 in ’unit1.pas’;  
    exports  
    {写入接口标示符}  
    Mycolor name ’My’,  
    Getcolor name ’Get’;  
    begin  
    end.  
    3)建立调用的程序  
    首先声明要调用的DLL函数  
    const  
    gdi32=’formDll.dll’;  
    function Mycolor(col:longint):longint;stdcall;external gdi32 name ’My’;  
    function Getcolor:longint;stdcall;external gdi32 name ’Get’;  
    然后写出相应的程序  
    procedure TForm1.Button1Click(Sender: TObject);  
    begin  
    Mycolor(color);  
    end;  
    procedure TForm1.Button2Click(Sender: TObject);  
    begin  
    color:=getcolor;  
    end;  
    我们可以看到,在改变颜色的窗体中做了颜色变化后,当前窗体的颜色将发生变化。 


  • 相关阅读:
    JS系列:三元运算符与循环
    浏览器解析js和type判断数据类型
    JS系列:数据类型详细讲解
    JS系列:编程语言
    京东校招面试汇总
    有关axios的request与response拦截
    正则表达式 判断内容是否为合法的url
    H5 小代码(实时更新)
    H5 回到顶部按钮
    图片压缩(js压缩,底部有vue压缩图片依赖使用的教程链接)
  • 原文地址:https://www.cnblogs.com/feng801/p/1270366.html
Copyright © 2020-2023  润新知