CWnd與HWND的簡單辨析


  今天在寫一個小的網絡應用,需要用到HWND類型的一個參數。而程序中有的“窗口操作句柄”只有一個CWnd類型的指針。這倆不都是“窗口句柄”么?而且反正都是地址直接轉換使用如何?結果出現了調用失效的情況。別處自信不會出錯,問題只能出在這個參數上了。可是這兩個不都是“窗口句柄“?!

  既然我加了雙引號,顯然后來明白了,這顯然不是正解。那么怎么解釋和區別兩者?又怎么靈活使用兩者?由於技術水平限制,在此僅僅做簡單區分,靈活使用等到我稱為偽大神時,再做深究。好,廢話少說,進入正題。

  首先轉載一段文章:

***************************************************

概念:

C++對象和Windows窗口(對象)的區別:

首先,你要明白Windows對象和MFC對象的區別。

 

MFC對象實際上並沒有把整個Windows對象都包裝在其中,它只是有一個窗口句柄而已,這個窗 口句柄如果指向一個實際存在的窗口對象,那么這個MFC對象就是有效的,否則這個MFC對象是空的。

 

如果你還不明白,請回憶一下,當我們使用MFC創建一 個窗口時,是分兩步進行的:

第一步,new一個CWnd對象,這一步是創建MFC對象,但是其中的HWND還是非法的,因為對應的Windows對象還沒 有被創建出來;

第二步,調用CWnd的成員函數Create創建真正的Windows對象,同時,把先前創建的MFC的CWnd對象的HWND成員指向該 窗口,這樣才算創建完畢一個窗口。

而如果你是用SDK方式,那么只要創建一個WNDCLASS結構,然后調用Create或者CreateEx就創建了一 個窗口。

 
     好,現在回答你的問題,你可以假設,現在你已經有了一個有效窗口句柄,那么你想把這個窗口和一個CWnd對象關聯起來怎么辦?很簡單,用Attach,其實就是讓一個CWnd對象的HWND成員指向這個窗口句柄。這就是Attach主要完成的任務。 


     第二個,關於Detach。如前所述,WNDCLASS其實和CWnd根本沒有什么關系。它們之間只是通過CWnd的成員HWND聯系起來的。如果把 Attach看做“聯姻”的話,那么Detach就是“離婚”了,通俗地說,就是切斷一個CWnd對象和一個有效窗口的臍帶。為什么要切斷呢?因為 CWnd是C++的對象,C++的對象有一個生存期的概念,脫離了該對象的作用域,這個對象就要被銷毀,但是Windows對象沒有這個特點,當銷毀 CWnd對象的時候,我們不一定希望WNDCLASS一起被銷毀,那么在此之前,我們就先要把這個“臍帶”剪斷,以免“城門失火,殃及池魚”。

 

 

另外一個描述:

 

基本就是把一個句柄附加到一個mfc的對象上

比如你通過loadimage創建了一個handle,現在想用cbitmap類的成員函數,

你就可以聲明一個cbitmap對象,通過attach將他們關聯在一起,

以后就可以使用cbitmap的成員函數來操作hbitmap了

==========================

黑體字的描述並不准確,根據英文原文的翻譯,應該是將一個Windows窗口(Windows window)附加到一個

Cwnd對象(MFC里的概念)上。

具體的操作如第一個描述里面,是將CWnd對象的HWND成員指向這個窗口句柄。(感覺也不夠准確,兩者應該是一樣的了。

都是HWND,賦值即可。)這樣描述會比較好:CWnd對象的HWND成員指向這個窗口,操作為將HWND成員賦為:

原有的“有效窗口句柄”。

第二個描述里的用法可以在以后繼續驗證(調用MFC類的成員函數)。

 

總結:

Cwnd對象是個空殼殼,需要一個具體的Windows window來填充。

***************************************************

  HWND是句柄,CWnd是MFC窗體類,CWnd中包含HWND句柄成員對象是m_hWnd.
  HWND是Windows系統中對所有窗口的一種標識,即窗口句柄。   
  CWnd是MFC類庫中所有窗口類的基類。微軟在MFC中將所有窗口的通用操作都封裝到了這個類中,如:ShowWindow等等,同時它也封裝了窗口句柄即m_hWnd成員。

  個人理解,HWND是Window內核處理對象,而MFC對Windows API進行封裝而提供了操作類,類中包含了對象句柄的成員變量。系統通過HWND進行操作,而我們則更多的通過CWnd提供的函數來間接操作HWND,進而實現目的操作。

  不完全的理解是兩者都可以實現某種功能,而且在一定條件下可以互相轉換,但是,HWND是CWnd基礎的構成部分,CWnd是對HWND操作的類,是一個封裝后的成果類,更加高級也更加簡化。

  兩者不同,卻密不可分。HWND是CWnd類的組成部分,CWnd對象的成員中有HWND對象。

 

兩者怎么轉換?!CWnd類中封裝了這么幾個成員函數:

  CWnd::operator HWND               //可cWndp->operator HWND()調用,得到CWnd對象中HWND句柄對象。

//return this == NULL ? NULL : m_hWnd;

  CWnd::FromHandle                     //Returns a pointer to a CWnd object

//when given a handle to a window.

// If a CWnd object is not attached to the handle,

// a temporary CWnd object is created and attached.

//直譯過來就是,由傳遞的HWND類型參數,

//得到一個與之關聯的CWnd對象或者一個

//臨時的CWnd對象(當所給HWND沒有關

//聯CWnd對象時)。

//那么,這個函數就可以由一個對象句柄的到所在窗口的指針。

//進而可以從HWnd轉換為CWnd。

  CWnd::Attach              //簡單理解就是將HWND句柄與CWnd對象關聯。    

CWnd::Detach             //由於WNDCLASS其實和CWnd根本沒有什么關系,

//它們之間只是通過CWnd的成員HWND聯系起來的。

//Detach的作用是切斷一個CWnd對象和一個有效窗口的聯系。

//因為CWnd是C++的對象,C++的對象有一個生存期的概念,脫離了該對象的作用域,

//這個對象就要被銷毀,但是Windows對象沒有這個特點,當銷毀CWnd對象的時候,

//我們不一定希望WNDCLASS一起被

//銷毀,那么在此之前,我們就先要把這個聯系切斷。

//說白了,就是Attach()的逆操作。

CWnd::GetSafeHwnd         //得到用於獲取窗體的安全句柄

 常用的可以如下轉換:

CWnd * pCWnd;
HWND Handle;
pCWnd=FromHandle(Handle);
Handle=GetSafeHwnd(pCWnd);

 

  最后自己總結下上面毫無邏輯性的介紹:就是HWND是一個對象句柄,可以指向窗口對象、窗口中的空間對象和其他Windows對象。而CWnd是一個窗口類,它的對象一定代表了一個窗口,CWnd類型指針只能指向CWnd的窗口對象。HWND更加底層。

  因為時間原因,此上解釋不太靠譜,待手頭工作完成后,對CWnd和HWND進行更進一步的學習和探索,再進行補充和修改。如大神看到勿噴,如有理解偏差,歡迎指出共同討論、修改,一起進步。

 

  另附上指針和句柄的分析:http://www.cnblogs.com/suanec/p/3892940.html


免責聲明!

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



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