HANDLE:
句柄是WONDOWS用來標識被應用程序所建立或使用的對象的唯一整數,WINDOWS使用各種各樣的句柄標識諸如應用程序實例,窗口,
控制,位圖,GDI對象等等。從數據類型上來看它是一個16位的無符號整數(0 ~ 65535)。
如果想更透徹一點地認識句柄,我可以告訴大家,句柄是一種指向指針的指針。我們知道,所謂指針是一種內存地址。應用程序啟動后,組
成這個程序的各對象是住留在內存的。如果簡單地理解,似乎我們只要獲知這個內存的首地址,那么就可以隨時用這個地址訪問對象。
但是,如果您真的這樣認為,那么您就大錯特錯了。我們知道,Windows是一個以虛擬內存為基礎的操作 系統。在這種系統環境下,Win-
dows內存管理器經常在內存中來回移動對象,依此來滿足各種應用程序的內存需要。對象被移動意味着它的地址變化了。如果 地址總是如
此變化,我們該到哪里去找該對象呢?
為了解決這個問題,Windows操作系統為各應用程序騰出一些內存儲地址,用來專門登記各應用對象在內存中的地址變化,而這個地址(存
儲單元的位置)本身是不變的。Windows內存管理器在移動對象在內存中的位置后,把對象新的地址告知這個句柄地址來保存。這樣我們只
需記住這個句柄地址就可以間接地知道對象具體在內存中的哪個位置。這個地址是在對象裝載(Load)時由系統分配給的,當系統卸載時(Un
load)又釋放給系統。
句柄地址(穩定)→記載着對象在內存中的地址────→對象在內存中的地址(不穩定)→實際對象
WINDOWS程序中並不是用物理地址來標識一個內存塊,文件,任務或動態裝入模塊的,相反的,WINDOWS API給這些項目分配確定的
句柄,並將句柄返回給應用程序,然后通過句柄來進行操作。但是必須注意的是程序每次從新啟動,系統不能保證分配給這個程序的句柄還
是原來的那個句柄,而且絕大多數情況的確不一樣的。
受M$的幫助文檔以及很多Windows編程書籍的影響,大家對局柄比較普遍的認識是:句柄是一個整數,用以標識Windows對象,句柄不
是一個指針……而實際上,這些不過是M$進行數據封裝的幌子而已,下面我們一起來分析一下HANDLE到底是什么。
請先到WinDef.h找絕大多數句柄的定義(~\Microsoft SDKs\Windows\v7.0A\Include):
1 DECLARE_HANDLE(HWND); 2 3 DECLARE_HANDLE(HHOOK); 4 5 …… 6 7 DECLARE_HANDLE(HGDIOBJ); 8 9 DECLARE_HANDLE(HBITMAP); 10 11 DECLARE_HANDLE(HBRUSH); 12 13 …… 14 15 typedef HANDLE HGLOBAL; 16 17 typedef HANDLE HLOCAL;
現在大家跟我一起翻到WinNT.h,看看DECLARE_HANDLE和HANDLE到底是什么:
1 #ifdef STRICT 2 typedef void *HANDLE; 3 #if 0 && (_MSC_VER > 1000) 4 #define DECLARE_HANDLE(name) struct name##__; typedef struct name##__ *name 5 #else 6 #define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name 7 #endif 8 #else 9 typedef PVOID HANDLE; 10 #define DECLARE_HANDLE(name) typedef HANDLE name 11 #endif 12 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$的程序大可以這么寫:
1 #include <windows.h> //這個和大家用的一樣 2 #include "windows_in.h" //這個是M$自用的,外人別想看到^o^ 3 HSOMETHINGELSE DoSomething(HSOMETHING hSomething) 4 { 5 struct RealSomething* p = (struct RealSomething*)hSomething; //先強制類型轉換成內部結構指針 6 ……do something…… 7 return (HSOMETHINGELSE)pRealSomethingElse;//強制類型逆轉換 8 }
參考資料:
[1] 轉載自http://www.cnblogs.com/yellowyu/archive/2009/06/07/1497910.html