MFC API - FromHandle()函数

  一 FromHandle()

  MFC 实际上是对内核对象HANDLE(如CDC的m_hDC,CWnd的m_hWnd)封装了这个句柄有关的所有操作,一个类生成一个新对象的时候这个句柄是无效的,要获得这个句柄,可以有两个方法,一个是Create来创建,另一个就是用Attach来与一个已有的句柄建立关联,实际上也就是给类的句柄成员变量赋值。 而有些时候这个句柄不是由我们创建,但是我们要对它的封装类进行操作,(mfc 框架)必需创建对应的封装类包装它

MFC 中对各种包含内核对象的封装类都有FromHandle(HANDLE h)方法。FromHandle(HANDLE h) 先查找由用户定义的内核对象的封装类, 如果找到直接返回,没有找到构造一个临时对象返回.

二 Fromhandle的内部机制

  例如,你的程序中必然对你的主窗口Attach(这是由Framework完成的),这样的话,假如你又得到了你程序的主窗口句柄hwndMain,你如果再调用FromHandle(hwndMain),它返回的将是你的App中的m_pMainWnd,原因就是FromHandle会维持一个内部的列表,纪录每个hwnd与CWnd的关联情况,如果一旦一个hwnd早已与某个CWnd对象相关连,它会返回该CWnd对象的指针。既然如此,FromHandle返回的便是m_pMainWnd,而此对象Framework会自动析构,因此你只是得到了该指针的一个副本,不能对其作析沟操作,否则会导致你的程序运行不正常。

   考虑另外一种情况,就是一个hwnd与任何对象都没有关联(比如,你用API
CreateWindow新建了一个窗口),此时的hwnd尚未与任何CWnd对象关联,如果你用FromHandle(hwnd),FromHandle便会临时new一个CWnd对象,并Attatch到此hwnd,然后返回给你。我刚才说了,FromHandle会维持一个hwnd与CWnd关联的列表,每当Framework OnIdle时,它便会检查此列表,一旦发现某个CWnd是FromHandle临时创建的对象,它便会首先Detach此对象,然后delete之。因此,你在程序中也不必delete从FromHandle得到的对象指针,但这种指针只在一次消息处理过程中有效。

三 与FromHandlePermanent()的区别

FromHandlePermanent函数,它当且仅当hwnd已与某个CWnd对象关联时才返回此对象的指针,否则返回NULL。这也是它为什么叫Permanent——区别于FromHandle会new一个临时的CWnd对象。 这两个函数都是在公共的 CMapHandle 中查找句柄对应的 CWnd 对象(通过一个CBT钩子,CWnd 对象将创建时得到的句柄和自己的指针纪录到 CMapHandle),区别是如果找不到相关的对象,FromHandle 在CMapHandle 的 temporarylist 中创建并返回一个临时对象的指针 ,而 FromHandlePermanent 返回 NULL(此外 FromHandlePermanent 不使用 temporarylist ,所以不查找 temporarylist 下的句柄)。

四  使用注意

  大部分情况下,对任意句柄使用 FromHandle 是不错的,因为大多情况下只利用返回的 CWnd 指针调用的非虚函数,返回的即使是一个临时对象,调用也是正确的(MFC 中较少用 FromHandlePermanent,除非确定句柄是由本线程创建的或不需要创建临时对象)。

但是在某些情况下,比如从使用 MFC 的非 Extension DLL 中创建的窗口,这个机制会有问题,因为窗口创建在其他的 MFC 模块之下,在 EXE 中调用 FromHandle,由于该模块的 CMapHandle 对象某有相关的纪录,所以只能得到临时对象,如果使用返回的指针调用 CWnd 的虚函数如 PreTranslateMessage,得到调用的是 CWnd::PreTranslateMessage,而不是 DLL 中的 CWnd 派生类重载过的 CWnd::PreTranslateMessage。


  对于GDI对象,以上的分析也是适用的。

发布了69 篇原创文章 · 获赞 10 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/u010096608/article/details/103735139