MFC框架各部分指针获取方式

前人在CSDN总结的,曾经帮助过我,整理总结一下,希望也能帮助一下别人。

获得CWinApp

获得CMainFrame

获得CChildFrame

获得CDocument

获得CView

在CWinApp中

AfxGetMainWnd()

m_pMainWnd

AfxGetMainWnd()->MDIGetActive()

AfxGetMainWnd()->GetActiveFrame()

SDI:AfxGetMainWnd()->GetActiveView()->GetDocument()

MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument()

SDI:AfxGetMainWnd()->GetActiveView()  
MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView() 
在CMainFrame中

AfxGetApp()

theApp

 

MDIGetActive()

GetActiveFrame()

SDI:GetActiveView()->GetDocument()  
MDI:MDIGetActive()->GetActiveView()->GetDocument()  
SDI:GetActiveView()  
MDI:MDIGetActive()->GetActiveView() 
在CChildFrame中

AfxGetApp()

theApp

GetParentFrame()  GetActiveView()->GetDocument()   GetActiveView()
在CDocument中

AfxGetApp()

theApp

AfxGetMainWnd()  

AfxGetMainWnd()->MDIGetActive()

AfxGetMainWnd()->GetActiveFrame()

  POSITION   pos   =   GetFirstViewPosition();GetNextView(pos)  
在CView中

AfxGetApp()

theApp

AfxGetMainWnd()   GetParentFrame()   GetDocument()  
在其他类中

AfxGetApp()

AfxGetMainWnd()  

AfxGetMainWnd()->MDIGetActive()

AfxGetMainWnd()->GetActiveFrame()

SDI:AfxGetMainWnd()->GetActiveView()->GetDocument()

MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument()

SDI:AfxGetMainWnd()->GetActiveView()  
MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView() 
 
理一理MFC的这几个类的关系,可以很容易明白上面的这些乱七八糟的逻辑。
App是应用域,所有的域中的东西都可以通过全局函数访问到它。
MainFrame是主框架,也基本可以用全局函数访问到。
MainFrame下是若干个ChildFrame,ChildFrame中若干个View和Document(可能不成对),ChildFrame管理着View,View和Document进行互操作。
因此整体框架就出来了,一般除了直接应用的关系都可以通过MainFrame-->Active ChildFrame-->Active View-->Document这条线进行访问,这应该叫什么来自?万能方法吧^_^。
恕我懒惰,不愿意画一个更详细的图解,凑合着看看吧。
 

 对于初学者来说,在MFC中获得各种类的指针是个障碍。如:要获得另一窗体视图类中的某控件指针,首先必须获得目标视图指针,然后再通过该视图指针用GetDlgItem函数才可获得控件指针。

只考虑文档、视图和框架窗口间的关系,常用的指针获取方法如下:

全局函数AfxGetApp可以得到CWinApp应用类指针
AfxGetApp()->m_pMainWnd为框架窗口指针
在框架窗口中:CFrameWnd::GetActiveDocument得到当前活动文档指针
在框架窗口中:CFrameWnd::GetActiveView得到当前活动视指针
在视中:CView::GetDocument得到对应的文档指针
在文档中:CDocument::GetFirstViewPosition,CDocument::GetNextView用来遍历所有和文档关联的视。
在文档中:CDocument::GetDocTemplate得到文档模板指针
在多文档界面中:CMDIFrameWnd::MDIGetActive得到当前活动的MDI子窗口

MFC中一些类的指针获取方法如下:

1) 在View中获得Doc指针 
2) 在App中获得MainFrame指针 
3) 在View中获得MainFrame指针 
4) 获得View(已建立)指针 
5) 获得当前文档指针 
6) 获得状态栏与工具栏指针 
7) 获得状态栏与工具栏变量 
8) 在Mainframe获得菜单指针 
9) 在任何类中获得应用程序类 
10) 从文档类取得视图类的指针(1) 
11) 在App中获得文档模板指针 
12) 从文档模板获得文档类指针 
13) 在文档类中获得文档模板指针 
14) 从文档类取得视图类的指针(2) 
15) 从一个视图类取得另一视图类的指针 
16) 获取分割视图中各个视图的指针

  VC中编程对于刚刚开始学习的同学,最大的障碍和问题就是消息机制和指针获取与操作。其实这些内容基本上是每本VC学习工具书上必讲的内容,而且通过MSDN很多问题都能解决。 
  下面文字主要是个人在编程中指针使用的一些体会,说的不当的地方请指正。 
  一般我们使用的框架是VC提供的Wizard生成的MFC App Wizard(exe)框架,无论是多文档还是单文档,都存在指针获取和操作问题。下面这节内容主要是一般的框架,然后再讲多线程中的指针使用。使用到的类需要包含响应的头文件。首先一般获得本类(视,文档,对话框都支持)实例指针this,用this的目的,主要可以通过类中的函数向其他类或者函数中发指针,以便于在非本类中操作和使用本类中的功能。

1) 在View中获得Doc指针

  CYouSDIDoc *pDoc=GetDocument();

  一个视只能有一个文档。 
 2) 在App中获得MainFrame指针 
  CWinApp 中的 m_pMainWnd变量就是MainFrame的指针 
  也可以:

  CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd(); 
 3) 在View中获得MainFrame指针

  CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd; 
 4) 获得View(已建立)指针

  CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd; 
  CyouView *pView=(CyouView *)pMain->GetActiveView(); 
5) 获得当前文档指针

  CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument(); 
 6) 获得状态栏与工具栏指针

  CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR); 
  CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);

7) 如果框架中加入工具栏和状态栏变量还可以这样

  (CMainFrame *)GetParent()->m_wndToolBar; 
  (CMainFrame *)GetParent()->m_wndStatusBar;

8) 在Mainframe获得菜单指针

  CMenu *pMenu=m_pMainWnd->GetMenu(); 
 9) 在任何类中获得应用程序类 
  用MFC全局函数AfxGetApp()获得。 
10) 从文档类取得视图类的指针 
  我是从http://download.cqcnc.com/soft/program/article/vc/vc405.html学到的,从文档获得视图类指针目的一般为了控制同一文档的多个视图的定位问题,我的体会特别是文字处理CEditView当产生多个视图类时,这个功能是非常需要的。 
  CDocument类提供了两个函数用于视图类的定位: 
  GetFirstViewPosition()和GetNextView() virtual POSITION GetFirstViewPosition() const; 
  virtual CView* GetNextView(POSITION& rPosition) const;

注意:GetNextView()括号中的参数用的是引用方式,因此执行后值可能改变。 
  GetFirstViewPosition()用于返回第一个视图位置(返回的并非视图类指针,而是一个POSITION类型值),GetNextView()有两个功能:返回下一个视图类的指针以及用引用调用的方式来改变传入的POSITION类型参数的值。很明显,在Test程序中,只有一个视图类,因此只需将这两个函数调用一次即可得到CTestView的指针如下(需定义一个POSITION结构变量来辅助操作):

  CTestView* pTestView; 
  POSITION pos=GetFirstViewPosition(); 
  pTestView=GetNextView(pos);

  这样,便可到了CTestView类的指针pTestView.执行完几句后,变量pos=NULL,因为没有下一个视图类,自然也没有下一个视图类的POSITION.但是这几条语句太简单,不具有太强的通用性和安全特征;当象前面说的那样,当要在多个视图为中返回某个指定类的指针时,我们需要遍历所有视图类,直到找到指定类为止。判断一个类指针指向的是否某个类的实例时,可用IsKindOf()成员函数时行检查,如:

  pView->IsKindOf(RUNTIME_CLASS(CTestView)); 
  即可检查pView所指是否是CTestView类。

  有了以上基础,我们已经可以从文档类取得任何类的指针。为了方便,我们将其作为一个文档类的成员函数,它有一个参数,表示要获得哪个类的指针。实现如下:

CView* CTestDoc::GetView(CRuntimeClass* pClass) 

  CView* pView; 
  POSITION pos=GetFirstViewPosition();

  while(pos!=NULL){ 
     pView=GetNextView(pos); 
    if(!pView->IsKindOf(pClass)) 
    break; 
  }

  if(!pView->IsKindOf(pClass)){ 
    AfxMessageBox("Connt Locate the View./r/n http://www.VCKBASE.com"); 
    return NULL; 
  }

  return pView; 
}

  其中用了两次视图类的成员函数IsKindOf()来判断,是因为退出while循环有三种可能:

  1. pos为NULL,即已经不存在下一个视图类供操作; 
  2. pView已符合要求。

  1和2同是满足。这是因为GetNextView()的功能是将当前视图指针改变成一个视图的位置同时返回当前视图指针,因此pos是pView的下一个视图类的POSITION,完全有可能既是pos==NULL又是pView符合需要。当所需的视图是最后一个视图是最后一个视图类时就如引。因此需采用两次判断。 
  使用该函数应遵循如下格式(以取得CTestView指针为例):

  CTestView* pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView)); 
  RUNTIME_CLASS是一个宏,可以简单地理解它的作用:将类的名字转化为CRuntimeClass为指针。 
  至于强制类型转换也是为了安全特性考虑的,因为从同一个基类之间的指针类型是互相兼容的。这种强制类型转换也许并不必要,但能避免一些可能出现的麻烦。

  3. 从一个视图类取得另一视图类的指针 综合1和2,很容易得出视图类之间互相获得指针的方法:就是用文档类作中转,先用1的方法得到文档类的指针,再用2的方法,以文档类的视图定位函数取得另一个视图类。同样,可以实现成一个函数: 
(假设要从CTestAView中取得指向其它视图类的指针)

CView* CTestAView::GetView(CRuntimeClass* pClass) 

  CTestDoc* pDoc=(CTestDoc*)GetDocument(); 
  CView* pView; 
  POSITION pos=pDoc->GetFirstViewPosition(); 
  while(pos!=NULL){ 
    pView=pDoc->GetNextView(pos); 
    if(!pView->IsKindOf(pClass)) 
      break; 
  } 
  if(!pView->IsKindOf(pClass)){ 
    AfxMessageBox("Connt Locate the View."); 
    return NULL; 
  }

  return pView; 

  这个函数和2中的GetView()相比,一是多了第一句以取得文档类指针,二是在GetFirstViewPosition()和GetNextView()前加上了文档类指针,以表示它们是文档类成员函数。 
  有了此函数;当要从CTestAView中取得CTestBView的指针时,只需如下:

  CTestBView* pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView)); 
 11) 对于单文档中也可以加入多个文档模板,但是一般的开发就使用MDI方式开发多文档模板,其方法与上述视图的获取方法很接近,这里稍做解释,如果不清楚,请查阅MSDN,(以下四个内容(11、12、13、14)来源:http://sanjianxia.myrice.com/vc/vc45.htm

可以用CWinApp::GetFirstDocTemplatePostion获得应用程序注册的第一个文档模板的位置; 
  利用该值来调用CWinApp::GetNextDocTemplate函数,获得第一个CDocTemplate对象指针。

  POSITION GetFirstDocTemplate( ) const; 
  CDocTemplate *GetNextDocTemplate( POSITION & pos ) const;

  第二个函数返回由pos 标识的文档模板。POSITION是MFC定义的一个用于迭代或对象指针检索的值。通过这两个函数,应用程序可以遍历整个文档模板列表。如果被检索的文档模板是模板列表中的最后一个,则pos参数被置为NULL。

接我的:

12) 一个文档模板可以有多个文档,每个文档模板都保留并维护了一个所有对应文档的指针列表。 
  用CDocTemplate::GetFirstDocPosition函数获得与文档模板相关的文档集合中第一个文档的位置,并用POSITION值作为CDocTemplate::GetNextDoc的参数来重复遍历与模板相关的文档列表。函数原形为:

  viaual POSITION GetFirstDocPosition( ) const = 0; 
  visual CDocument *GetNextDoc(POSITION & rPos) const = 0;

  如果列表为空,则rPos被置为NULL.

13) 在文档中可以调用CDocument::GetDocTemplate获得指向该文档模板的指针。函数原形如下:

  CDocTemplate * GetDocTemplate ( ) const; 
  如果该文档不属于文档模板管理,则返回值为NULL。

14) 一个文档可以有多个视。每一个文档都保留并维护一个所有相关视的列表。CDocument::AddView将一个视连接到文档上,将该视加入到文档相联系的视的列表中,并将视的文档指针指向该文档。当有File/New、File/Open、Windows/New或Window/Split的命令而将一个新创建的视的对象连接到文档上时, MFC会自动调用该函数,框架通过文档/视的结构将文档和视联系起来。当然,程序员也可以根据自己的需要调用该函数。

  Virtual POSITION GetFirstViewPosition( ) const; 
  Virtual CView * GetNextView( POSITION &rPosition) cosnt;

  应用程序可以调用CDocument::GetFirstViewPosition返回与调用文档相联系的视的列表中的第一个视的位置,并调用CDocument::GetNextView返回指定位置的视,并将rPositon的值置为列表中下一个视的POSITION值。如果找到的视为列表中的最后一个视,则将rPosition置为NULL.

15) 从一个视图类取得另一视图类的指针 
  这个应用在多视的应用程序中很多见,一般如果自己在主程序或者主框架中做好变量记号,也可以获得,还有比较通用的就是用文档类作中转,以文档类的视图遍历定位,取得另一个视图类。这个功能从本文第10项中可以得到。

16) 获取分割视图中各个视图的指针 
CSplitterWnd m_wndSplitter; 
m_wndSplitter.CreateStatic(this, 1, 2);//分割成一行两列 
m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftPaneView), CSize(10, 10), pContext); 
m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CRightPaneFrame), CSize(0, 0), pContext); 
//获取左边视图的两种方法 
CLeftPaneView* pLeftPaneView     = (CLeftPaneView*)   m_wndSplitter.GetPane(0,0); 
//上一句可以用下句代替: 
//CLeftPaneView* pLeftPaneView  = (CLeftPaneView *)GetActiveView(); 
//获取右边视图 
pLeftPaneView->m_pRightPaneFrame = (CRightPaneFrame*) m_wndSplitter.GetPane(0,1);

http://blog.csdn.net/yuvmen/article/details/5877232

MFC框架各部分指针获取方式的更多相关文章

  1. MFC中 SDI/MDI框架各部分指针获取方式

    VC MFC SDI/MDI框架各部分指针获取方式   整理总结一下,希望能帮助到别人.   获得CWinApp 获得CMainFrame 获得CChildFrame 获得CDocument 获得CV ...

  2. 框架原理第一讲,熟悉常用的设计方式.(以MFC框架讲解)

    框架原理第一讲,熟悉常用的设计方式.(以MFC框架讲解) 一丶什么是框架,以及框架的作用 什么是框架? 框架,简而言之就是把东西封装好了,使用框架开发可以快速开发程序,例如MFC程序的双击写代码. 为 ...

  3. MFC框架

    第一点:类别型录网的搭建: 类别型录网搭建的目的是为了实现所谓的"执行期类型识别",也就是在程序运行的时候识别出某个对象是否是某个类的实例(基类也可以).这里还不是很明白为什么需要 ...

  4. 框架原理第三讲,RTTCreate,运行时类型创建.(以MFC框架讲解)

    框架原理第三讲,RTTCreate,运行时类型创建.(以MFC框架讲解) 通过昨天的讲解,我们已经理解了运行时类型识别是什么. 比如  CObject * pthis = (Cobject *)Cre ...

  5. 介绍MFC框架中涉及到的设计模式(二)

    接着上一篇<介绍MFC框架中涉及到的设计模式(一)>介绍 单例模式(Singleton Pattern) 单例模式是一种经常使用的软件设计模式.在它的核心结构中仅仅包括一个被称为单例类的特 ...

  6. 第3章 MFC框架程序剖析

    参考: https://blog.csdn.net/u014162133/article/details/46573873 1. 2.MFC简介:MFC(Microsoft Foundation Cl ...

  7. C++开发人脸性别识别教程(8)——搭建MFC框架之读取目录信息

    在上一篇博客中我们已经绘制了MFC界面,在这篇博客中我们将加入响应代码,为MFC框架加入一个最主要的功能:打开一个目录. 一.加入相关头文件 这里头文件主要包括三类:opencv头文件.批量读取文件相 ...

  8. C++开发人脸性别识别教程(9)——搭建MFC框架之显示图片

    在之前的博客中我们已经实现读取用户选定的目录.并将其路径保存在对应的变量中.在这篇博文中我们将介绍怎样借助CvvImage类将图片显示在picture控件中,并自己主动读取目录下的其它图片. 一.加入 ...

  9. MFC DLL 导出函数的定义方式

    一直在鼓捣DLL,每天的工作都是调试一个一个的DLL,往DLL里面添加自己的代码,但是对于DLL一直不太了解啊!今天一查资料,才发现自己对于DLL编写的一些基本知识也不了解.要学习,这篇文章先总结DL ...

随机推荐

  1. Java语言Lang包下常用的工具类介绍_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 无论你在开发哪中 Java 应用程序,都免不了要写很多工具类/工具函数.你可知道,有很多现成的工具类可用,并且代码质量都 ...

  2. 详述 DB2 分页查询及 Java 实现的示例_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 博主说:有时候,我们需要对数据库中现有的数据进行大量处理操作(例如表中的某个字段需要全部更新等),如果直接使用selec ...

  3. LeetCode--105--从前序与中序遍历序列构造二叉树(python)

    根据一棵树的前序遍历与中序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,2 ...

  4. 使用HTML和CSS来实现为文字设置图片底纹

    先看一下最终实现的效果 图中的hello是文本而不是图片 那么如何实现这种效果呢? HTML部分: 创建一个h1标签 ,标签内容为(hello).通过link标签链接外部样式表style.css. s ...

  5. React native 平时积累笔记

    常用插件: react-native-check-box 复选框react-native-sortable-listview 列表拖拽排序 react-native-doc-viewer 预览组件 r ...

  6. NPM错误

    有时突然报下面错误: 本人经验是IP变了...

  7. javascript之大文件分段上传、断点续传(一)

    需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包 ...

  8. HDU 6205 card card card ( 思维 )

    题意 : 给定两个序列 a 和 b ,保证 a 数列的和 == b数列的和,从头到尾考虑 (a[i] - b[i]) 的前缀和,直到前缀和为负数则无法进行下去,所得的便是a[1~i]的和,现在有一个操 ...

  9. HDU 2825 Wireless Password ( Trie图 && 状态压缩DP )

    题意 : 输入n.m.k意思就是给你 m 个模式串,问你构建长度为 n 至少包含 k 个模式串的方案有多少种 分析 : ( 以下题解大多都是在和 POJ 2778 && POJ 162 ...

  10. 数位dp浅谈(hdu3555)

    数位dp简介: 数位dp常用于求区间内某些特殊(常关于数字各个数位上的值)数字(比如要求数字含62,49): 常用解法: 数位dp常用记忆化搜索或递推来实现: 由于记忆化搜索比较好写再加上博主比较蒟, ...