句柄的面纱

一 句柄和指针的区别
句柄和指针根本就不是一回事,基本上没有共同的地方

我对句柄的定义是:

句柄是系统内部受保护的数据结构的标志或者说索引.我的解释:

当你的应用程序或者系统建立内核对象,用户对象,GUI对象的时候实际上这些对象是一些内存数据结构(这个就不要我解释了吧)显然这些对象需要受到保护,不能让用户随便修改访问,否则系统很容易崩溃所以提供了一个机制来保护性的访问这些对象,那就是API句柄是这些对象的标记,或者说是索引在内存中往往会存在一张句柄表,一般至少有如下结构

索引(也就是句柄)  指针(指向内存对象数据结构) 其他项
    1                   ox????????
    2                   ox????????
    3                   ox????????
    4...系统采用API,查询句柄表,取得句柄所对应的指针,这个指针才是真正的指针,用它可以访问修改受保护的内存.

假如句柄是指针

1 你自己输出一些句柄的值来看,句柄一般都是一些很小的整数值, 比如1,2,3,4...... 如果是指针的话,它起不是指向受保护的区域?岂不是NULL指针???

2 句柄如果是指针的话,那么用户岂不可以直接访问内存对象了?那系统还有什么稳定性,安全性?

3 你把得到的句柄,比如hwnd做hwnd++,hwnd--等运算,你看错不错.

其他理由我都不想说了 如果有人说看到句柄的定义为指针(我没有看到过) 那你就去当指针吧,反正指针也是32位的值,和无符号整数没有任何区别.

句柄就一个32位的二进制数 句柄就一个对象的标识

句柄就像身份证,用标识茫茫人海的你我他(她) 句柄就像一个数组的索引(Index) 

理解句柄

什么是句柄?

功能上的理解:
什么是"句柄"(handle),handle的本意是把柄,把手的意思。是你与操作系统打交道的东东。
举个通俗的例子,比如你考上了大学,入学后,学校(操作系统)会给你一个学生证号。
注意,这个号码是学校指定的,你无法自选。
有了这个号码(学生证,假设一证多用)享受学校提供的服务:
如你就可以去图书馆借书,去食堂吃饭,去教室上课等等。

但你不能到食堂里买啤酒,因为学校不允许这种服务。
而在计算机中系统提供的服务就是API调用,你有了HANDLE,就可以理直气壮地向系统提出调用API的服务。
而指针的权力就大多了,有了指针你可以到处去喝酒,打架,学校(操作系统)管不着,
所以句柄和指针的区别在于句柄指针调用系统提供的服务。
而句柄虽然是一个能相互区别的号码,但与我们普通的ID号又有区别,
普通的ID号是可以由程序员自己定义的,而句柄不行,它是对象生成是系统指定的,
是为了区别系统中存在的各个对象,这个句柄不是由程序员符给的。

概念上的理解
1。句柄,是整个windows编程的基础,一个句柄是指使用的一个唯一的整数值,
是指一个四字节长的数值,用于标志应用程序中的不同对象和同类对象中的不同的实例,
诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。
应用程序能够通过句柄访问相应的对象的信息。
2。句柄不是一个指针,程序不能利用它句柄来直接阅读文件中的信息。
如果句柄不用在I/O文件中,它是毫无用处的。
3。句柄是windows用来标志应用程序中建立的或是使用的唯一整数,
windows使用了大量的句柄来来标志很多对象。

机制上的理解
前面的分析很经典,但我认为有一点必须指出的。如果不对,请各位指证。
句柄是指针,一点不假,但是这个指针又与C中的指针有不同之处。
因为Windows是一个多任务的系统,其内存是可以移动的,
这样的话如果某一时刻有一个指针指向一块内存,之后的某个时刻却被系统移走了,
如果你再用这个指针的话就会出错。
为了解决这一问题,windows在系统专区开一块内存用于存放句柄,这个句柄的值就是一个地址,
当这一块内存被移走后,windows就修改这个句柄的值,再访问这块内存时,句柄的值总是有效的。
正因为这样当你使用GlobalAlloc分配的内存时,如果你指定这块内存的属性是固定的,
那么它的返回值可以直接给一个指针,如果是可以移动的,
返回值就必须给一个句柄,你就必须先GlobalLock后才能使用。
这是我对句柄理解,不知道对不对?

我的理解
其实,句柄是一个指向指针的指针。即:
在windows程序设计中,句柄仅是一个应用程序用来识别某些事情的数字

如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。
我们知 道,所谓指针是一种内存地址。
应用程序启动后,组成这个程序的各对象是住留在内的 。
如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。
但是,如果您真的这样认为,那么您就大错特错了。
我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,
Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。
对象被移动意味着它的地址变化 了。如果地址总是如此变化,我们该到哪里去找该对象呢?
为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,
用来专门 登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。
Wi ndows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。
这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。
这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统 。

句柄地址(稳定)→记载着对象在内存中的地址→对象在内存中的地址(不稳定) →实际对象
    但是,必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是
原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成
是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电
影院售给我们的门票总是不同的一个座位是一样的道理。

bool与BOOL的区别联系?
bool是C++中的一种变量类型(布尔类型),只可以写
bool   x;
x   = true;
x   = false;
在VC++中BOOL是这样说明的:
typedef int   BOOL;
也就是说BOOL是当int用的。
BOOL   x;
x   = 1;
x   = 0;
当然为了方便,VC++已经定义了
#define    TRUE   0
#define    FALSE  1

一、书上定义:

<<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)

本栏文章均来自于互联网,版权归原作者和各发布网站所有,本站收集这些文章仅供学习参考之用。任何人都不能将这些文章用于商业或者其他目的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值