文档与视图的联系(三)[1]

[入库:2005年8月19日] [更新:2007年3月25日]

本文简介:选择自 zeroless 的 blog

(三)文档与视图之间的联系

在视图类有一个保护数据成员:cdocument* m_pdocument;,这个文档指针指向视图对象所属的文档,视图里常用的函数getdocument()就是返回的这个指针;在文档类有一个保护数据成员:cdocument* m_viewlist;,它保存的是所有正在显示该文档的视图的指针,通过cdocument的成员函数getfirstviewposition和getnextview函数可以实现对这些视图的访问。

在视图被创建的时候,在oncreate函数里视图和文档发生了关联:

int cview::oncreate(lpcreatestruct lpcs)

{

       if (cwnd::oncreate(lpcs) == -1)

              return -1;

       ccreatecontext* pcontext = (ccreatecontext*)lpcs->lpcreateparams;

 

       if (pcontext != null && pcontext->m_pcurrentdoc != null)

       {

              pcontext->m_pcurrentdoc->addview(this);

              assert(m_pdocument != null);

       }

       else

       {

              trace0("warning: creating a pane with no cdocument.\n");

       }

 

       return 0;  

}

这个关联是通过文档类的addview函数实现的:

void cdocument::addview(cview* pview)

{

    ……

       m_viewlist.addtail(pview);

       pview->m_pdocument = this;

 

       onchangedviewlist();  

}

在这个函数里,首先文档对象先把所添加的视图指针加到自己的视图链表里,然后指向自己的指针赋給了所添加的视图的m_pdocument成员。

众所周知,文档与视图进行通信的方式先调用文档的updateallviews函数,从而调用视图的onupdate函数:

void cdocument::updateallviews(cview* psender, lparam lhint, cobject* phint)

       // walk through all views

{

    //视图链表不能为空且发送者不能为空

       assert(psender == null || !m_viewlist.isempty());

       position pos = getfirstviewposition();

       while (pos != null)

       {

              cview* pview = getnextview(pos);

              assert_valid(pview);

      //不调用发送者的onupdate函数

              if (pview != psender)

                     pview->onupdate(psender, lhint, phint);

       }

}

在视图的onupdate函数里默认的实现仅是通知视图进行重画:

invalidate(true);

我们一般重载这个更新视图的某些数据或进行其他操作,比如更新视图滚动条的滚动范围。

(四)框架窗口与文档、视图之间的联系

在框架窗口被创建的时候,创建了视图,相关的函数如下:

int cframewnd::oncreate(lpcreatestruct lpcs)

{

       ccreatecontext* pcontext = (ccreatecontext*)lpcs->lpcreateparams;

       return oncreatehelper(lpcs, pcontext);

}

int cframewnd::oncreatehelper(lpcreatestruct lpcs, ccreatecontext* pcontext)

{

       if (cwnd::oncreate(lpcs) == -1)

              return -1;

 

       // create special children first

       if (!oncreateclient(lpcs, pcontext))

       {

              trace0("failed to create client pane/view for frame.\n");

              return -1;

       }

 

       // post message for initial message string

       postmessage(wm_setmessagestring, afx_ids_idlemessage);

 

       // make sure the child windows have been properly sized

       recalclayout();

 

       return 0;   // create ok

}

bool cframewnd::oncreateclient(lpcreatestruct, ccreatecontext* pcontext)

{

       // default create client will create a view if asked for it

       if (pcontext != null && pcontext->m_pnewviewclass != null)

       {

              if (createview(pcontext, afx_idw_pane_first) == null)

                     return false;

       }

       return true;

}

cwnd* cframewnd::createview(ccreatecontext* pcontext, uint nid)

{

 

       cwnd* pview = (cwnd*)pcontext->m_pnewviewclass->createobject();

       if (pview == null)

       {

              return null;

       }

       assert_kindof(cwnd, pview);

 

       if (!pview->create(null, null, afx_ws_default_view,

              crect(0,0,0,0), this, nid, pcontext))

       {

              return null;        // can't continue without a view

       }

 

       if (afxdata.bwin4 && (pview->getexstyle() & ws_ex_clientedge))

       {

              modifystyleex(ws_ex_clientedge, 0, swp_framechanged);

       }

       return pview;

}

在文档模板的opendocumentfile函数发生了如下的调用:

initialupdateframe(pframe, pdocument, bmakevisible);

文档模板的这个函数的实现为:

pframe->initialupdateframe(pdoc, bmakevisible);

实际是调用了框架窗口的同名函数:

void cframewnd::initialupdateframe(cdocument* pdoc, bool bmakevisible)

{

       cview* pview = null;

       if (getactiveview() == null)

       {

              //取主视图

              cwnd* pwnd = getdescendantwindow(afx_idw_pane_first, true);

              if (pwnd != null && pwnd->iskindof(runtime_class(cview)))

              {

        //主视图存在且合法,把当前的主视图设置为活动视图

                     pview = (cview*)pwnd;

                     setactiveview(pview, false);

              }

       }

 

       if (bmakevisible)

       {

              sendmessagetodescendants(wm_initialupdate, 0, 0, true, true);

 

              if (pview != null)

                     pview->onactivateframe(wa_inactive, this);

        ……

              activateframe(ncmdshow);

              if (pview != null)

                     pview->onactivateview(true, pview, pview);

       }

 

       // update frame counts and frame title (may already have been visible)

       if (pdoc != null)

本文关键:文档与视图的联系(三)
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top