作者:朱金灿

来源:http://blog.csdn.net/clever101/

使用AfxGetMainWnd函数获取MFC程序中的主框架类指针是一个常用作法。但是你会发现这一做法有时也会失灵。不信, 你测试一下下面的代码:

  1. unsigned __stdcall SecondThreadFunc( void* pArguments )
  2. {
  3. CMainFrame* pMainWnd =  (CMainFrame*)AfxGetMainWnd();
  4. if (NULL!=pMainWnd)
  5. {
  6. CView *pView = pMainWnd->GetActiveView();
  7. if (NULL!=pView)
  8. {
  9. CDC *pDC = pView->GetDC();
  10. ASSERT(NULL!=pDC);
  11. pDC->TextOut(100,100,_T("来自线程的字符串"));
  12. pView->ReleaseDC(pDC);
  13. }
  14. }
  15. return 0;
  16. }
  17. void CMainFrame::OnTest1()
  18. {
  19. // TODO: 在此添加命令处理程序代码
  20. HANDLE hThread;
  21. unsigned threadID;
  22. hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );
  23. // Destroy the thread object.
  24. CloseHandle( hThread );
  25. }

运行OnTest1函数,你会发现客户区并没有打印"来自线程的字符串"。下面我们把线程函数变一下:

  1. unsigned __stdcall SecondThreadFunc( void* pArguments )
  2. {
  3. //   CMainFrame* pMainWnd =  (CMainFrame*)AfxGetMainWnd();
  4. COwnerApp *pApp = (COwnerApp *)AfxGetApp();
  5. CMainFrame* pMainWnd = (CMainFrame*) pApp->m_pMainWnd;
  6. if (NULL!=pMainWnd)
  7. {
  8. CView *pView = pMainWnd->GetActiveView();
  9. if (NULL!=pView)
  10. {
  11. CDC *pDC = pView->GetDC();
  12. ASSERT(NULL!=pDC);
  13. pDC->TextOut(100,100,_T("来自线程的字符串"));
  14. pView->ReleaseDC(pDC);
  15. }
  16. }
  17. return 0;
  18. }

运行OnTest1函数,我们发现视图客户区出现了"来自线程的字符串"。接下来我们调试进去AfxGetMainWnd函数,发现AfxGetMainWnd函数如下:

  1. _AFXWIN_INLINE CWnd* AFXAPI AfxGetMainWnd()
  2. { CWinThread* pThread = AfxGetThread();
  3. return pThread != NULL ? pThread->GetMainWnd() : NULL; }

由于AfxGetThread()函数返回为NULL,所以AfxGetMainWnd函数返回为NULL。为什么会这样呢?下面我提出我的猜想(本人暂时验证不了,仅起抛砖引玉的作用)。我估计是MFC在多线程中大量运用了TLS(线程本地存储)来保存某些状态,主框架窗口指针属于主线程的TLS(线程本地存储)保存的状态,但是应用程序类指针不属于TLS保存的状态,它可以在该进程的任何线程获取。

(转)使用AfxGetMainWnd函数的一个心得的更多相关文章

  1. AfxGetMainWnd()函数用法

    CWnd* AfxGetMainWnd( ); 使用AfxGetMainWnd函数获取MFC程序中的主框架类指针是一个常用作法. 就是获得应用程序主窗口的指针,AfxGetMainWnd()-> ...

  2. 用javascript 写个函数返回一个页面里共使用了多少种HTML 标签

    今天我无意间看到一个面试题: 如何用javascript 写个函数返回一个页面里共使用了多少种HTML 标签? 不知你看到 是否蒙B了,如果是我 面试,肯定脑子嗡嗡的响.... 网上搜了搜也没有找到答 ...

  3. Entity Framework 6 Recipes 2nd Edition(11-1)译 -> 从“模型定义”函数返回一个标量值

    第11章函数 函数提供了一个有力代码复用机制, 并且让你的代码保持简洁和易懂. 它们同样也是EF运行时能利用的数据库层代码.函数有几类: Rowset Functions, 聚合函数, Ranking ...

  4. Entity Framework 6 Recipes 2nd Edition(11-2)译 -> 为一个”模型定义”函数返回一个计算列

    11-3. 为一个”模型定义”函数返回一个计算列 问题 想从”模型定义”函数里返回一个计算列 解决方案 假设我们有一个员工(Employee)实体,属性有: FirstName, LastName,和 ...

  5. Entity Framework 6 Recipes 2nd Edition(11-5)译 -> 从”模型定义”函数返回一个匿名类型

    11-5. 从”模型定义”函数返回一个匿名类型 问题 想创建一个返回一个匿名类型的”模型定义”函数 解决方案 假设已有游客(Visitor) 预订(reservation)房间(hotel ) 的模型 ...

  6. C++学习45 流成员函数put输出单个字符 cin输入流详解 get()函数读入一个字符

    在程序中一般用cout和插入运算符“<<”实现输出,cout流在内存中有相应的缓冲区.有时用户还有特殊的输出要求,例如只输出一个字符.ostream类除了提供上面介绍过的用于格式控制的成员 ...

  7. 【转载】让c++ 函数返回一个数组

    在c++中是不允许数组作为函数的返回值的 int [] someFunction( ); //ILLEGAL 要想实现函数返回一个数组,那返回对应数组里面类型的指针 you must return a ...

  8. js eval()函数 接收一个字符串,做为js代码来执行。 如: s='var d="kaka"'; 或者s=‘function (code){return code }’;

    eval函数接收一个参数s,如果s不是字符串,则直接返回s.否则执行s语句.如果s语句执行结果是一个值,则返回此值,否则返回undefined. 需要特别注意的是对象声明语法“{}”并不能返回一个值, ...

  9. jQuery 函数位于一个 document ready 函数中

    在我们的实例中的所有 jQuery 函数位于一个 document ready 函数中: $(document).ready(function(){ --- jQuery functions go h ...

随机推荐

  1. NewsLetter001

    http://www.learn-english-today.com/ Project management - Iron out problems. – resolve issues. Critic ...

  2. sumatrapdf 软件介绍

    sumatrapdf  软件介绍 介绍 支持PDF, ePub, Mobi, XPS, DjVu, CHM, CBZ 和 CBR格式的电子文件 仅支持Windows,原因见官网论坛 绿色版,小巧,于此 ...

  3. django1.8读书笔记模版高级进阶

    一.概述 想要定制或者扩展模版引擎,模版系统工作原理,自动转移特征 名词解析:模板 渲染 就是是通过从context获取值来替换模板中变量并执行所有的模板标签. 二.Context处理器 如果在模版中 ...

  4. FPGA按键去抖verilog代码

    按键去抖的原因及其分类就不罗嗦了. 在这里解释一段代码,代码是网上找的,看了半天没懂,无奈查了半天想了半天,终于明白了... module sw_debounce(clk,rst_n,sw1,sw2, ...

  5. Spring Cloud Eureka自我保护机制(服务无法剔除)

    说明 自我保护背景 首先对Eureka注册中心需要了解的是Eureka各个节点都是平等的,没有ZK中角色的概念, 即使N-1个节点挂掉也不会影响其他节点的正常运行. 默认情况下,如果Eureka Se ...

  6. Linux写时拷贝技术(copy-on-write)

    1.传统的fork()函数创建一个子进程,子进程和父进程共享正文段,复制数据段,堆,栈到子进程示意图如下: 2.Linux的fork()函数-写时复制(copy-on-write)创建一个子进程,内核 ...

  7. ny710 外星人的供给站

    外星人的供给站 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 外星人指的是地球以外的智慧生命.外星人长的是不是与地球上的人一样并不重要,但起码应该符合我们目前对生命基本 ...

  8. Python从MongoDB中按天读取数据并格式化日志

    #$cat SpeechMongoHandle.py from pymongo import Connection import time import datetime # CTRL_A='\x01 ...

  9. svn show log 不显示作者等信息解决

    原因很简单,只需要修改svnserver.conf文件里面:anon-access = read -->修改为 anon-access = none.很诧异吧...修改过后测试没有问题,log可 ...

  10. upupw phpmyadmin写shell

    废话: upupw给我的感觉是一个充当了waf毁三观的垃圾程序.然而,我讨厌的程序,管理员都特别喜欢用. 你会发现直接用之前那套写shell的建表然后在值里添加shell代码写到一个路径不可以了. C ...