MFC 对 Windows API 进行了封装,在很多方面都会提供便利。用 FromHandle 返回零时对象的指针,就可以调用各种类的方法。临时对象会在 OnIdle 中销毁。这里对 FromHandle 的实现原理从源码上进行解析。

//
// 1
//
CWnd* PASCAL CWnd::FromHandle(HWND hWnd)
{
CHandleMap* pMap = afxMapHWND(TRUE); //create map if not exist
ASSERT(pMap != NULL);
CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd);
#ifndef _AFX_NO_OCC_SUPPORT
pWnd->AttachControlSite(pMap);
#endif
ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
return pWnd;
}
这是 CWnd 的 FromHandle 方法,大致的意思为从 CHandleMap 中获取临时 CWnd 对象的指针。
//
// 2
//
CHandleMap* PASCAL afxMapHWND(BOOL bCreate)
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
if (pState->m_pmapHWND == NULL && bCreate)
{
BOOL bEnable = AfxEnableMemoryTracking(FALSE);
#ifndef _AFX_PORTABLE
_PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
#endif pState->m_pmapHWND = new CHandleMap(RUNTIME_CLASS(CTempWnd),
offsetof(CWnd, m_hWnd));
#ifndef _AFX_PORTABLE
AfxSetNewHandler(pnhOldHandler);
#endif
AfxEnableMemoryTracking(bEnable);
}
return pState->m_pmapHWND;
}
再看
#define offsetof(s,m) (size_t)&(((s *)0)->m)
继续
//
// 3
//
CObject* CHandleMap::FromHandle(HANDLE h)
{
ASSERT(m_pClass != NULL);
ASSERT(m_nHandles == || m_nHandles == );
if (h == NULL)
return NULL;
CObject* pObject = LookupPermanent(h);
if (pObject != NULL)
return pObject; // return permanent one
else if ((pObject = LookupTemporary(h)) != NULL)
{
HANDLE* ph = (HANDLE*)((BYTE*)pObject + m_nOffset);
ASSERT(ph[] == h || ph[] == NULL);
ph[] = h;
if (m_nHandles == )
{
ASSERT(ph[] == h || ph[] == NULL);
ph[] = h;
}
return pObject; // return current temporary one
}
// This handle wasn't created by us, so we must create a temporary
// C++ object to wrap it. We don't want the user to see this memory
// allocation, so we turn tracing off.
BOOL bEnable = AfxEnableMemoryTracking(FALSE);
#ifndef _AFX_PORTABLE
_PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
#endif
CObject* pTemp = NULL;
TRY
{
pTemp = m_pClass->CreateObject();
if (pTemp == NULL)
AfxThrowMemoryException();
m_temporaryMap.SetAt((LPVOID)h, pTemp);
}
CATCH_ALL(e)
{
#ifndef _AFX_PORTABLE
AfxSetNewHandler(pnhOldHandler);
#endif
AfxEnableMemoryTracking(bEnable);
THROW_LAST();
}
END_CATCH_ALL
#ifndef _AFX_PORTABLE
AfxSetNewHandler(pnhOldHandler);
#endif
AfxEnableMemoryTracking(bEnable);
// now set the handle in the object
HANDLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset); // after CObject
ph[] = h;
if (m_nHandles == )
ph[] = h;
return pTemp;
}

解析 MFC 中的 FromHandle的更多相关文章

  1. 深入解析MFC -- 句柄与对象的关系

    CWnd::FromHandlePermanent ——根据窗口句柄得到CWnd*指针 This function, unlike FromHandle, does not create tempor ...

  2. MFC中的一些视图

    本章主要介绍MFC中主要的视图类,这些继承自Cview类. 继承关系如上图所示. 滚动视图 CscrollView给Cview添加了基本的滚动功能,它包含WM_VSCROLL和WM_HSCROLL消息 ...

  3. MFC中线程相关知识

    MFC中把线程分为两种类型,UI线程和工作者线程. MFC中启动一个线程的最好方法是调用AfxBeginThread,有两个版本,一个用于启动Ui线程,另外一个用于启动工作者线程.在MFC程序中,只有 ...

  4. MFC中获取各个窗口之间的句柄或者指针对象的方法

    MFC在非常多的对话框操作中,我们常常要用到在一个对话框中调用还有一个对话框的函数或变量.能够用例如以下方法来解决.    HWND hWnd=::FindWindow(NULL,_T("S ...

  5. 深度解析VC中的消息(转发)

    http://blog.csdn.net/chenlycly/article/details/7586067 这篇转发的文章总结的比较好,但是没有告诉我为什么ON_MESSAGE的返回值必须是LRES ...

  6. C运行时库(C Run-time Library)详解(提供的另一个最重要的功能是为应用程序添加启动函数。Visual C++对控制台程序默认使用单线程的静态链接库,而MFC中的CFile类已暗藏了多线程)

    一.什么是C运行时库 1)C运行时库就是 C run-time library,是 C 而非 C++ 语言世界的概念:取这个名字就是因为你的 C 程序运行时需要这些库中的函数. 2)C 语言是所谓的“ ...

  7. 【VS开发】MFC中调用C函数模块的解决方案

    [VS开发]MFC中调用C函数模块的解决方案 标签(空格分隔): [VS开发] 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明:最近调试基于MFC的程序 ...

  8. 浅解析js中的对象

    浅解析js中的对象 原文网址:http://www.cnblogs.com/foodoir/p/5971686.html,转载请注明出处. 前面的话: 说到对象,我首先想到的是每到过年过节见长辈的时候 ...

  9. MFC中使用FLASH

    一.准备工作 第一步:下载并安装Adobe Flash Player. 从官方网站(http://get.adobe.com/cn/flashplayer/)上下载最新的Flash Player(大约 ...

随机推荐

  1. R文件报错

    res中drawable中的资源文件进行命名时只能用0-9或者a-z或者-,其他的东西不能使用,也禁止在重命名时开头使用大写字母

  2. ceph学习之PG

    PG的计算公式: 整个集群PG的计算公式 Total PGs = ((Total_number_of_OSD * ) / max_replication_count) 每个POOL中PG的计算公式: ...

  3. bzoj4804

    莫比乌斯反演 我不会推线性筛 留坑

  4. dubbo 自定义过滤器,打印接口调用信息

    dubbo提供了web filter类似的com.alibaba.dubbo.rpc.Filter,这样,我们可以在dubbo提供的服务提供方和消费方都可以自定义过滤 器,从而可以获得方法调用的时间或 ...

  5. OS__信号量(semaphore)PV操作

    信号量的概念 1.信号量的类型定义 信号量(semaphore)的数据结构为记录型数据结构一个值和一个指针,指针指向等待该信号量的下一个进程.信号量的值与相应资源的使用情况有关,在操作系统中,信号量用 ...

  6. Win10资源管理器中的库文件夹按照修改日期排序

    win7之后添加的库十分的好用,可以将下载,音乐,文档设置在我的电脑(win10叫此电脑)首页,快速进入. 我对文件夹设置了按照时间排序,这样进去就可以直接看到最近下载了什么文件.但是win10用时间 ...

  7. android摄像头获取图像——第三弹

    相机获取图像的格式问题 android中承认的格式的参考网址为 :http://developer.android.com/reference/android/graphics/ImageFormat ...

  8. 3DMAX 如何将删去的面补回来

    1.例如下面长方体被删除一个面 2.点击主键盘区数字键[3] ,进入[边界]修改模式 ,使用鼠标点击 被删除面的边界,并点击[修改面板]---[封口],例如下图:

  9. c# 添加reference后,Visual Studio 仍然提示无法找到函数, 询问是否添加了含有这个函数的Assembly

    1.问题 添加reference后,编译仍然无法通过,测试工程添加这个assembly 就可以编译通过. 对比了这个assembly的 .net 版本,也没问题 由于工程是x64的, 添加的assem ...

  10. [Xcode 实际操作]九、实用进阶-(6)在Swift文件中调用Object-C的类和方法

    目录:[Swift]Xcode实际操作 本文将演示在Swift文件中调用Object-C的类和方法. 在项目文件夹[DemoApp]上点击鼠标右键 ->[New File]创建一个Object- ...