CWnd::FromHandle与CWnd::FromHandlePermanent有什么区别

来源:互联网 发布:前瞻数据 编辑:程序博客网 时间:2024/06/14 17:20
你可以参考 MFC 代码中 FromHandle 和 FromHandlePermanent 的实现,这两个函数都是在公共的 CMapHandle 中查找句柄对应的 CWnd 对象(通过一个CBT钩子,CWnd 对象将创建时得到的句柄和自己的指针纪录到 CMapHandle),区别是如果找不到相关的对象,FromHandle 在CMapHandle 的 temporarylist 中创建并返回一个临时对象的指针 ,而 FromHandlePermanent 返回 NULL(此外 FromHandlePermanent 不使用 temporarylist ,所以不查找 temporarylist 下的句柄)。

我想 MFC 引入这个机制的原因是需要从 WindowProc、钩子或 API 返回的 HWND 值中得到“正确”的 CWnd 指针,比如 CMainFrame, CView 的指针。因为需要从这些指针调用 CWnd 的虚函数(如PreTranslateMessage),这些虚函数可能被重载过。

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

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

关于 CMapHandle 的描述可以参考 MFC 代码中的以下函数和结构:
_AFX_MODULE_THREAD_STATE,CThreadLocal
CHandleMap* PASCAL afxMapHWND(BOOL bCreate)
LRESULT CALLBACK _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
BOOL CWinThread::PreTranslateMessage(MSG* pMsg)

BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)

转自:http://bbs.csdn.net/topics/20268542

0 0
原创粉丝点击