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