1. 程式人生 > >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物件的使用】

。。。