ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:27.57KB ,
资源ID:17574155      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/17574155.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Delphi下的DLL编程Word文件下载.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Delphi下的DLL编程Word文件下载.docx

1、在进行后面的讲解之前,我想大家应该先清楚一个概念:例程声明的是一个指针变量,调用函数/过程,其实是通过指针转入该函数/过程的执行代码。我们先尝试用Delphi来建立一个自己的DLL文件。这个DLL包含一个标准的目录删除(包含子目录及文件)函数。建立DLL通过Delphi建立一个DLL是很容易的。New一个新Project,选择DLL Wizard,然后会生成一个非常简单的单元。该单元不象一般的工程文件以program开始,而是以library开始的。该工程单元缺省引用了SysUtils、Classes两个单元。可以直接在该单元的uses之后,begin end部分之前添加函数/过程代码,也可以

2、在工程中添加包含代码的单元,然后该单元将会被自动uses。接下来是编写DLL例程的代码。如果是引用单元里的例程,需要通过声明时添加export后缀引出。假如是直接写在library单元中的,则不必再写export了。最后一步是在library单元的begin语句之上,uses部分及函数定义之下添加exports部分,并列举需要引出的例程名称。注意仅仅是名称,不包含procedure或function关键字,也不需要参数、返回值和后缀。exports语句后的语法有三种形式(例程指具体的函数/过程):exports例程名;exports例程名index索引值;name新名称;索引值和新名称便于其他

3、程序确定函数地址;也可以不指定,如果没有使用Index关键字,Delphi将按照exports后的顺序从1开始自动分配索引号。Exports后可跟多个例程,之间以逗号分隔。编译,build最终的dll文件。需注意的格式为了保证生成的DLL能正确与C+等语言兼容,需要注意以下几点:尽量使用简单类型或指针作为参数及返回值的类型。这里的简单类型是指C+的简单类型,所以string字符串类型最好转换成Pchar字符指针。直接使用string的DLL例程在Delphi开发的程序中调用是没有问题的(有资料指出需加入ShareMem做为第一单元以确保正确),但如果使用C+或其他语言开发的程序调用,则不能保证

4、参数传递正确;虽然过程是允许的,但是最好习惯全部写成函数。过程则返回执行正确与否的true/false;对于参数的指示字比如const(只读)、out(只写)等等,为保证调用的兼容性,最好使用缺省方式(缺省var,即可读写的地址);使用stdcall声明后缀,以保证正确的异常处理。16位DLL无法通过这种方式处理异常,所以还得在例程最外层用Try Except将异常处理掉;一般不使用far后缀,除非为了保持与16位兼容。范例代码DLL工程单元:library FileOperate;uses SysUtils, Classes, uDirectory in uDirectory.pas;$R

5、*.res exports DeleteDir;beginend. 函数功能实现单元:unit uDirectory;interface Classes, SysUtils; function DeleteDir(DirName : Pchar):boolean;export;stdcall;implementation function DeleteDir(DirName :var FindFile: TSearchRec; s : string;= DirName; if copy(s,length(s),1) then s := s+ ; if DirectoryExists(s) th

6、en begin if FindFirst(s + *.*, faAnyFile, FindFile) = 0 then begin repeat if FindFile.Attr faDirectory then begin /文件则删除 DeleteFile(s + FindFile.Name); end else begin /目录则嵌套自身 if (FindFile.Name .) and (FindFile.Name .) then DeleteDir(Pchar(s + FindFile.Name); end; until FindNext(FindFile) user32.txt

7、然后打开user32.txt文件,找到Exports from USER32.dll行,之下的部分就是DLL例程定义了,比如: RVA Ord. Hint Name - - - 00001371 1 0000 ActivateKeyboardLayout 00005C20 2 0001 AdjustWindowRect 0000161B 3 0002 AdjustWindowRectExName列就是例程的名称,Ord就是该例程索引号。注意,该工具是不能得到例程的参数表的。如果参数错误,调用DLL例程会引起堆栈错误而导致调用程序崩溃。调用代码建立一个普通工程,在Main窗体上放置一个TShel

8、lTreeView控件(Samples页),再放置一个按钮,添加代码如下:external FileOperate.dll;procedure TForm1.Button1Click(Sender: TObject); if DirectoryExists(ShellTreeView.Path) then if Application.MessageBox(Pchar(确定删除目录+QuotedStr(ShellTreeView.Path)+吗?), Information,MB_YESNO) = IDYes then if DeleteDir(PChar(ShellTreeView.Path

9、) then showmessage(删除成功);该范例调用的就是前面建立的DLL。注意,声明时要包括stdcall后缀,这样才能保证调用Delphi开发的DLL的例程中类似PChar这样的参数值传递正确。大家有兴趣可以试验一下,不加入stdcall或者safecall后缀执行上面代码,将不能保证成功传递字符串参数给DLL函数。调试方法在Delphi主菜单Run项目中选择Parameters,打开“Run Parameters”对话框。在Host Application中填入一个宿主程序(该程序调用了将要调试的DLL),还可以在Parameters中输入参数。保存内容,然后就可以在DLL工程中

10、设置断点、跟踪/单步执行了。Run该DLL工程,然后将运行宿主程序。执行会调用DLL的操作,然后就能跟踪进入该DLL的代码,接下来的调试操作和普通程序是一样的。因为操作系统或其他软件影响的原因,可能会出现进行了上述步骤仍然无法正常跟踪/中断DLL代码的情况。这时可以试试在菜单Project|Options对话框的Linker页面里将EXEand DLL Options中的IncludeTD32debuginfo及includeremotesymbols两个选项选中。假如还是不能中断 -_-| 那只好另外建立一个引用执行代码单元的应用程序,写代码调用例程调试完成后再编译DLL了(其实该方法有时候

11、蛮方便的,但有时候亦非常麻烦)。引入文件DLL比较复杂时,可以为它的声明专门创建一个引入单元,这会使该DLL变得更加容易维护和查看。引入单元的格式如下:unitMyDllImport;ImportunitforMyDll.dll interface procedureMyDllProc; implementation procedureexternalMyDll1;这样以后想要使用MyDll中的例程时,只要简单的在程序模块中的uses子句中加上MyDllImport即可。其实这仅仅是种方便开发的技巧,大家打开Windows等引入windows API的单元,可以看到类似的做法。动态(显式)调用

12、DLL 前面讲述静态调用DLL时提到,DLL会在启动调用程序时即被调入。所以这样的做法只能起到公用DLL以及减小运行文件大小的作用,而且DLL装载出错会立刻导致整个启动过程终止,哪怕该DLL在运行中只起到微不足道的作用。使用动态调用DLL的方式,仅在调用外部例程时才将DLL装载内存(引用记数为0时自动将该DLL从内存中清除),从而节约了内存空间。而且可以判断装载是否正确以避免调用程序崩溃的情况,最多损失该例程功能而已。动态调用虽然有上述优点,但是对于频繁使用的例程,因DLL的调入和释放会有额外的性能损耗,所以这样的例程则适合使用静态引入。调用范例DLL动态调用的原理是首先声明一个函数/过程类型

13、并创建一个指针变量。为了保证该指针与外部例程指针一致以确保赋值正确,函数/过程的声明必须和外部例程的原始声明兼容(兼容的意思是1、参数名称可以不一样;2、参数/返回值类型至少保持可以相互赋值,比如原始类型声明为Word,新的声明可以为Integer,假如传递的实参总是在Word的范围内,就不会出错)。接下来通过windows API函数LoadLibrary引入指定的库文件,LoadLibrary的参数是DLL文件名,返回一个THandle。如果该步骤成功,再通过另一个API函数GetProcAddress获得例程的入口地址,参数分别为LoadLibrary的指针和例程名,最终返回例程的入口指

14、针。将该指针赋值给我们预先定义好的函数/过程指针,然后就可以使用这个函数/过程了。记住最后还要使用API函数FreeLibrary来减少DLL引用记数,以保证DLL使用结束后可以清除出内存。这三个API函数的Delphi声明如下:Function LoadLibrary(LibFileName:PChar):THandle;Function GetProcAddress(Module:ProcName:TfarProc;Procedure FreeLibrary(LibModule:THandle);将前面静态调用DLL例程的代码更改为动态调用,如下所示:type TDllProc = fun

15、ction (PathName : LibHandle: THandle; DelPath : TDllProc; LibHandle := LoadLibrary(PChar(FileOperate.dll); if LibHandle = 32 then begin try DelPath := GetProcAddress(LibHandle,PChar(DeleteDir); if DelPath(PChar(ShellTreeView.Path) then finally FreeLibrary(LibHandle);16位DLL的动态调入下面将演示一个16位DLL例程调用的例子,该

16、例程是windows9x中的一个隐藏API函数。代码混合了静态、动态调用两种方式,除了进一步熟悉外,还可以看到调用16位DLL的解决方法。先解释一下问题所在:我要实现的功能是获得win9x的“系统资源”。在winNT/2000下是没有“系统资源”这个概念的,因为winNT/2000中堆栈和句柄不再象win9X那样被限制在大小。为了取该值,可以使用win9x的user dll中一个隐藏的API函数GetFreeSystemResources。该DLL例程必须动态引入。如果静态声明的话,在win2000里执行就会立即出错。这个兼容性不解决是不行的。所以必须先判断系统版本,如果是win9x再动态加载

17、。检查操作系统版本的代码是: OSversion _OSVERSIONINFOA;FWinVerIs9x: Boolean;OSversion.dwOSVersionInfoSize:=sizeof(_OSVERSIONINFOA);GetVersionEx(OSversion);FWinVerIs9x:=OSversion.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS;End;以上直接调用API函数,已在Windows单元中被声明。function LoadLibrary16(LibraryName: PChar): external kernel32 index 35;procedure FreeLibrary16(HInstance: THandle); external kernel32 index 36;function GetProcAddress16(Hinstance: ProcName: Pointer; external kernel32 index 37;function TWinResMonitor.GetFr

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1