一 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对象,以上的分析也是适用的。
 

FromHandle函数的更多相关文章

  1. C/C++ 笔试题

    /////转自http://blog.csdn.net/suxinpingtao51/article/details/8015147#userconsent# 微软亚洲技术中心的面试题!!! 1.进程 ...

  2. 通过HWND获得CWnd指针

    cwnd 又为计算机网络中拥塞窗口(congestion window)的简写.拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化.发送方让自己的发送窗口还可能小于拥塞窗口. CWnd是MFC窗口类 ...

  3. MFC编程基础

    http://www.cnblogs.com/lzmfywz/archive/2012/03/15/2399403.html 一.MFC类库概述 MFC(Microsoft Foundation cl ...

  4. C/C++笔试题(很多)

    微软亚洲技术中心的面试题!!! .进程和线程的差别. 线程是指进程内的一个执行单元,也是进程内的可调度实体. 与进程的区别: (1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位 (2 ...

  5. MFC永久窗口对象与临时窗口对象

    这篇讲得很清楚,就转过来了,原文如下: 因项目需要,最近在学习MFC,下午在一篇教程中提到了临时窗口.永久窗口,作者让读者自行查阅MSDN,了解临时窗口与永久窗口的概念,出于好奇,出于方便,直接百度一 ...

  6. 精通 VC++ 实效编程280例 - 01 窗口

    窗口是屏幕上的一个矩形区域.窗口分为3种:重叠窗口.弹出窗口和子窗口.每个窗口都有由系统绘制的“非客户区”和应用程序绘制的“客户区”.在 MFC 中,CWnd 类为各种窗口提供了基类. 1 通过 HW ...

  7. GetDlgItem的用法小结

    GetDlgItem用于获得指定控件ID的窗体指针,函数原型如下: HWND GetDlgItem( HWND hDlg, int nIDDlgItem ); CWnd* GetDlgItem(int ...

  8. MFC 线程中CWnd对象

    尽量不要在MFC线程中将CWnd作为参数传递,会引起crash 正确的做法: 1. 将CWnd对应的handle传进来,通过CWnd::FromHandle()函数转换: 2. 在线程中用SendMe ...

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

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

随机推荐

  1. asp.net的运行内幕

    每当浏览器向IIS发送一个页面请求的时候,相应的网页就会被编译成DLL文件,然后由JIT来运行这个DLL文件,最后将运行结果发送给客户端.一旦网页发送了变化,下次再请求页面的话,网页又会被重新被编译成 ...

  2. SVN记住用户名和密码后如何修改

    今天遇到一个SVN检出代码用户验证问题.由于自己最近参与了好几个项目,一时间忙不过来.所以希望跟着自己的试用期的同事帮我测试一下刚修改完成的新功能是否有问题.但是该同事没有项目中权限,正好今天恰逢星期 ...

  3. Linux下安装启动nginx的过程

    1.首先将nginx的安装包传到虚拟机里的/home目录下 2.为了方便nginx运行而不影响linux安全需创建组合用户 groupadd -r nginxuseradd -r -g nginx  ...

  4. MarkdownPad2

    http://markdownpad.com/ MarkdownPad2

  5. C++之编码问题(Unicode,ASCII,本地默认)

    本篇文章试图回答的问题: 1.char* pStr="我aa";这句代码执行后,pStr指向的内存区域中存储的字节到底是根据什么码表而来的呢?该字符串占几个字节? 2.将一个VS2 ...

  6. shell常识总结

    #!/bin/bash cmd="ls -lt | grep ^d | awk 'NR==1 {print $9}'" $cmd 这是一个获取文件夹名字的脚本,但是却提示: ls: ...

  7. HW4.8

    import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...

  8. POJ3750: 小孩报数问题+一道经典约瑟夫问题(猴子选大王)

    又一次因为一个小错误,POJ上Wrong Answer了无数次..... 在差不多要放弃的时候,发现了这个猥琐的不能再猥琐的bug,改完了提交就AC了,简直无语.... 本题wo采用模拟方法: 1 # ...

  9. php中的$_SERVER从哪来

    前几个月学了个tcpdump抓包命令,遇到任何问题总想试试,真是程序员的终级武器呀,它像显微镜一下,把任何的丑陋的bug都显示在你的面前. 为什么有题目中所说的疑问呢?因为我发现在不同的环境下面,我获 ...

  10. mysql字符串分割函数(行转列)

    由于工作需要需要处理一些以逗号分隔的字符串,每次都要现做很是麻烦,网上找了很多都没有现成的,好吧,自己动手写一个好了 )) ) BEGIN /*函数功能: 把带逗号的字符串分割取出 参数: num 要 ...