MFC中的MainFrame Dlg,App,Doc,View的关系

MFC框架中指针获取与操作详解
本文详细介绍了MFC框架中如何在不同组件(视图、文档、对话框)之间获取指针,包括如何在视图中获得文档指针、在应用中获得主框架指针等常见操作,并提供了相关函数的使用方法和注意事项。

转自http://www.cnblogs.com/areliang/archive/2011/11/17/2252901.html


MainFrame: 主框架类

Dlg 是Dialog 的缩写,表示对话框本身

 
App类就是这个SDI作为"程序"的入口,有点像c的Main函数,它不是从CWND中派生出来的。App表示应用程序本身。

 
View表示视图类,负责显示数据,提供编辑数据、修改数据的功能。它是指编辑区里面的事就是那块白色的中间区域,负责绘制和响应一些消息

 
Doc表示文档类,提供对数据的保存和加载。有点像数据库,保存着编辑数据,用于view的Redraw的时候用,还有保存文件。

 一般动态的编辑数据都放在Doc里面。他也不是从CWND中派生出来的,没有继承MessageBox函数,可以用AfxMessageBox函数。

 

 

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)   从一个视图类取得另一视图类的指针    

     

  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类。    

     

  有了以上基础,我们已经可以从文档类取得任何类的指针。为了方便,我们将其作    

  为一个文档类的成员函数,它有一个参数,表示要获得哪个类的指针。实现如下:      

      

  其中用了两次视图类的成员函数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中取得指向其它视图类的指针)    

   这个函数和2中的GetView()相比,一是多了第一句以取得文档类指针,二是在    

  GetFirstViewPosition()和GetNextView()前加上了文档类指针,以表示它们是文档    

  类成员函数。有了此函数;当要从CTestAView中取得CTestBView的指针时,只需如    

  下:CTestBView*   pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView)); 

### CWinApp 与 CDialog 的区别 #### 基本职责与功能 `CWinApp` 是 MFC 中用于表示应用程序对象的类,其继承自 `CWinThread`,负责管理整个应用程序的生命周期。它封装了 Windows SDK 中的 WinMain 函数逻辑,处理消息循环、初始化应用程序、加载资源等关键任务。每个基于 MFC 的 GUI 应用程序都必须包含一个从 `CWinApp` 派生的类实例,作为程序入口点的替代[^2]。 `CDialog` 则是用于实现对话框界面的类,继承自 `CWnd`,主要用于构建管理模态或非模态对话框。它封装了 Windows 对话框资源的创建、消息映射、控件交互等功能,适用于用户需要通过简单的弹出窗口进行输入或选择的场景[^4]。 #### 消息处理机制 由于 `CWinApp` 继承自 `CWinThread`,其可以处理命令消息(如菜单项、工具栏按钮),但不能直接响应普通 Windows 消息(如 WM_PAINT、WM_MOUSEMOVE)。命令消息可以通过多个类(如 `CDocument`、`CView`、`CFrameWnd`)进行路由处理,而 `CWinApp` 通常用于全局级别的命令处理[^1]。 相比之下,`CDialog` 继承自 `CWnd`,具备完整的窗口句柄消息映射能力,因此能够处理标准的 Windows 消息以及用户定义的消息。这使得 `CDialog` 更适合用于交互性强的界面元素,例如设置对话框、登录窗口等。 #### 创建与运行方式 `CWinApp` 类的对象通常在源文件中通过宏 `theApp` 全局实例化,并由 MFC 框架自动调用其 `InitInstance()` `Run()` 方法启动应用程序。该过程包括创建主框架窗口、加载文档模板、进入消息循环等步骤[^2]。 `CDialog` 对象则通常在用户代码中动态创建,并通过调用 `DoModal()` 或 `Create()` 方法显示为模态或非模态对话框。模态对话框会阻塞主程序的执行,直到用户关闭对话框;而非模态对话框则允许用户在对话框与其他窗口之间切换[^4]。 #### 资源依赖与结构 `CWinApp` 并不直接关联特定的 UI 资源,而是通过 `CFrameWnd`、`CView` 等类间接加载菜单、图标、加速键表等资源。它更偏向于全局配置初始化角色[^2]。 `CDialog` 则必须绑定到一个对话框资源模板(.rc 文件中的 DIALOG 资源),并使用 `BEGIN_MESSAGE_MAP` 宏将控件 ID 映射到相应的事件处理函数。这种设计使其在 UI 编程中更加直观高效[^4]。 #### 示例:基本结构对比 ```cpp // CWinApp 派生类示例 class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; BOOL CMyApp::InitInstance() { CFrameWnd* pFrame = new CMainFrame; pFrame->LoadFrame(IDR_MAINFRAME); m_pMainWnd = pFrame; pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); return TRUE; } ``` ```cpp // CDialog 派生类示例 class CLoginDlg : public CDialog { public: CLoginDlg() : CDialog(IDD_LOGIN_DIALOG) {} protected: afx_msg void OnBnClickedOk(); DECLARE_MESSAGE_MAP() }; void CLoginDlg::OnBnClickedOk() { // 处理 OK 按钮点击事件 } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值