HANDLE:句柄的概念
HANDLE:句柄,是Windows用來表示對象的(不是C++的對象),HWND是其中一種,HWND是HANDLE,但HANDLE不只是HWND,HANDLE是一個通用句柄表示,HWND是一個專用表示窗口的句柄。更具體的查MSDN吧。包含在winnt.h頭文件中。句柄 是windows編程的一個關(guān)鍵性的概念,編寫windows應(yīng)用程序總是要和各種句柄打交首,所謂句柄,就是一個4字節(jié)長的唯一的數(shù),HANDLE就是PVOID,也就是無類型指針(不指向任何類型數(shù)據(jù)的指針)句柄其實(shí)就是指針,但是他和指針最大的不同是,給你一個指針,你可以通過這個指針做任何事情,也許是做好事,也許是通過這個指針破壞內(nèi)存,句柄就沒有這個缺點(diǎn),通過句柄,你能干一些windows讓你干的事情,沒有了指針的壞處。windwos引入了實(shí)例句柄,windows為每個應(yīng)用程序建立一張表,實(shí)例句柄就好像是這張表的一個索引。windows不僅使用句柄來管理實(shí)例,也用它來管理窗口,位圖,字體,元文件,圖標(biāo)等系統(tǒng)資源。在windows環(huán)境中,句柄是用來標(biāo)識項(xiàng)目的,這些項(xiàng)目包括:模塊,任務(wù),實(shí)例,文件,內(nèi)存塊,菜單,控制,字體,資源,包括圖標(biāo),光標(biāo),字符串等,GDI對象,所括位圖,畫刷,元文件,調(diào)色板,畫筆,區(qū)域,以及設(shè)備描述表句柄是用來標(biāo)識(被應(yīng)用程序所建立或使用的)對象的唯一整數(shù),windows使用各種各樣的句柄標(biāo)識諸如應(yīng)用程序?qū)嵗?#xff0c;窗口,控制,位圖,GDI對象等等。MFC源代碼:
#ifdef STRICT typedef void *HANDLE;(類型定義 void * handle---無類型指針) #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name HANDLE m_hWriteHandle; ::WriteFile(m_hWriteHandle, pReqData, dwReqDataLen, &dwNumberofBytesWritten, &overlapped)//在windows程序設(shè)計(jì)中,句柄是無法精確定義的術(shù)語,但是在程序設(shè)計(jì)中,句柄無所不在,窗口有窗口的句柄HWND,線程和進(jìn)程也有句柄HANDLE,甚至有人把套接字也稱為句柄,簡而言之,句柄是處理對象的一個接口,你可以通過句柄去操作程序中所涉及的對象在windows中,句柄是和對象一一對應(yīng)的32位無符號整數(shù)值,對象可以映射到唯一的句柄,句柄也可以映射到唯一的對象windows需要向程序員提供必要地編程接口,在這些接口中,允許程序員訪問,創(chuàng)建和銷毀對象,但是,出于封裝的考慮,windows并不想向程序員返回指針,指針包含了太多的信息,(1)首先指針給出了對象存儲的確切位置,(2)其次,要操作一個指針,程序員必須知道指針?biāo)笇ο蟮膬?nèi)部結(jié)構(gòu)特片,也就是說windows必須向程序員暴露相應(yīng)的數(shù)據(jù)結(jié)構(gòu),而這些數(shù)據(jù)結(jié)構(gòu)也許是操作系統(tǒng)想向程序員隱藏的。如果說COM技術(shù)向用戶隱藏了數(shù)據(jù),只暴露了接口并只允許按接口定義的方法操
作數(shù)據(jù)的話,句柄這種方式則允許你按自己的方式直接操作數(shù)據(jù),但windows又不向
你直接暴露數(shù)據(jù)。直接操作數(shù)據(jù)是程序員需要的,不暴露數(shù)據(jù)是windows所需要的,
句柄封裝方式實(shí)現(xiàn)了各取所需。(很好的找到了滿足雙方需且的平衡點(diǎn))
3.句柄如何與對象映射?
封裝背后,必須有一個地方可以實(shí)現(xiàn)解碼,以實(shí)現(xiàn)句柄和對象的相互轉(zhuǎn)換。在
windows中,存在兩種映射方式:
a. 全等映射。也即,句柄本身就是一個指針。映射在這里只是類型轉(zhuǎn)換而已。
這種情況有,進(jìn)程實(shí)例句柄或模塊句柄,以及資源句柄等等。(不明白)
b. 基于表格的映射。這是對象指針與句柄之間最普通的映射機(jī)制。操作系統(tǒng)創(chuàng)
建表格,并保存所有要考慮的對象。需要創(chuàng)建新對象時(shí),要先在表格中找到空入口
,然后把表示對象的數(shù)據(jù)添入其中。當(dāng)對象被刪除時(shí),它的數(shù)據(jù)成員和其在表中的
入口被釋放。
4.句柄的定義和實(shí)現(xiàn)
我們以GDI對象為例進(jìn)行討論。創(chuàng)建了GDI對象,就會得到該對象的句柄。句柄
的對象可能是HBRUSH、HPEN、HFONT或HDC中的一種,這依賴于你創(chuàng)建 的GDI對象類
型。但是最普通的GDI對象類型是HGDIOBJ。HGDIOBJ被定義成空指針。
HPEN的實(shí)際編譯類型定義隨編譯時(shí)間宏STRICT的不同而不同。如果STRCIT已經(jīng)
被定義了,HPEN是這樣的:
struct HPEN__ {int unused};
typedef struct HPEN__* HPEN;
1
2
如果STRICT沒有定義,HPEN是這樣定義的:
typedef void *HANDLE;
typedef HANDLE HPEN;
1
2
上面這段代碼是一個注重細(xì)節(jié)的程序員最接近句柄的地方,因此我們重點(diǎn)分析
一下。這里有一點(diǎn)點(diǎn)技巧。如果定義了STRICT宏,HPEN是指向有單個未使用字段的
結(jié)構(gòu)的指針,否則HPEN是空指針。C/C++編譯器允許把任何類型的指針作為空指什傳
遞,反之則不可以。兩個不同類型的非空指針是互不兼容的。在STRICT版本中,編
譯對GDI對象句柄的不正確混用將給出警告,對于非GDI句柄,如HWND、HMENU的不正
確混用也會給出警告,從而使程序在編譯器得到更STRICT的檢查。
接下來的分析可能不那么令你感興趣,但它更深刻地揭示了句柄。對GDI句柄來
說,盡管windows頭文件把它定義成指針,但如果你仔細(xì)檢查這些句柄的值,它根本
就不像指針,這也是為什么我說它只是一個32位無符整數(shù)值的原因。對句柄就是指
針的情況,這句話也仍然適用。讓我們隨意地生成一些句柄,比如你用GetStockOb
ject()以得到一些句柄,你會發(fā)現(xiàn),它們的值總在區(qū)間0x01900011到0xba040389。
前者指向用戶區(qū)中的未分配的無效區(qū)域,后者指向內(nèi)核地址空間。另外你可能發(fā)現(xiàn)
,兩個句柄之間的值可能只差數(shù)值1,這也說明GDI句柄不是指針。
和多數(shù)人想象的不一樣,句柄也不是一個單純的索引值。對GDI對象句柄來說,
GDI句柄由8位 、1位堆對象標(biāo)記(表明對象是否創(chuàng)建在堆中)、7位對象類型信息和
高4位為0的16位索引組成,如圖:
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1|1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
| 8 位引用計(jì)數(shù) |堆 | 對象類型7 | 16位索引 |
標(biāo)
記
在這里你可以看到,對GDI來說,它只使用了16位作為索引。這意味著一個進(jìn)程最多只
可以創(chuàng)建小于64K個句柄,實(shí)際上受其他一些限制,整個windwos系統(tǒng)中大概可以容納約
16384(0x4000)個GDI對象。
總結(jié)
以上是生活随笔為你收集整理的HANDLE:句柄的概念的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vc6.0上安装qt插件
- 下一篇: WaitForSingleObject的