1、在初始化部分写:DLLPrOC := DLLE nterPoi nt;DIIE nterPoi nt(DLL_PROCESS_ATTACH);2女口 Form 上有 TdCOmCOnnectiOn 组件,就 USeS Activex,在初始化时写一句 CoInitialize (nil);3在退出时一定保证 DcomConnection.Connected := False,并且数据集已关闭。否则报地址错。在Widnows 32位程序中,两个应用程序的地址空间是相互没有联系的。 虽然DLL在内存中是一份,但变量是在各进程的地址空间中,因此你不能借助 dll的全局变量来达到两个应用程序间的数据传
2、递,除非你用内存映像文件。1客户端函数声名:1)大小写敏感。2)与DLL中的声明一样。女口: ShoWform(form:Tform);Far;externalyproject_dll.dll:3)调用时传过去的参数类型最好也与 Win dows c+ 一样。4)调用时DLL必须在 Win dows搜索路径中,顺序是:当前目录;Path路径;Wi ndows;WidoWSsystem;Wi ndowsssystem32;1建立一种过程类型如果你对过程类型的变量只是一个指针的本质清楚的话,你就知道是 怎么回事了 。如:typemypoi nter=procedure(form:external;
3、VarHin st:Tha ndle;showform:mypo in ter;beginHinst:=Ioadlibrary(yproject_dll);Load 个 Dll,按文件名找。ShoWform:=getprocaddress(Hinst,showform/按函数名找,大小写敏感。如果你知道自动化 对象的本质就清楚了。showform(application.mainform);/ 找到函数入口指针就调用。FreeIibrary(Hi nst);en d;1把你的Form USeS到Dll中,你的Form用到的关联的单元也要 USeS进来这是最麻烦的一点,因为你的Form或许USe
4、S 了许多特殊的单元或函数2传递一个 APPIiCatiOn参数,用它建立 Form.八在DLL中建立一个TMDIChildForM1 Dll 中的 MDIForm.FormStyIe 不用为 fmMDIChild.2在CreateFOrm后写以下两句:function ShowForm(ma inFo rm:TForm):i nteger;StdCaIlForm1: TForm1;ptr:PL Onglnt;=(APPIiCatiOn.MainForm);/ 先把dll的MainForm 句柄保存起来,也无须释放,只不过是 替换一下ptr:=Lo ngl nt(ma in Form);/ 用
5、主调程序的 mai nF Orm 替换 DLL 的 Mai nForm。 Ma in Form 是特 殊的 WlNDoW ,它专门管理 APPIiCatiOn中的Forms资源./为什么不直接 APPIiCation.MainForm := mainForm, 因为 APPIiCation.MainForm 是只读属性 Form1:=TForm1.Create(mainForm);/ 用参数建立备注:参数是主调程序的 APPIiCati On .Mai nFormDLL源代码:Iibrary PrOjeCt2;USeSSysUtils,Classes,Dialogs,Forms,Unit2 i
6、n U ni t2.pas Form2;$R *.RESccc: Pchar;PrOCedUre OPenFo rm(ma inFo rm:TForm);StdCall;=(APPIiCati on.MainFo rm);=L On gI nt(mai nF orm);=TForm1.Create(mai nF orm);PrOCedUre In PUtCCC(Text: PChar);CCC := Text;PrOCedUre ShOWCCC;ShOWMeSSage(Stri ng(ccc);exportsOPenForm;In PUtCCC,ShOWCCC;en d.调用方源代码:Unit
7、Uni t1;in terfaceWin dows, Messages, SysUtils, Classes, Graphics, Con trols, Forms, Dialogs, StdCtrls;TForm1 = CIaSS(TFOrm)Butto n1: TBUtt on;Butto n2:Edit1: TEdit;PrOCedUre Butto n1Click(Se nder: TObject);PrOCedUre Butto n2Click(Se nder:PriVate PriVate declarati OnS PUbIiC PUbIiC declarati OnS impl
8、eme ntati On$R *.DFMEXter nalproject2.dll;EXternalPrOCedUre TForm1.Butt On 1Click(Se nder:Text:TeXt := PChar(Edit1.Text);/ OPenForm(Application.MainForm);/ 为了调 MDlCHILDInputCCC(Text);/为了实验DLL中的全局变量是否在各个应用程序间共享 en d;ProCedUre TForm1.Butt On 2Click(Se nder:/这里表明WlNDoWS 32位应用程序DLL中的全局变量也是在应用程序地址空 间中,16
9、位应用程序或许不同,没有做实验。1与POWerBUiIder混合编程在定义不定长动态数组方面在函数退出清理堆栈时老出现不可重现的地址错, 原因未明,大概与PB的编译器原理有关,即使 PB编译成二进制代码也如此。Windows的执行文件可以划分为两种形式程序和动态连接库(DLLS)。一般程序运行是用.EXE文件,但应用程序有时也可以 调用存储在DLL中的函数。当我们调用 Windows中的API函数的时候,实际上就是调用 存储在DLL中的函数。在如下几种情况下,调用 DLL是合理的:1) 不同的程序使用相同的 DLL ,这样只需要将 DLL在内存 中装载一次,节省了内存的开销。2) 当某些内容需
10、要升级的时候,如果使用 DLL只需要改变 DLL就可以了,而不需要把整个程序都进行变动。3) 由于DLL是独立于语言的,所以,当不同语言习惯的人共同开发一个大型项目的时候,使用 DLL便于程序系统的交流,当然,DeIPhi开发的DLL也可以在诸如ViSUaI BASIC,C+等系 统中使用。下面通过几个例子,说明 DeIPhi开发动态连接库的方法和规范。第一节动态连接库的构建和调用方法一、动态连接库构建File-New-Other-DLL WiZard这就创建了一个动态连接库的基本模块SySUtiIs, Classes;$R *.res把工程名改为Mydll ,并写入必要的函数Iibrary
11、mydll;SySUtiISQaSSeS,Dialogs,w in dows;fun ctio n TriPIe(N:1 nteger):begin resuIt:=N+3;fun ctio n DoubIe(N:I nteger):=N+2;function TriPIe1(N:ShOWmeSsage(计算 N+3 resuIt:function DoubIe1(N:messagebox(0,计算 N+2,计算 N+2,mb_ok);TriPIe n ame Tr,Double n ame DoTriPIeI name TrMDouble1 n ame DoMTriPIe,DoubIe,Tr
12、ipIe1,DoubIe1;其中函数:TriPIe :把传入值加三Double :把传入值加二TriPleI :把传入值加三并显示提示 DoUbleI :把传入值加二并显示提示从这个例子中可以看出 DLL程序的几个规则:1) 在DLL程序中,输出函数必须被声明为 StdCaIl ,以使用标准的Win32参数传递技术来代替优化的 RegiSterO(说明:在DeIPhi中RegiSter方式是缺省的调用约定,这个约定尽量采用寄存器来传递参数,传递次序从左到右,最多可用到 3个CPU的寄存器,如果参数多于 3个,剩下的就通过栈来传送,使用寄存器传送可保证参数传递的速度最快。而Stdcall方式是通
13、过Windows的标准调用来传递参数,传递秩序从左到右,这种方式适合调用 Windows的APl ,在DLL中,当然要使用这种方式)。2)所有的输出函数都必须列在 exports子句下面,这使的子例程 在DLL外部就可以看到。, Double1 n ame 列出了用户使用这个函数的接口名字。虽然别名不是必须的,但最好给个别名,以便用户程序更容易找到这个函数,同时还要指出,DeIPhi 6.0取消了 DeIPhi 5.0中允许使用的index ,如果还用Index 来指明接口名字,DeIPhi 6.0中将提示错误。实例中给出了两种提示方法,主要想说明一个问题:ShOWmeSSage(),是VCL
14、提供的函数,由于多次编译 VCL ,做出 的程序会比较大。而 messagebox(0,mb_ok) 是 Windows 提供的 API 函数,做 出的程序会比较小。这就是说,编写 DLL程序的时候,要尽量避免多次编译 VCL。作为一个实例,这里把两种方法都列出来了。保存编译:ProjrCt-Build Mydll这就完成了一个简单的动态连接库的编写。二、动态连接库的调用首先在implementation下做调用声明Con Stgdi32=mydll.dllfun ctio n triple( n:in teger):StdCaIl;external gdi32 n ame fun ctio
15、n DoUbIe(N: fun ctio n triple1( n: function Double1(N:exter nal gdi32 n ame 以后程序中就可以作为普通的函数使用了,例如:PrOCedUre TForm1.Butt On 1CIick(Se nder: Var N:N:=updow n1.positi on;edit1.text:=i nttostr(triple(N); en d;第二节 DLL中的DeIPhi窗体一、在DLL中放置窗的的方法在DLL中,除了放置标准的函数和过程以外,也可以放置 已经做好的的delphi窗体,也可以把做好的窗体供其它程序使 用,方法是:
16、1)首先按普通方法制作窗体,不过在 in terface区域,对接 口函数做如下声明function CreatefOrm(Capt:Stri ng):Stri ng;2)在implementation下加入接口函数function Createform(Capt:StdCalI;Var Form1:form1:=Tform1.Create(applicatio n);form1.show;form1.capti on:=capt;3)制作DLL动态连接库,但要声明:Un it1 in un it1.pas写入接口标示符CreatefOrm n ame Myform4) 调用窗体的程序按普通方
17、法制作,但是 在implementation下首 先声明要调用的 DLL函数myFormdll.dllfun ctio n CreatefOrm(Capt:PrOCedUre TForm3.Butt On 1Click(Se nder:Var n, m:m:=我的窗体;Createform(m);Var n,m:二、DLL中的调用窗体时的数据传递在窗体调用时,可以用普通的函数方法传递数据,下面举 个例子。1)建立窗体做一个改变颜色窗体,放在 DLL中,可以用普通的方法来做,但要作如下声明:fun Ctio n mycolor(col:lo ngin t):l Ongin t;function
18、GetCoIor:1 Ongin t;其中,mycolor为构造窗体;Getcolor为传递颜色数据。在implementatiOn区声明一个窗体内全局的变量Var CoIor1:1 Ongint;下面写出相应的程序fun ctio n mycolor(col:l On gi nt):lo ngin t;form1.pa nel1.Color:=col;form1.edit1.Text:=in ttostr(form1.pa nel1.Color);result:=CoIor1;function Getcolor:PrOCedUre TForm1.ScrollBar1Cha nge(Se nd
19、er:Pan eI2.CoIor:=RGB(SCroIIBar1.Positio n,ScrollBar2 .P ositio n,ScrollBar3 .P ositio n); edit2.Text:=i nttostr(pa nel2.Color);color1:=Pa nel2.Color;PrOCedUre TForm1.Butt On 2CIick(Se nder:Free; /析构 Form12)建立动态连接库运行成功后,再建立动态连接库:Iibrary FormDLL;从文件调入MyColor name My, Getcolor n ame Get3)建立调用的程序首先声明要调用的 DLL函数formDll.dllfun ctio n MyCoIor(Col:lo ngi nt):l On gi nt; fun ctio n Getcolor:lo ngi nt;然后写出相应的程序Mycolor(color);PrOCedUre TForm1.Butt On 2Click(Se nder:color:=getcolor;我们可以看到,在改变颜色的窗体中做了颜色变化后,当前窗 体的颜色将发生变化。han dle
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1