句柄、路径、dll.docx_第1页
句柄、路径、dll.docx_第2页
句柄、路径、dll.docx_第3页
句柄、路径、dll.docx_第4页
句柄、路径、dll.docx_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

句柄的概念:所谓句柄实际上是一个数据,是一个Long (整长型)的数据。 句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。 从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。 如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢? 为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。 句柄地址(稳定)记载着对象在内存中的地址对象在内存中的地址(不稳定)实际对象 本质:WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。 但是必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门票总是不同的一个座位是一样的道理。API(Application Programming Interface,应用程序编程接口)HWND:全称是 Handle of Window,是一个窗体的句柄,基于THandle。HDC :Handle to a device context (DC). 即指向一个设备上下文DLL:Dynamic-Link Libraries(动态链接库)exceptionkspnn.例外,除外;反对,批评;法律异议,反对ExtractFileDir 获取文件路径getcurrentdir:获取当前路径Delphi GetModuleFileName函数的用法(可以获取项目的路径,桌面的路径,我的文档的路径)2011-04-13 09:00:50|分类:Delphi|字号订阅function GetModuleFileName(Module: HMODULE; Buffer: PChar; BufLen: Integer): Integer;Module模块的句柄模块,其文件名是必需的。Buffer是一个缓冲区,它接收文件的名称。BufLen是在缓冲区的字节数。GetModuleFileName返回写入缓冲区的字节数。警告:GetModuleFileName并不总是成功的。在应用程序调用方式,在/ proc文件系统的存在,以及其他因素的不同,有些时候可能会返回GetModuleFileName一个不完全合格的名称,或在某些情况下,没有在所有的文件名。请务必在使用前要检查这个返回值函数的结果。当前项目的路径 function GetCurrPath(IsAutoGetDll: boolean = true): string; 当前项目的全部的路径(包括exe) function GetCurrDllpath: string; 获取桌面 function GetDeskeptPath: string; 获取我的文档 function GetMyDoumentpath: string;- 过程名: GetCurrPath 作者: 张志峰 日期: 2010.11.23 参数: 无 返回值: String 说明: 获取当前项目的路径-function GetCurrPath(IsAutoGetDll: boolean = true): string;var ModName: array0.MAX_PATH of Char;begin if ModuleIsLib and IsAutoGetDll then begin GetModuleFileName(HInstance, ModName, SizeOf(ModName); / 取得当前项目的路径 Result := ExtractFilePath(ModName); end else Result := ExtractFilePath(ParamStr(0);end;- 过程名: GetCurrDllpath 作者: 张志峰 日期: 2010.11.23 参数: 无 返回值: String 说明: 获取当前项目的路径包括exe-function GetCurrDllpath: string;var p: pchar;begin getmem(p, 255); try getmodulefilename(hinstance, p, 255); result := trim(strpas(p); finally freemem(p, 255); end;end;function GetShellFolders(strDir: string): string;const regPath = SoftwareMicrosoftWindowsCurrentVersionExplorerShell Folders;var Reg: TRegistry; strFolders: string;begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_CURRENT_USER; if Reg.OpenKey(regPath, false) then begin strFolders := Reg.ReadString(strDir); end; finally Reg.Free; end; result := strFolders;end;获取桌面function GetDeskeptPath: string;begin Result := GetShellFolders(Desktop); /是取得桌面文件夹的路径end;获取我的文档function GetMyDoumentpath: string;begin Result := GetShellFolders(Personal); /我的文档end;Delphi中DLL的创建和使用 1.DLL简介; 2.调用DLL; 3.创建DLL; 4.两个技巧; 5.初始化; 6.例外处理。 1、DLL简介 DLL是Dynamic-Link Libraries(动态链接库)的缩写,库里面是一些可执行的模块以及资源(如位图、图标等)。可以认为DLL和EXE基本上是一回事,只是DLL不能直接执行,而必须由应用程序或者其他DLL调用。DLL为应用程序间的资源共享提供了方便,同时也是多语言混合编程的重要手段。由此可见学习使用DLL是Windows程序员必须掌握的一项重要技术。 2、如何调用DLL 在Delphi中有两种方法调用DLL中的函数和过程,即外部声明或者动态加载。 外部声明 在Delphi中外部声明是访问外部例程最容易和最常用的方式,有两种声明方式:通过名字、通过索引号。举例如下:在MYDLL.DLL中有两个函数和一个过程,则其外部声明可以写成: function test1:integer;external mydll; /直接通过名称调用test1(注意名称大小写敏感)。 function test11:integer;external mydll name test1; /通过名称调用test1,在程序中使用新名称(原名称仍然大小写敏感)。 procedure test2;external mydll index 1; /通过索引号调用TEST2。程序中可以用与DLL中不一样的名称. 使用外部声明的缺点是程序启动时如果找不到mydll.dll将无法运行,即使没有调用其中的模块。 动态加载的方法可以避免这种情况。 动态加载 通过调用Windows API中的相关函数,将DLL调入内存并获得指向函数或过程的指针,执行完模块后释放内存。除了节约内存外,这种方法的一个很大的优点是能处理找不到dll或者在装入过程中出错的情况。这样即使某个dll有问题,应用程序的其他部分仍然能够正常运行。动态加载的例子如下: var hDll:THandle; Test1:function:integer; begin hDll:=LoadLibrary(mydll.dll); if hDllNew对话框中选择DLL),当然也可以自己写,现在这个Project是这样的: library Project1; uses SysUtils,Classes; begin end. 当然这是一个空DLL,现在让我们来加入一个函数,让他成为我们的第一个可以使用的DLL。完成后的文件是这样的: library dll1; uses SysUtils,Classes; function Test1(a,b:integer):integer; begin Result:=a+b; end; exports Test1 index 1; begin end. 在这个DLL里我们声明了一个加法函数,然后用exports语句输出它,只有被输出的函数或过程能被其他程序调用。exports语句后的语法是:函数名 index ,index 是为函数手工指定索引号,以便其他程序确定函数地址;也可以不指定,如果没有使用Index关键字,Delphi将按照exports后的顺序从1开始自动分配索引号。现在我们可以调用这个DLL了,下面给出一个实例,运行后form1的标题将变成“1+2=3”: 声明部分:function Test1(a,b:integer):integer;external dll1; 注意此处是大小写敏感的。 运行部分:form1.caption:=1+2=+inttostr(test1(1,2); 、使用DLL的两个技巧 把现有的项目改成DLL 学会制作DLL以前,大多数程序员手中都积攒下来不少已经完成了的项目,如果现在需要把这些项目做成DLL而不是可执行文件,重新写一遍显然是没有必要的,只要按照下面的步骤对已有的项目文件进行修改就可以了: 打开项目文件(.DPR),删除单元底部begin和end.之间的所有语句(一般情况下这些语句是由Delphi自动生成的)。如果项目中没有用到Form,则从uses子句中删除表单单元(Form),然后转到第步。 对项目进行修改,令除Main Form之外的所有Form都是动态生成的,这样我们只要在DLL输出的一个函数或者过程中生成Main Form,即可调用执行整个项目。我们假设Main Form的名字是MyMainForm,项目的名字是MyDll,现在在单元底部的begin语句之前加入一个过程,过程的名字为RunMyDll,这个过程将动态生成Main Form,从而运行整个项目。RunMyDll的写法如下: procedure InitDll2; begin Application.CreateForm(TMyMainForm, MyMainForm); MyMainForm.Show; /如果MyMainForm不可视则需要这一句. end; 如果想要输出其他函数或者过程,而原来的项目中没有,则可以在单元底部的begin语句之前加入这些代码。 在单元底部的begin语句之前加入一个exports小节,然后写出所有想要输出的函数或过程的名字(最好指定索引号)。注意如果执行了第步,一定要输出RunMyDll过程。 将项目文件顶部的保留字program改为library。 编译。 现在就可以在其他程序中调用本项目中的函数和过程了,只要执行RunMyDll就可以执行这个项目,和执行原来的可执行文件一模一样。 创建一个引入文件 如果DLL比较复杂,则为它的声明专门创建一个引入程序单元将是十分有意义的,并且会使这个DLL变得更加容易维护。引入单元的格式如下: unit MyImport; Import unit for MyDll.Dll interface procedure RunMyDll; implementation procedure RunMyDll;external MyDll index 1; end. 这样以后想要使用MyDll中的例程时,只要简单的在程序模块中的uses子句中加上MyImport即可。 5、DLL的初始化和善后工作 一般的DLL不需要做初始化和善后工作,因此大部分读者可以跳过这一节。但如果你想让你的DLL在被载入时先作一些初始设定,或者退出时释放资源,则可以有三种方法达到目的: 利用Unit的Initalization与Finalization这两个小节 可以在Unit的这两个小节中安排Unit的进入和退出,但是Program与Library并没有这两个部分,所以只能写在Unit中。 利用ExitProc变量 在Library的begin.end.中间是可以写代码的,这里可以放置DLL初始化代码。如果想要做善后工作,则可以利用ExitProc变量。我们首先在初始化代码中把ExitProc中包含的默认的善后过程地址保存下来,然后把自定义的过程的地址赋给它,这样DLL退出时就会执行我们制定的程序;在自定义的过程的最后,把ExitProc恢复原来的默认值,以便DLL能够继续完成原来默认的善后工作。下面是示例: library MyDLL; . OldExitProc: pointer; . procedure MyExitProc; begin . /善后程序 ExitProc := OldExitProc; end; . begin . /初始化程序 OldExitProc := ExitProc; ExitProc := MyExitProc; end. 利用DllProc变量 和ExitProc一样,DllProc也是一个在Systemd单元中预定义的变量。在使用DLLProc时, 必须先写好一个具有以下原型的程序: procedure DLLHandler(Reason: integer); 并在library的begin.end.之间, 将这个DLLHandler程序的执行地址赋给DLLProc中, 这时就可以根据参数Reason的值分别作出相应的处理。另外注意要将Windows单元加入uses子句。示例如下: library TestDLL; . procedure MyDLLHandler(Reason: integer); begin case Reason of DLL_Process_Attach: /整个DLL的初始化代码 DLL_Process_Detach: /整个DLL的善後程序 DLL_Thread_Attach: /当主叫端开始一个Thread时 DLL_Thread_Detach: /当主叫端终止一个Thread时 end; end; . begin . /初始化代码 DLLProc := MyDLLHandler; MyDLLHandle(DLL_Process_Attach); end. 由上例可以知道,当DLL支援多进程(Thread)的处理时, DllProc非常适合使用。 6、DLL中的例外处理 在用Delphi制作DLL时, 在例外处理方面请留意以下三点: 如果uses子句中没有SysUtils话,无法使用例外处理。 如果DLL中没有对例外进行处理的话,这个例外会想完传导到主叫端的应用程序。如果该应用程序也是Delphi写的话, 这个例外可以由主叫端进行处理。 承上, 如果主叫端的程式不是Delphi或Borland C+ Builder,则例外以作业系统错误的形式来处理,例外编号是$0EEDFACE,ExceptionInformation中第一个进入点是例外发生的地址,第二个进入点是指向的Delphi例外物件的引用。 Important note about DLL memory management: ShareMem must be the first unit in your librarys USES clause AND your projects (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL-even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. uses SysUtils, Classes, Unit1 in Unit1.pas; Exports EnableMouseHook, /只要把这两个函数输出就可以了, DisableMouseHook;/不会不懂函数的意思吧_。 $R *.res begin end. unit1 unit Unit1; interface Uses Messages,Windows; var hHk: HHOOK;/钩子的句柄值。 function MouseHookProc(nCode: Integer;WParam: WPARAM;LParam: LPARAM): LRESULT;stdcall; /鼠标钩子的回调函数,即是用它来处理得到消息后要干什么。这里我只是发送一个/WM_PASTE消息。 /nCode参数是Hook的标志,一般只关心小于0时。看下面的详细说明 /WParam参数表示鼠标消息的类型 /LParam参数是一个指向 TMOUSEHOOKSTRUCT 结构的指针。结构包含了鼠标消息的状态,我只用了hwnd一个 /即鼠标消息要传递给的窗口句柄。 /返回值如果不是0的话windows就把这个消息丢掉,其它的程序就不会再收到这个消息了。 function EnableMouseHook:Boolean; stdcall; export; function DisableMouseHook:Boolean; stdcall; export;/两个函数都是Boolean类型,成功都是返回True implementation function MouseHookProc(nCode: Integer;WParam: WPARAM;LParam: LPARAM): LRESULT;stdcall; var MouseHookStruct: TMOUSEHOOKSTRUCT;/这个结构Delphi在Windows单元有定义,直接用就可以了。 nState: SHORT;/得到键盘状态的GetKeyState函数的返回值。这是一个16位的数。 begin Result := 0; /最好首先给他一个返回值,不然会有警告的!记住这可不是C语言。 /当nCode小于0时表示还有其它的Hook,必须把参数

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论