Mapping of Windows Handles to Objects(Windows句柄到(C++)對象的映射)

 

TN003: Mapping of Windows Handles to Objects

技術文章003:Windows句柄到(C++)對象的映射

This note describes the MFC routines that support mapping Windows object handles to C++ objects.

此章節講述了支持Windows對象句柄到C++對象的映射這一MFC常規內容。

The Problem

Windows objects are normally represented by HANDLEs. The MFC classes wrap Windows object handles with C++ objects. The handle wrapping functions of the MFC class library provide a way to find the C++ object that is wrapping the Windows object with a particular handle. There are times when a Windows object does not have a C++ wrapper object, however, and at these times a temporary object is created to act as the C++ wrapper.

問題

Windows對象通常由HANDLEs來表示。MFC類把Windows對象句柄與C++對象關聯在一起。MFC類庫的句柄關聯函數提供了一種方法來找出與某有着獨特句柄的Windows對象相關聯C++對象。然而,有時一個Windows對象沒有一個與之相關聯的C++對象,在這種情況下,一個臨時的C++對象會被創建,並用來與之關聯。

The Windows objects that use handle maps are:

Windows對象句柄與C++對象的映射關係如下:

  • HWND (CWnd and CWnd-derived classes)
  • HDC (CDC and CDC-derived classes)
  • HMENU (CMenu)
  • HPEN (CGdiObject)
  • HBRUSH (CGdiObject)
  • HFONT (CGdiObject)
  • HBITMAP (CGdiObject)
  • HPALETTE (CGdiObject)
  • HRGN (CGdiObject)
  • HIMAGELIST (CImageList)
  • SOCKET (CSocket)

Given a handle to any of these objects, you can find the MFC object that wraps the handle by calling the static member function FromHandle. For example, given an HWND called hWnd:

CWnd::FromHandle(hWnd)

will return a pointer to the CWnd that wraps the hWnd. If that hWnd does not have a specific wrapper object, then a temporary CWnd is created to wrap the hWnd. This makes it possible to get a valid C++ object from any handle.

給你指向任意這些對象的一個句柄,你通過調用靜態成員函數FromHandle來找出與此句柄關聯的MFC對象。例如,給你一個叫做hWnd的HWND,CWnd::FromHandle(hWnd)將會返回一個指針,此指針指向與hWnd相關聯的CWnd對象。如果hWnd沒有一個明確的與之相關聯的對象,那麼一個臨時的CWnd對象將會被創建,用來與hWnd相關聯。這使得從任何句柄得到一個有效的C++對象成爲可能。

Once you have a wrapper object, you can get to its handle through a public member variable. In the case of an CWnd, m_hWnd contains the HWND for that object.

一旦你有一個與某句柄相關聯的對象,那麼你可以通過一個公有的成員變量來得到它的句柄。對於一個CWnd對象而言,m_hWnd表示與之相關聯的句柄HWND。

Attaching Handles to MFC Objects

Given a newly created handle-wrapper object and a handle to a Windows object, you can associate the two by calling Attach. For example:

CWnd myWnd;

myWnd.Attach(hWnd);

This makes an entry in the permanent map associating myWnd and hWnd. Calling CWnd::FromHandle(hWnd) will now return a pointer to myWnd. When myWnd is deleted, the destructor will automatically destroy the hWnd by calling the Windows DestroyWindow function. If this is not desired, the hWnd must be detached from myWnd before the myWnd object is destroyed (normally when leaving the scope at which myWnd was defined). The Detach member function does this.

myWnd.Detach();

 

將句柄與MFC對象關聯

給你一個剛剛創建的與某句柄相關聯的對象和一個指向Windows對象的句柄,通過調用Attach可使之關聯。例如:

CWnd myWnd;

myWnd.Attach(hWnd);

這樣就使得myWnd 和 hWnd永久地關聯在一起。現在調用CWnd::FromHandle(hWnd)的話將會返回一個指向myWnd的指針。當myWnd被刪除時,析構函數會自動地調用Windows的DestroyWindow來銷燬hWnd。如果你不想讓它這樣做,那麼在myWnd這個對象銷燬(通常情況下,是在離開定義myWnd的範圍)之前,必須將hWnd與myWnd分離。成員函數Detach可以幫你實現這一功能。

More About Temporary Objects

Temporary objects are created whenever FromHandle is given a handle that does not already have a wrapper object. These temporary objects are detached from their handle and deleted by the DeleteTempMap functions. The default OnIdle processing in CWinThread automatically calls DeleteTempMap for each class that supports temporary handle maps. This means that you cannot assume a pointer to a temporary object will be valid past the point of exit from the function where the pointer was obtained, as the temporary object will be deleted during the Windows message-loop idle time.

更多信息關於臨時對象

每當傳遞給FromHandle的句柄沒有一個與之相關聯的對象時,臨時對象就會被創建。通過調用DeleteTempMap函數可以將這些臨時對象與它們的句柄分離,並將它們刪除。在CWinThread 裏的OnIdle函數爲每個支持臨時句柄映射的類自動調用DeleteTempMap。那意味着你不能假定一個指向臨時對象的指針一直在程序退出之前都是有效的,因爲臨時對象會在Windows消息循環的空閒時間裏被刪除掉。

Wrapper Objects and Multiple Threads

Both temporary and permanent objects are maintained on a per-thread basis. That is, one thread cannot access another thread’s C++ wrapper objects, regardless of whether it is temporary or permanent. As stated above, temporary objects are deleted when the thread which that temporary object belongs enters OnIdle.

To pass these objects from one thread to another, always send them as their native HANDLE type. Passing a C++ wrapper object from one thread to another will often result in unexpected results.

與句柄關聯的對象和多線程

不管是臨時對象還是持久對象,它們都是基於單線程的基礎之上的。那就是說,一個線程不能訪問另一個線程的與句柄相關聯的C++對象,不管此對象是臨時的還是持久的。按照上述規定,臨時對象將會在它們所屬的線程進入OnIdle時被刪除。

爲了在線程之間傳遞這些對象,經常發送它們自己的HANDLE類型。將一個與句柄相關聯的C++對象從一個線程傳遞到另一個線程會經常導致意想不到的結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章