句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。 句柄实际上是一个标识符,是用来标识对象或者项目的,句柄是一个 32 位的正整数,Microsoft® Windows® 用它来识别窗体或其他对象,例如字体或位图。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用这个句柄,以引用相应的对象。在WINDOWS编程中会用到大量的句柄,比如:HINSTANCE(实例句柄),HBITMAP(位图句柄),HDC(设备描述表句柄),HICON(图标句柄)等等,这当中还有一个通用的句柄HANDLE。 句柄实际上是一种指向某种资源的指针,但与指针又有所不同:指针对应着一个数据在内存中的地址,得到了指针就可以自由地修改该数据。Windows并不希望一般程序修改其内部数据结构,因为这样太不安全。所以Windows给每个使用GlobalAlloc等函数声明的内存区域指定一个句柄(本质上仍是一个指针,但不要直接操作它),平时你只是在调用API函数时利用这个句柄来说明要操作哪段内存。当你需要对某个内存进行直接操作时,可以使用GlobalLock锁住这段内存并获得指针来直接进行操作。 “句柄”(handle),handle的本意是把柄,把手的意思。是你与操作系统打交道的东西。举个例子:比如你做了亏心事(我说的是比如,呵呵),不幸让我抓住了把柄,那么我让你做什么你就得做什么,因为你的把柄在我这。我们编程的时候也是这样,比如我们要想操纵一个窗口,那我们就必须“抓住它的把柄”,只有这样,我们才能改变它的属性,改变它的式样,甚至销毁它(狠了点儿)。我们再引用一个通俗一点的例子,比如你考上了大学,入学后,学校(操作系统)会给你一个学生证号。注意,这个号码是学校指定的,你无法自选。有了这个号码(学生证,假设一证多用)就可以享受学校提供的服务:如你就可以去图书馆借书,去食堂吃饭,去教室上课等等。但你不能到食堂里买啤酒,因为学校不允许这种服务。而在计算机中系统提供的服务就是API调用,你有了HANDLE,就可以理直气壮地向系统提出调用API的服务。而指针的权力就大多了,有了指针你可以到处去喝酒,打架,学校(操作系统)管不着,所以句柄和指针的区别在于句柄只能调用系统提供的服务。而句柄虽然是一个能相互区别的号码,但与我们普通的ID号又有区别,普通的ID号是可以由程序员自己定义的,而句柄不行,它是对象生成时系统指定的,是为了区别系统中存在的各个对象,这个句柄不是由程序员赋给的。实际应用中,最常用的就是文件句柄和窗口句柄。例如,窗口句柄的值是一个长整数,每个窗体都用一个句柄来表示。所以句柄是不会重复的,很多的函数都会用到窗体的句柄。
Windows 句柄 Delphi从Windows 引入了不少数据类型,其中句柄最重要。这种数据类型名为THandle,该类型在Windows 单元中定义: type THandle = LongWord; 句柄数据类型通过数字实现,但并不当数字用。在Windows 中,句柄是一个系统内部数据结构的引用。例如,当你操作一个窗口,或说是一个Delphi 窗体时,系统会给你一个该窗口的句柄,系统会通知你:你正在操作142号窗口,就此,你的应用程序就能要求系统对142号窗口进行操作——移动窗口、改变窗口大小、把窗口极小化为图标,等等。实际上许多Windows API 函数把句柄作为它的第一个参数,如GDI (图形设备接口)句柄、菜单句柄、实例句柄、位图句柄等等,不仅仅局限于窗口函数,。 换句话说,句柄是一种内部代码,通过它能引用受系统控制的特殊元素,如窗口、位图、图标、内存块、光标、字体、菜单等等。Delphi中很少需要直接使用句柄,因为句柄藏在窗体、位图及其他Delphi对象的内部。当你要调用Delphi不支持的Windows API 函数时,句柄才会有用。 现在举一个简单的Windows句柄例子,完善这节内容。例WHandle 程序的窗体很简单,只有一个按钮。正如下面主窗体文本所定义的那样,我在代码中添加了窗体的OnCreate 事件和按钮的OnClick 事件: object FormWHandle: TFormWHandle Caption = 'Window Handle' OnCreate = FormCreate object BtnCallAPI: TButton Caption = 'Call API' OnClick = BtnCallAPIClick end end 窗体一创建,程序就会通过窗体本身的Handle 属性,获取窗体对应的窗口句柄。调用IntToStr ,把句柄数值转换为一个字符串,然后再把它添加到窗体标题中,如图9.1: procedure TFormWHandle.FormCreate(Sender: TObject); begin Caption := Caption + ' ' + IntToStr (Handle); end; 因为FormCreate 是窗体类的方法,它可直接访问同类的其他属性和方法。因此,在这个过程中我们能够直接访问窗体的Caption 属性和Handle 属性。 图 9.1: 例 WHandle 显示窗体句柄,每次运行程序得到的句柄值不同 如果你多此次执行该程序,通常会获得不同的句柄值。这个值实际上是由Windows 操作系统确定并返回给应用程序的。(句柄从来不是由程序决定的,而且句柄没有预定义值,句柄是由系统决定的,每执行一次程序,产生一个新值。) 当你单击按钮,程序将调用Windows API 函数SetWindowText,它会根据第一个传递参数改变窗口的标题。更准确地说,所用的API 函数其第一个参数是需要修改窗体的句柄: procedure TFormWHandle.BtnCallAPIClick(Sender: TObject); begin SetWindowText (Handle, 'Hi'); end; 这段代码与前面所讲的事件处理程序等效,它通过给窗体的Caption 属性赋一个新值,改变窗体的标题。对上面这种情况,调用一个API 函数没有什么意义,因为用Delphi来做更简单。然而有些API在Delphi中没有相应的函数,就需要直接调用API