日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

句柄和指針的區(qū)別

 君王之王 2015-05-17
2011-04-27 15:07:17

當(dāng)把硬盤上的資源調(diào)入內(nèi)存以后,將有一個(gè)句柄指向它,但是句柄只能指向一個(gè)資源。而且句柄知道所指的內(nèi)存有多大。還有指針,指針指向地址,它不知道分配的內(nèi)存有多大。  

但是如果你定義一個(gè)句柄,然后在VC里面右擊鼠標(biāo),選擇"go to definition of handle”,你會發(fā)現(xiàn)它的本質(zhì)就是一個(gè)指針,但是它的作用不同于指針。它和通常意義上的指針是有區(qū)別的。句柄借用了指針的思想,有它的邏輯特點(diǎn),但沒 有它的物理功能。句柄是WINDOWS分配給窗口等資源的唯一標(biāo)識,是一個(gè)整數(shù)。


一、書上定義:

<<Microsoft Windows 3 Developer''s Workshop>>(Microsoft Press,by Richard Wilton)

在Windows環(huán)境中,句柄是用來標(biāo)識項(xiàng)目的,這些項(xiàng)目包括:模塊(module)、任務(wù)(task)、實(shí)例 (instance)、文件(file)、內(nèi)存塊(block of memory)、菜單(menu)、控制(control)、字體(font)、資源(resource),包括圖標(biāo)(icon),光標(biāo) (cursor),字符串(string)等、GDI對象(GDI object),包括位圖(bitmap),畫刷(brush),元文件(metafile),調(diào)色板(palette),畫筆(pen),區(qū)域 (region),以及設(shè)備描述表(device context)。

<<WINDOWS編程短平快>>(南京大學(xué)出版社):

句柄是WONDOWS用來標(biāo)識被應(yīng)用程序所建立或使用的對象的唯一整數(shù),WINDOWS使用各種各樣的句柄標(biāo)識諸如應(yīng)用程序?qū)嵗?,窗口,控制,位圖,GDI對象等等。WINDOWS句柄有點(diǎn)象C語言中的文件句柄。

二、MFC源代碼:

#ifdef STRICT
typedef void *HANDLE;
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif

DECLARE_HANDLE(HMODULE); 
DECLARE_HANDLE(HINSTANCE); 
DECLARE_HANDLE(HLOCAL); 
DECLARE_HANDLE(HGLOBAL); 
DECLARE_HANDLE(HDC); 
DECLARE_HANDLE(HRGN); 
DECLARE_HANDLE(HWND); 
DECLARE_HANDLE(HMENU); 
DECLARE_HANDLE(HACCEL); 
DECLARE_HANDLE(HTASK);

三、理解:

句柄是一個(gè)32位的整數(shù),實(shí)際上是windows在內(nèi)存中維護(hù)的一個(gè)對象(窗口等)內(nèi)存物理地址列表的整數(shù)索引。因?yàn)閣indows的內(nèi)存管理經(jīng)常 會將當(dāng)前空閑對象的內(nèi)存釋放掉,當(dāng)需要時(shí)訪問再重新提交到物理存儲,所以對象的物理地址是變化的,不允許程序直接通過物理地址來訪問對象。程序?qū)⑾朐L問的 對象的句柄傳遞給系統(tǒng),系統(tǒng)根據(jù)句柄檢索自己維護(hù)的對象列表就能知道程序想訪問的對象及其物理地址了。句柄是一種指向指針的指針。我們知道,所謂指針是一 種內(nèi)存地址。應(yīng)用程序啟動后,組成這個(gè)程序的各個(gè)對象是駐留在內(nèi)存的。如果簡單地理解,似乎我們只要獲知這個(gè)內(nèi)存的首地址,那么就可以隨時(shí)用這個(gè)地址訪問 對象了。但是,如果真這么認(rèn)為,那么就大錯(cuò)特錯(cuò)了。我們知道windows是一個(gè)虛擬內(nèi)存為基礎(chǔ)的操作系統(tǒng)。在這種情況下,windows內(nèi)存管理器經(jīng)常 在內(nèi)存中來回移動對象,以此來滿足各種應(yīng)用程序的內(nèi)存需要,對象被移動意味著它的地址變化了。如果地址總是如此的變化,我們應(yīng)該去那里找對象呢?為了解決 這個(gè)問題,windows操作系統(tǒng)為各個(gè)應(yīng)用程序騰出一些內(nèi)存地址,用來專門登記各個(gè)應(yīng)用對象在內(nèi)存中的地址變化,而這個(gè)地址(存儲單元的位置)本身是不變的。windows 內(nèi)存管理器移動對象在內(nèi)存中的位置后,把對象新的地址告知這個(gè)句柄地址來保存。這樣我們只需要記住這個(gè)句柄地址就可以間接地知道對象具體在內(nèi)存中哪個(gè)位置 了。這個(gè)地址是在對象裝載(load)時(shí)由系統(tǒng)分配的,當(dāng)系統(tǒng)卸載時(shí)又釋放給系統(tǒng)。句并地址(穩(wěn)定)----->記載著對象在內(nèi)存中的地址 -------->對象在內(nèi)存中的地址(不穩(wěn)定)----->實(shí)際對象。但是必須注意,程序每次重新啟動,系統(tǒng)不保證分配跟這個(gè)程序的句柄還 是原來哪個(gè)句柄,而絕大多數(shù)情況下的確不一樣。假如我們把進(jìn)入電影院看電影看成是一個(gè)應(yīng)用程序的啟動運(yùn)行,那么系統(tǒng)給應(yīng)用程序分配的句柄總是不一樣,這和 每次電影院給我們的門票總是不同的座位是一個(gè)道理。

因此,句柄和指針其實(shí)是兩個(gè)截然不同的概念。windows系統(tǒng)用句并標(biāo)記系統(tǒng)資源,用句并隱藏系統(tǒng)信息。你只需要知道有這個(gè)東西,然后去調(diào)用它就行了,它是32bit的uint。指針則標(biāo)記某個(gè)物理內(nèi)存的地址,是不同的概念。


指針對應(yīng)著一個(gè)數(shù)據(jù)在內(nèi)存中的地址,得到了指針就可以自由地修改該數(shù)據(jù)。Windows并不希望一般程序修改其內(nèi)部數(shù)據(jù)結(jié)構(gòu),因?yàn)檫@樣太不 安全。所以Windows給每個(gè)使用GlobalAlloc等函數(shù)聲明的內(nèi)存區(qū)域指定一個(gè)句柄(本質(zhì)上仍是一個(gè)指針,但不要直接操作它),平時(shí)你只是在調(diào) 用API函數(shù)時(shí)利用這個(gè)句柄來說明要操作哪段內(nèi)存。當(dāng)你需要對某個(gè)內(nèi)存進(jìn)行直接操作時(shí),可以使用GlobalLock鎖住這段內(nèi)存并獲得指針來直接進(jìn)行操 作。

句柄是指針的“指針”,使用句柄主要是為了利于windows在進(jìn)程內(nèi)存地址空間移動分配的內(nèi)存塊,以防止進(jìn)程的內(nèi)存空間被撕的四分五裂而存在過多的碎片。

句柄是一些表的索引也就是指向指針的指針。間接的引用對象,windows可以修改對象的"物理"地址和 描述器的值,但是句柄的值是不變的。


句柄可以在獲得窗口的時(shí)候使用,指針可以進(jìn)行調(diào)用窗口,兩個(gè)使用的地方不一樣.一個(gè)括號外,一個(gè)括號內(nèi).

從窗口指針獲取窗口句柄:GetSafeHwnd();
從窗口句柄獲取臨時(shí)窗口指針:FromHandle(); 
從窗口句柄獲取永久窗口指針: FromHandlePermanent();

其實(shí)兩者被沒有關(guān)系,實(shí)際上是MFC在創(chuàng)建窗口的時(shí)候用鉤子函數(shù)溝住HCBT_CREATEWND消息,
然后通過CWnd::Attach()函數(shù)把二者捆綁在一起。
以后就可以用GetSafeHwnd(),F(xiàn)romHandle(),F(xiàn)romHandlePermanent()這三個(gè)函數(shù)可以互相得到了。

MFC之所以要這樣做,主要是為了使原來的SDK面向過程的編程遍成面向?qū)ο蟮木幊蹋械腗FC的窗口都共用一窗口過程函數(shù),在窗口過程函數(shù)里, 通過窗口句柄(HWND)找到窗口對象指針(CWnd *)從而把消息分發(fā)到窗口對象中,這樣以后就可以在窗口類中實(shí)行消息響應(yīng)編程處理了。

附注:獲得窗口句柄三種方法

1.HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)

HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName)

2.HWND WindowFromPoint(POINT& Point)//獲得當(dāng)前鼠標(biāo)光標(biāo)位置的窗口HWND

3.BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)

BOOL CALLBACK EnumChildWindows(HWND hWndParent, WNDENUMPROC lpEnumFunc,LPARAM lParam)

BOOL CALLBACK EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多