MFC中的句柄


1.引出句柄

CDC問題:
1.CDC dc;dc.LineTo(point);無法運行

2.CDC *dc=GetDC();dc->LineTo(point);就可以運行了

MFC中有大量的句柄包裝類。所謂句柄包裝類,指的是這些類是封裝了系統對象的句柄,並提供了一組成員函數作為訪問系統對象的接口。

從這些句柄包裝類的意義上可以看出,一個被完全構造好,處於良好狀態的MFC對象,其中的句柄成員必須是有效的,才能正常使用那些成員函數來操作這個對象。

所以一般的MFC句柄包裝類的構建要完成兩個任務:

第一,創建一個句柄包裝類對象。

第二,初始化其中的系統對象句柄。

大部分的包裝類對象的構建都通常分為兩步進行:

1、創建一個對象;

2、通過create等類似的成員函數創建系統對象並初始化對象中的句柄。

當然這兩部分也可以直接在構造函數中完成。此時一般需要一個系統對象句柄作為參數,或者另一個被良好構造的句柄包裝類對象做參數,以在構造函數中就能初始化句柄成員。其他方法還有通過Attach和Detach將部

分構造的對象和系統對象句柄綁定,或通過FromHandle獲得一個臨時的句柄包裝類對象等。

現在問題就很清晰了:

CDC dc;dc.LineTo( point );//無法運行,是因為dc這個對象僅僅被部分構建,其中的系統對象句柄成員並沒有賦值為一個有效的繪圖設備句柄,自然其后的LineTo調用就會失敗。

而:

CDC *dc = GetDC();dc->LineTo( point );/*通過調用窗口類的GetDC()成員函數,將返回一個被良好構造的CDC對象(即該對象中的設備句柄成員已經被賦值為一個有效的

                                                             句柄),所以其后的LineTo操作就沒問題。也就是問題的關鍵不在於對象創建於棧還是堆中,而在於是否完全構造好了一個句柄包裝

                                                             類對象。*/

2.句柄到底是什么東東呢,指針呢?

  其實,句柄並沒有什么神奇之處,不管哪種句柄,實際都是一個整數。它標識一種資源,如窗口、位圖等等。就象你找一個人,必須知道它的地址一樣,如果你要操作一種資源,必須先獲得句柄。“取窗口句柄

()”並不是只能取出窗口的句柄,所有窗口控件,如編輯框、標簽等都可以用本命令取出自己的句柄,如:編輯框1.取窗口句柄()或標簽1.取窗口句柄()。控件的句柄同樣,任何控件都有它自身的特有屬性,句柄

也就指它的特有屬性(包括共性)。

  句柄英文譯作HANDLE,HANDLE的本意是把柄,把手的意思,是與操作系統打交道的東東。有人舉過比較通俗的例子:你考上了大學,入學后,學校(操作系統)會給你一個學生證號。注意,這個號碼是學校指

定的,你無法自選。有了這個號碼(學生證,假設一證多用)享受學校提供的服務:如你就可以去圖書館借書,去食堂吃飯,去教室上課等 等。但你不能到食堂里買啤酒,因為學校不允許這種服務。而在計算機中系統

提供的服務就是API調用了。當你有了HANDLE,就可以理直氣壯地向系統提出調用API的服務。而指針的權力就大多了,有了指針你可以到處去喝酒,打架,學校(操作系統)管不着,所以句柄和指針的區別在於句柄

只能調用系統提供的服務。而句柄雖然是一個能相互區別的號碼,但與我們普通的ID號又有區別,普通的ID號是可以由程序員自己定義的,而句柄不行,它是對象生成時系統指定的,是為了區別系統中存在的各個對

象,這個句柄不是由程序員賦給的。

可以引用csdn上一個人的話來說明句柄,指針對象實例之間的關系:

牧童遙指杏花村。牧童的手為指針,杏花村的牌子為句柄,杏花村酒店為對象的實例。

3.深入探討句柄

  更透徹的說,句柄是一種指向指針的指針。大家都知道,所謂指針是一種內存地址。應用程序啟動后,組成這個程序的各對象是住留在內存的。如果簡單地理解,似乎我們只要獲知這個內存的首地址,那么就可以隨

時用這個地址訪問對象。但是,如果您真的這樣認為,那么您就大錯特錯了。我們知道,Windows是一個以虛擬內存為基礎的操作系統。在這種系統環境 下,Windows內存管理器經常在內存中來回移動對象,依此來

滿足各種應用程序的內存需要。對象被移動意味着它的地址變化了。如果地址總是如此變化,我們該到哪里去找該對象呢? 為了解決這個問題,Windows操作系統為各應用程序騰出一些內存儲地址,用來專門登記各應

用對象在內存中的地址變化,而這個地址(存儲單元的位置)本 身是不變的。Windows內存管理器在移動對象在內存中的位置后,把對象新的地址告知這個句柄地址來保存。這樣我們只需記住這個句柄地址就可以間接地

知道對象具體在內存中的哪個位置。這個地址是在對象裝載(Load)時由系統分配給的,當系統卸載時(Unload)又釋放給系統。句柄地址(穩定) ─→記載着對象在內存中的地址─→對象在內存中的地址(不穩定) ─→實際

對象

本質:WINDOWS程序中並不是用物理地址來標識一個內存塊,文件,任務或動態裝入模塊的,相反的,WINDOWS API給這些項目分配確定的句柄,並將句柄返回給應用程序,然后通過句柄來進行操作。 但是

必須注意的是程序每次從新啟動,系統不能保證分配給這個程序的句柄還是原來的那個句柄,而且絕大多數情況的確不一樣的。假如我們把進入電影院看電影看 成是一個應用程序的啟動運行,那么系統給應用程序分配

的句柄總是不一樣,這和每次電影院售給我們的門票總是不同的一個座位是一樣的道理。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM