FromHandle函數


  一 FromHandle()

  MFC 實際上是對內核對象HANDLE(如CDC的m_hDC,CWnd的m_hWnd)封裝了這個句柄有關的所有操作,一個類生成一個新對象的時候這個句柄是無效的,要獲得這個句柄,可以有兩個方法,一個是Create來創建,另一個就是用Attach來與一個已有的句柄建立關聯,實際上也就是給類的句柄 成員變量賦值。 而有些時候這個句柄不是由我們創建,但是我們要對它的 封裝類進行操作,(mfc 框架)必需創建對應的封裝類包裝它
MFC 中對各種包含 內核對象的封裝類都有FromHandle(HANDLE h)方法。FromHandle(HANDLE h) 先查找由用戶定義的 內核對象的封裝類, 如果找到直接返回,沒有找到構造一個臨時對象返回.
 

二 Fromhandle的內部機制

  例如,你的程序中必然對你的主窗口Attach(這是由Framework完成的),這樣的話,假如你又得到了你程序的主窗口句柄hwndMain,你如果再調用FromHandle(hwndMain),它返回的將是你的App中的m_pMainWnd,原因就是FromHandle會維持一個內部的列表,紀錄每個hwnd與CWnd的關聯情況,如果一旦一個hwnd早已與某個CWnd對象相關連,它會返回該CWnd對象的指針。既然如此,FromHandle返回的便是m_pMainWnd,而此對象Framework會自動析構,因此你只是得到了該指針的一個副本,不能對其作析溝操作,否則會導致你的程序運行不正常。

   考慮另外一種情況,就是一個hwnd與任何對象都沒有關聯(比如,你用API
CreateWindow新建了一個窗口),此時的hwnd尚未與任何CWnd對象關聯,如果你用FromHandle(hwnd),FromHandle便會臨時new一個CWnd對象,並Attatch到此hwnd,然后返回給你。我剛才說了,FromHandle會維持一個hwnd與CWnd關聯的列表,每當Framework OnIdle時,它便會檢查此列表,一旦發現某個CWnd是FromHandle臨時創建的對象,它便會首先Detach此對象,然后delete之。因此,你在程序中也不必delete從FromHandle得到的對象指針,但這種指針只在一次消息處理過程中有效。
 

三 與FromHandlePermanent()的區別

FromHandlePermanent函數,它當且僅當hwnd已與某個CWnd對象關聯時才返回此對象的指針,否則返回NULL。這也是它為什么叫Permanent——區別於FromHandle會new一個臨時的CWnd對象。 這兩個函數都是在公共的 CMapHandle 中查找句柄對應的 CWnd 對象(通過一個CBT鈎子,CWnd 對象將創建時得到的句柄和自己的指針紀錄到 CMapHandle),區別是如果找不到相關的對象,FromHandle 在CMapHandle 的 temporarylist 中創建並返回一個臨時對象的指針 ,而 FromHandlePermanent 返回 NULL(此外 FromHandlePermanent 不使用 temporarylist ,所以不查找 temporarylist 下的句柄)。
 

四  使用注意

  大部分情況下,對任意句柄使用 FromHandle 是不錯的,因為大多情況下只利用返回的 CWnd 指針調用的非虛函數,返回的即使是一個臨時對象,調用也是正確的(MFC 中較少用 FromHandlePermanent,除非確定句柄是由本線程創建的或不需要創建臨時對象)。

但是在某些情況下,比如從使用 MFC 的非 Extension DLL 中創建的窗口,這個機制會有問題,因為窗口創建在其他的 MFC 模塊之下,在 EXE 中調用 FromHandle,由於該模塊的 CMapHandle 對象某有相關的紀錄,所以只能得到臨時對象,如果使用返回的指針調用 CWnd 的虛函數如 PreTranslateMessage,得到調用的是 CWnd::PreTranslateMessage,而不是 DLL 中的 CWnd 派生類重載過的 CWnd::PreTranslateMessage。

  對於GDI對象,以上的分析也是適用的。
 


免責聲明!

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



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