受M$的帮助文档以及很多Windows编程书籍的影响,大家对局柄比较普遍的认识是:句柄是一个整数,用以标识Windows对象,句柄不是一个指针……
而实际上,这些不过是M$进行数据封装的幌子而已,下面我们一起来分析一下HANDLE到底是什么。
请先到Windef.h找绝大多数句柄的定义: DECLARE_HANDLE(HWND); DECLARE_HANDLE(HHOOK); …… DECLARE_HANDLE(HGDIOBJ); DECLARE_HANDLE(HBITMAP); DECLARE_HANDLE(HBRUSH); …… typedef HANDLE HGLOBAL; typedef HANDLE HLOCAL; ……
OK, 现在大家跟我一起翻到Winnt.h,看看DECLARE_HANDLE和HANDLE到底是什么: #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 typedef HANDLE *PHANDLE;
哈哈,现在知道了吧,HANDLE就是PVOID,也就是无类型指针, 而DECLARE_HANDLE(HWND);就是: struct HWND__ { int unused;}; typedef struct HWND__ *HWND; 现在实际上都清楚啦,这些Handles都不过是指向struct的指针,至于这个struct的用处,连M$都说unused了,^o^
现在解释下M$这么做的意义,这就是所谓数据封装,你可以在你的程序中把M$的内部结构指针传来传去,可是你却不知道它到底指向的内容是什么,而且可以编个句柄的瞎话防止大家的质疑:)。而M$的程序大可以这么写: #include <windows.h> //这个和大家用的一样 #include "windows_in.h" //这个是M$自用的,外人别想看到^o^
HSOMETHINGELSE DoSomething(HSOMETHING hSomething) { struct RealSomething* p = (struct RealSomething*)hSomething; //先强制类型转换成内部结构指针 ……do something…… return (HSOMETHINGELSE)pRealSomethingElse;//强制类型逆转换 }
^o^ ^o^ ^o^ ^o^ ^o^ ^o^ ^o^ ^o^ ^o^ ^o^ ^o^ ^o^ ^o^ ^o^ ^o^ ^o^ 
|