文档类、子框架类及视图类的关系及如何相互调用

一、概念。

   1、了解文档和视图的相互作用关系是编写mfc程序的基本功。但是mfc的应用程序框架把文档和视图之间的关系封装了起来,初学的朋友往往不得要领,因此写程序往往被局限于在用向导生成的框架中。本文希望能够尽可能说明白文档视图框架之间是如何进行作用,希望能给一些朋友带来小小的帮助。
   2、基本概念: 
    文档对象:是用来保存数据的。
    视图对象:是用来显示和编辑数据的。
    应用程序框架:框架是用来管理不同文档显示界面的。例如你有一个数据网格显示界面,还有一个图形显示界面,它们的数据可能都来自你的文档,但是视图不同,怎么办?可以用框架。便可以把界面管理独立出来。
    文档模板:mfc把文档/视图/框架视为一体,只要你创建文档/视图框架结构的程序,必定会为你创建这三个类。这个工作在在应用程序初始化时完成,如下:
    
  bool cmyhtmlapp::initinstance()
  {
  //。。。。。。
  csingledoctemplate* pdoctemplate;
  pdoctemplate = new csingledoctemplate(
  idr_mainframe,
  runtime_class(cmyhtmldoc),
  runtime_class(cmainframe), // main sdi frame window
  runtime_class(cmyhtmlview));
  adddoctemplate(pdoctemplate);
  //。。。。。。
  }
    
  单文档:就是一次只能打开一个文件,和你的文档类型支持的多少无关。你完全可以做一个单文档的支持所有图象格式的程序,只不过它一次只能打开一个文档罢了。
  多文档:就是你可以打开多个文件,和文档类型也无关。你也可以作一个可以同时打开多个文档的程序,但它只支持一种文档类型。 
    
二、何时需要文档/视图框架结构?
  首先你可以不使用文档视图这种框架结构,即便是在mfc中。你可以在你需要的时候选择使用这种方式。你可以完成一个只有视图没有文档的程序,例如一个基于对话框的应用。那什么时候需要呢? 当你想将你的数据层和界面层分开的时候。
  通常我们对数据的操作放在文档类中,例如存取,打开,关闭。在这里你可以尽情的对你的数据进行操作,假如你需要,在对数据进行了改变后,对视图做一下更新,那么程序会将你对数据所做的改变呈现给你的程序的用户。由此可见视图的作用就是提供一个用户和数据之间进行数据交换的界面,它的作用就是在需要的时候显示数据,并在需要的时候提供输入界面。当用户输入后实际的数据操作工作是由文档类来做的。那框架类有在做什么呢?
  框架类是为了便于管理你的文档类和视图类而存在的。通常我们的操作都是通过视图窗口完成,消息由视图进行接收并且进行处理。所以消息映射定义一般在视图中。但假如一个应用同时拥有多个视图而当前活动视图没有对消息进行处理则消息会发往框架窗口。另外框架窗口可以方便的处理非窗口消息。 
    
三、典型的单文档程序的生成过程(不完整,只挑有用的)
  1、 cwinapp对象被建立,这个对象是全局的且只能有一个,名字叫theapp。这时你可以完成一些工作,例如对注册表的操作,(假如你想写一个不修改注册表的软件,需要在这里做写工作)
  2、 在initinstance()函数中创建文档模板,文档模板以cruntimclass静态成员指针做构造参数。
  3、 执行mfc框架默认的命令行参数。命令行参数有很多其中之一是,cmd1它会创建一个新文件。(假如没有命令行参数则执行默认的id_file_new)
  4、 文档模板的实例根据三个类的动态创建信息创建出文档、视图、框架。
  5、 对文档、视图、框架进行初始化。 
    
四、文档,视图,框架之间的相互作用。
  由上面的典型的单文档程序的生成过程可以看出一个完整的应用一般由四个类组成:cwinapp应用类,cframewnd框架类,cdocument文档类,cview视图类。我将四个类常用的成员函数列出,大家一看便知。不过参数,返回值均未列出,大家可以从msdn上了解更多。几个重要的虚函数也未做说明。大家自己看吧。
    
  通过全局函数afxgetapp可以得到cwinapp应用类的全局对象theapp.
  cwinapp
  数据成员:
  m_pszappname 应用程序名称
  m_pszexename 可执行文件的名称
  m_pszprofilename ini文件的名
  m_pszregistrykey 注册表或ini文件的key
  m_hinstance 实例的句柄
  m_pmainwnd 为框架窗口指针
  成员函数:
  initinstance() //初始化
  parsecommandline() //完成命令行的解析处理
    
  cframewnd
  getactivedocument() //得到当前活动文档指针
  getactiveview() //得到当前活动视图指针
  setactiveview() //设置当前视图为活动视图
    
  cdocument
  onnewdocument()
  onopendocument()
  onsavedocument()
  onfileclose()
  //以上是用来对文档的操作
  getfirstviewposition() //文档对象链表中的第一个文档位置
  getnextview() //下一个
  //以上是用来遍历所有和文档关联的视图
  getdoctemplate()得到文档模板指针
  addview() //增加一个视图
  removeview() //删除一个视图
  updateallview() //更新所有视图
    
  cview
  getdocument()得到对应的文档指针 
    
五、几个常见到的问题。
  1,为什么在对话框的应用程序中没有发现文档模板?
  默认的对话框程序没有使用文档/视图框架结构。
    
  2 ,假如我使用数据库作为数据源是否意味着可以不需要文档类?
  看你自己,但是我建议使用。因为可以文档,视图这一个清楚方便的框架结构,以及方便完成三者之间的相互作用。

六、框架、文档、视图类之间的调用关系
 
1、主框架(cframewnd)中访问视图(cview)
  cview* getactiveview() const;
  通常定义的视图为cview的派生类,在调用自定义视图对象的方法时
 
应该这样写:((cmousekeyview*)getactiveview())->myfunc();
 
2、主框架(cframewnd)中访问文档(cdocument)
  getactivedocument,返回cdocument对象;
 
3、在视图(cview)中访问文档(cdocument)
  inline cmousekeydoc* cmousekeyview::getdocument()
    {return (cmousekeydoc*)m_pdocument;}
 
4、在视图(cview)中访问框架(cframewnd)
  cframewnd* getparentframe() const;
 
5、在文档(cdocument)中访问框架(cframewnd)
  cwnd* afxgetmainwnd();
  cwnd* afxgetapp()->m_pmainwnd;
 
6、在文档(cdocument)中访问视图(cview)
  updateallviews
  功能:通知所有的视图文档已被修改的信息
  原型:
    void updateallviews(
      cview* psender, // 要更新的视图指针,假如希望更新所有视
 
图,将此参数设为null
      lparam lhint=0l, // 包含更改消息的通知
      cobject* phint=null // 保管更改消息的对象
    }
 
7、在其他类中访问文档类(cdocument)
  cdocument* getdocument()
  {
    cframewnd* frm=(cframewnd*)::afxgetmainwnd();
    assert(frm);
    cdocument* pdoc=frm->getactivedocument();
    assert(pdoc);
    assert(pdoc->iskindof(runtime_class(cmousekeydoc)));
    return (cmousekeydoc*)pdoc;
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值