句柄是怎么回事呢? ( 积分: 100 )

  • 主题发起人 主题发起人 shirely.hu
  • 开始时间 开始时间
S

shirely.hu

Unregistered / Unconfirmed
GUEST, unregistred user!
句柄是怎么回事呢?麻烦高手回答的详细些,谢谢
 
句柄是怎么回事呢?麻烦高手回答的详细些,谢谢
 
个人看法,仅供参考

句柄就是一个标识符号,和我们在数据库里面的唯一ID那样,他在Windows是唯一的,Windows通过这个东西来发送消息等等,其实它就是一个指针,楼下大虾继续


------------------------------转自网络
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1863299
[:D]句柄是一个整数,是系统用来唯一标识一个设备资源的记号。
句柄概念在WINDOWS编程中是一个很重要的概念,在许多地方都扮演着重要的角色。但由此而产生的句柄概念也大同小异,比如:
<<Microsoft Windows 3 Developer's Workshop>>(Microsoft Press,by Richard Wilton)一书中句柄的概念是:在Windows环境中,句柄是用来标识项目的,这些项目包括:
*.模块(module)
*.任务(task)
*.实例(instance)
*.文件(file)
*.内存块(block of memory)
*.菜单(menu)
*.控制(control)
*.字体(font)
*.资源(resource),包括图标(icon),光标(cursor),字符串(string)等
*.GDI对象(GDI object),包括位图(bitmap),画刷(brush),元文件(metafile),调色板(palette),画笔(pen),区域(region),以及设备描述表(device context)。
WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。
在<<WINDOWS编程短平快>>(南京大学出版社)一书中是这么说的:句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。
从上面的2个定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。在WINDOWS编程中会用到大量的句柄,比如:HINSTANCE(实例句柄),HBITMAP(位图句柄),HDC(设备描述表句柄),HICON(图标句柄)等等,这当中还有一个通用的句柄,就是HANDLE,比如下面的语句:
HINSTANCE hInstance;
可以改成:
HANDLE hInstance;
上面的2句语句都是对的。
一个WINDOWS应用程序可以用不同的方法获得一个特定项的句柄。许多API函数,诸如CreateWindow,GlobalAlloc,OpenFile的返回值都是一个句柄值。另外,WINDOWS也能通过应用程序的引出函数将一个句柄作为参数传送给应用程序,应用程序一旦获得了一个确定项的句柄,便可在WINDOWS环境下的任何地方对这个句柄进行操作。其实句柄的大量使用已经影响到了每一个WINDOWS的程序设计。
句柄只有当唯一的确定了一个项目的时候,它才开始有意义。句柄对应着项目表中的一项,而只有WINDOWS本身才能直接存取这个表,应用程序只能通过API函数来处理不同的句柄,举个例子来说吧!比如:我们可以为我们的应用程序申请一块内存块,通过调用API函数GlobalAlloc,来返回一个句柄值:
hMem=GlobalAlloc(......);
其实现在hMem的值只是一个索引值,不是物理地址,应用程序还不能直接存取这块内存。这儿还有一个话外题,就是,一般情况下我们在编程的时候,给应用程序分配的内存都是可以移动的或者是可以丢弃的,这样能使有限的内存资源充分利用,所以,在某一个时候我们分配的那块内存的地址是不确定的,因为他是可以移动的,所以得先锁定那块内存块,这儿应用程序需要调用API函数GlobalLock函数来锁定句柄。如下:
lpMem=GlobalLock(hMem);
这样应用程序才能存取这块内存。
 
个人看法:
句柄是一个数值,通过这个数值可以查找出其代码在内存中的相应位置,如窗口句柄,程序句柄,控件句柄等等,如知道一个窗口句柄,则知道这段窗口的代码在内存中的位置.句柄在特定范围唯一的,如控件句柄在对应的窗体句柄是唯一的,要查找控件句柄,可能要先知道该窗体的句柄.
 
在调用 DLL 函数前必须理解的另外一个重要概念是句柄。句柄是一个 32 位的正整数,Microsoft® Windows® 用它来识别窗体或其他对象,例如字体或位图。

在 Windows 中,窗口可以有许多种。窗口可以是屏幕上的一块矩形封闭区域,比如您熟悉的应用程序窗口。窗体上的控件(例如列表框或滚动条)也可以是窗口,但并不是所有类型的控件都是窗口。桌面上的图标和桌面本身也是窗口。

因为所有这些类型的对象都是窗口,所以 Windows 可以用类似的方式处理它们。Windows 给每个窗口一个唯一的句柄,通过句柄操纵该窗口。许多 API 函数可返回句柄或者接受句柄作参数。

创建窗口时,Windows 给它指派一个句柄,窗口消失后句柄被释放。虽然句柄在窗口的整个生存期内保持不变,但不能保证某窗口在被损坏并重新创建后还使用原来的句柄。所以,如果在变量中存储了一个句柄,请记住窗口损坏后句柄就失效了。

例如 GetActiveWindow 函数就可以返回窗口的句柄,这里的窗口是一个当前活动的应用程序窗口。GetWindowText 函数接受窗口的句柄,如果该窗口有标题,则返回标题。下面的过程用 GetActiveWindow 返回活动窗口的句柄,用 GetWindowText 返回该窗口的标题:

Declare Function GetActiveWindow Lib "user32" () As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal Hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Function ActiveWindowCaption() As String
Dim strCaption As String
Dim lngLen As Long

' 创建由空字符填充的字符串。
strCaption = String$(255, vbNullChar)
' 返回字符串长度。
lngLen = Len(strCaption)

' 调用 GetActiveWindow,返回活动窗口的句柄,
' 把句柄连同字符串和字符串长度一起传递给 GetWindowText。
If (GetWindowText(GetActiveWindow, strCaption, lngLen) > 0) Then
' 返回 Windows 写到字符串中的值。
ActiveWindowCaption = strCaption
End If
End Function
GetWindowText 函数有 3 个参数:窗口句柄;准备接受窗口标题的 NULL 结束字符串;以及该字符串的长度。
 
句柄是Wi n 3 2 定义的3 2 位数字,标识某些对象实例。这里所说的对象是Wi n 3 2 对象,不是D e l p h i 对象。在Wi n 3 2 下有不同类型的对象:内核对象、用户对象和G D I 对象。内核对象应用于事件、文件映射对象和进程等项目。用户对象指窗口对象如编辑框、列表框和按钮等。GDI 对象指位图、画刷和字体等。
 
句柄是怎么回事呢?
简单一句话:一个整数。
 
句柄本质

一、书上定义:

<<Microsoft Windows 3 Developer's Workshop>>(Microsoft Press,by Richard Wilton)
在Windows环境中,句柄是用来标识项目的,这些项目包括:模块(module)、任务(task)、实例 (instance)、文件(file)、内存块(block of memory)、菜单(menu)、控制(control)、字体(font)、资源(resource),包括图标(icon),光标 (cursor),字符串(string)等、GDI对象(GDI object),包括位图(bitmap),画刷(brush),元文件(metafile),调色板(palette),画笔(pen),区域 (region),以及设备描述表(device context)。

<<WINDOWS编程短平快>>(南京大学出版社):
句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。

二、MFC源代码:

#ifdef STRICT
typedef void *HANDLE;
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif

DECLARE_HANDLE(HMODULE);
DECLARE_HANDLE(HINSTANCE);
DECLARE_HANDLE(HLOCAL);
DECLARE_HANDLE(HGLOBAL);
DECLARE_HANDLE(HDC);
DECLARE_HANDLE(HRGN);
DECLARE_HANDLE(HWND);
DECLARE_HANDLE(HMENU);
DECLARE_HANDLE(HACCEL);
DECLARE_HANDLE(HTASK);

三、理解:
HANDLE就是PVOID,也就是无类型指针,
上面这些资源的句柄Handles都不过是指向struct的指针,至于这个struct的用处,连M$都说unused了,现在解释下M$这么做的意义,这就是所谓数据封装,你可以在你的程序中把M$的内部结构指针传来传去,可是你却不知道它到底指向的内容是什么。

句柄与指针确实是完全不同的两个概念。句柄仅仅是一个32位整数,WIN32中用于标记某个系统或进程的对象,可以理解为对象索引(由于M$未完全公开相关技术,在一定程度上只能如此理解),这个索引更像是一种映射关系(从句柄到对象指针的映射),而不是纯粹意义上的“数组下标”。

句柄可以理解为用于指向或标识内存的一块“资源”,这些资源如:文件(file)、内存块(block of memory)、菜单(menu)等等。操作系统通过句柄来定位核心对象和系统资源。
指针即为指向内存的“数据或指令”某一单元。

说的确切一点,句柄实际上是一种指向某种资源的指针,但与指针又有所不同:指针对应着一个数据在内存中的地址,得到了指针就可以自由地修改该数据。Windows并不希望一般程序修改其内部数据结构,因为这样太不安全。所以Windows给每个使用GlobalAlloc等函数声明的内存区域指定一个句柄(本质上仍是一个指针,但不要直接操作它),平时你只是在调用API函数时利用这个句柄来说明要操作哪段内存。

四、引喻:
牧童遥指杏花村
牧童的手为指针,杏花村的牌子为句柄,杏花村酒店为对象的实例.


附注:获得窗口句柄三种方法

1.HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)
HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName)
2.HWND WindowFromPoint(POINT& Point)//获得当前鼠标光标位置的窗口HWND
3.BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
BOOL CALLBACK EnumChildWindows(HWND hWndParent, WNDENUMPROC lpEnumFunc,LPARAM lParam)
BOOL CALLBACK EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
 

Similar threads

后退
顶部