今天在寫一個小的網絡應用,需要用到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