TN003: 映射Windows句柄到对象

来源:互联网 发布:java swing多线程 编辑:程序博客网 时间:2024/05/05 04:50

 

 

问题

Windows对象通常由HANDLEs来表示。MFC类把Windows对象句柄与C++对象关联在一起。MFC类库的句柄关联函数提供了一种方法来找出与某有着独特句柄的Windows对象相关联C++对象。然而,有时一个Windows对象没有一个与之相关联的C++对象,在这种情况下,一个临时的C++对象会被创建,并用来与之关联。

 

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)
  •  

    给你指向任意这些对象的一个句柄,你通过调用静态成员函数FromHandle来找出与此句柄关联的MFC对象。例如,给你一个叫做hWndHWND:

    CWnd::FromHandle(hWnd)

    将会返回一个指针,此指针指向与hWnd相关联的CWnd对象。如果hWnd没有一个明确的与之相关联的对象,那么一个临时的CWnd对象将会被创建,用来与hWnd相关联。这使得从任何句柄得到一个有效的C++对象成为可能。

    一旦你有一个与某句柄相关联的对象,那么你可以通过一个公有的成员变量来得到它的句柄。对于一个CWnd对象而言,m_hWnd表示与之相关联的句柄HWND

     

    将句柄与MFC对象关联

    给你一个刚刚创建的与某句柄相关联的对象和一个指向Windows对象的句柄,通过调用Attach可使之关联。例如:

    CWnd myWnd;

    myWnd.Attach(hWnd);

    这样就使得myWnd hWnd永久地关联在一起。现在调用CWnd::FromHandle(hWnd)的话将会返回一个指向myWnd的指针。当myWnd被删除时,析构函数会自动地调用WindowsDestroyWindow来销毁hWnd。如果你不想让它这样做,那么在myWnd这个对象销毁(通常情况下,是在离开定义myWnd的范围)之前,必须将hWndmyWnd分离。成员函数Detach可以帮你实现这一功能。

     

     

    更多信息关于临时对象

    每当传递给FromHandle的句柄没有一个与之相关联的对象时,临时对象就会被创建。通过调用DeleteTempMap函数可以将这些临时对象与它们的句柄分离,并将它们删除。在CWinThread 里的OnIdle函数为每个支持临时句柄映射的类自动调用DeleteTempMap。那意味着你不能假定一个指向临时对象的指针一直在程序退出之前都是有效的,因为临时对象会在Windows消息循环的空闲时间里被删除掉。

     

    与句柄关联的对象和多线程

    不管是临时对象还是持久对象,它们都是基于单线程的基础之上的。那就是说,一个线程不能访问另一个线程的与句柄相关联的C++对象,不管此对象是临时的还是持久的。按照上述规定,临时对象将会在它们所属的线程进入OnIdle时被删除。

    为了在线程之间传递这些对象,经常发送它们自己的HANDLE类型。将一个与句柄相关联的C++对象从一个线程传递到另一个线程会经常导致意想不到的结果。

    原创粉丝点击