TN003:将 Windows 句柄映射到对象

此说明介绍了支持将 Windows 对象句柄映射到C++对象的 MFC 例程。

问题

Windows 对象通常由各种 HANDLE 对象表示。MFC 类使用C++对象包装 Windows 对象句柄。 通过 MFC 类库的句柄包装函数,可以找到包装具有特定句柄的 Windows 对象的C++对象。 但是,有时对象没有C++包装器对象,而此时系统会创建一个临时对象来充当C++包装器。

使用句柄映射的 Windows 对象如下所示:

  • HWND (CWndCWnd-derived 类)

  • HDC (CDCCDC-derived 类)

  • HMENU (CMenu

  • HPEN (CGdiObject

  • HBRUSH (CGdiObject

  • HFONT (CGdiObject

  • HBITMAP (CGdiObject

  • HPALETTE (CGdiObject

  • HRGN (CGdiObject

  • HIMAGELIST (CImageList

  • SOCKET (CSocket

对于其中任一对象的句柄,可以通过调用静态方法 FromHandle找到包装句柄的 MFC 对象。 例如,给定名为 hWnd 的 HWND,以下行将返回指向包装 hWndCWnd指针:

CWnd::FromHandle(hWnd)

如果 hWnd 没有特定的包装器对象,则会创建一个临时对象 CWnd 来包装 hWnd。 这样就可以从任何句柄获取有效的C++对象。

有了包装对象后,可以从包装类的公共成员变量中检索其句柄。 在这种情况下 CWndm_hWnd 包含该对象的 HWND。

将句柄附加到 MFC 对象

给定新创建的句柄包装对象和 Windows 对象的句柄,可以通过调用 Attach 函数来关联这两个对象,如以下示例所示:

CWnd myWnd;
myWnd.Attach(hWnd);

这会使永久映射中的条目关联 myWndhWnd。 调用 CWnd::FromHandle(hWnd) 现在将返回指向 myWnd 的指针。 删除 myWnd 后,析构函数将通过调用 Windows DestroyWindow 函数自动销毁 hWnd。 如果不需要,则必须先从 myWnd 分离 hWnd,然后 myWnd 才会被销毁(通常离开 myWnd 的定义范围时)。 此方法 Detach 执行此作。

myWnd.Detach();

有关临时对象的详细信息

每当 FromHandle 给定没有包装器对象的句柄时,都会创建临时对象。 这些临时对象与其句柄分离,并由 DeleteTempMap 函数删除。 默认情况下 ,CWinThread::OnIdle 会自动调用 DeleteTempMap 支持临时句柄映射的每个类。 这意味着不能假定指向临时对象的指针在从获取指针的函数退出点后有效。

包装器对象和多个线程

临时对象和永久对象均按线程维护。 也就是说,无论线程是临时的还是永久性的,一个线程都无法访问另一个线程的C++包装器对象。

若要将这些对象从一个线程传递到另一个线程,请始终将它们作为本机 HANDLE 类型发送。 将C++包装器对象从一个线程传递到另一个线程通常会导致意外结果。

另请参阅

按编号列出的技术说明
按类别列出的技术说明