首页 > 代码库 > VC/MFC开发中的句柄HWND

VC/MFC开发中的句柄HWND

Windows开发中,经常会碰到一个常见的字眼HWND,如下

   HWND hWnd;
   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
HWND就是句柄,那么句柄是什么?

【句柄定义】

先看Windows下面的定义,如下

DECLARE_HANDLE            (HWND);
DECLARE_HANDLE            (HHOOK);
再往下看接续查找DECLARE_HANDLE的定义,如下
#ifdef STRICT //编译级别的选项开关
typedef void *HANDLE;  // void* 
#if 0 && (_MSC_VER > 1000)
#define DECLARE_HANDLE(name) struct name##__; typedef struct name##__ *name
#else
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
#endif
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif
typedef HANDLE *PHANDLE;

这里我的编译器采用的是VS2012,_MSC_VER含义如下:

MSVC++ 11.0 _MSC_VER = 1700 (Visual Studio 2012)
MSVC++ 10.0 _MSC_VER = 1600 (Visual Studio 2010)
MSVC++ 9.0  _MSC_VER = 1500 (Visual Studio 2008)
MSVC++ 8.0  _MSC_VER = 1400 (Visual Studio 2005)
MSVC++ 7.1  _MSC_VER = 1310 (Visual Studio 2003)
MSVC++ 7.0  _MSC_VER = 1300
MSVC++ 6.0  _MSC_VER = 1200
MSVC++ 5.0  _MSC_VER = 1100
就进入了宏开关的else分支:
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
展开上面的宏,假设传入的name为obj,展开后的结果
	#define DECLARE_HANDLE(obj) 
	struct obj__
	{
		int unused;
	}; 
	typedef struct obj__ *obj
再将DECLARE_HANDLE            (HWND);展开
	#define DECLARE_HANDLE(HWND) 
	struct HWND__
	{
		int unused;
	}; 
	typedef struct HWND__ *HWND
那么HWND就是一个仅含有一个整型成员变量的结构体对象的地址,这样一来HWND hwnd; 其实就等价于 HWND__* hWnd;

注意:(1)句柄是跨进程可见的,而指针从来都是属于某个特定进程的,这里摘自网上还没验证,但是根据核心编程里面对内核对象的理解,那里指出内核对象是内核地址上的一块区域,应该差不多

           (2)HANDLE、HINSTANCE又是什么呢?

#ifdef STRICT
typedef void *HANDLE;
...
#endif
typedef HANDLE *PHANDLE;

而HINSTANCE的定义域HWND类似,就是HINSTACE__ *

DECLARE_HANDLE(HINSTANCE);

【句柄猜想】

注意:这里是参照Windows核心编程对内核对象的解释

句柄其实就是对象地址的再次封装,防止肆意破坏对象且提供了一种安全的机制权限的一个整型值,这里我们进封装,由于Windows对象很多,需要一个类似索引的表,如

     句柄         地址      ...           权限

     1  0x0000 1200    ????    0x0000 0000

     2  0x0000 3400    ????    0x0000 0001

以上是一种猜测的假设, 这样句柄1的内存地址为0x0000 1200 ,假设权限0x0000 0000 就是无任何权限或者继承当前窗口或者进程的权限

参照上面的定义查询,发现没有权限之类的?why?这个我暂时也没搞懂,总之内核里面会维护一张句柄表,而每次都从那张表中查找具体的对象地址

何为内核对象?何为用户对象?何为GDI对象?

内核对象提供了一种健全的机制,可保证不同用户、不同权限的访问,在创建内核对象必须使用安全标志,并且其分布在内核地址空间某一段内存中,具体地址请查看微软技术丛书,而这两种就是除了上面讲的之外的句柄对象,例如一个窗口的使用,就是一个用户对象的使用;

【GDI对象的使用】

。。。