如何模拟《WORD》的窗口形式

[入库:2005年8月18日] [更新:2007年3月27日]

本文简介:选择自 lanzhengpeng2 的 blog

如何模拟《word》的窗口形式

重点:在cchildframe上做文章。

1、利用向导生成一个多文档应用程序 testmdi,则生成下列类:

caboutdlg,cchildframe,cmainframe,ctestmdiapp,ctestmdidoc,ctestmdiview
2、改造ctestmdiapp::initinstance():pmainframe->showwindow(sw_hide);
3、改造cchildframe:首先用cframewnd替换它的基类,再将cmainframe里跟创建工具栏状态栏相关代码移到cchildframe里面。为了突出重点,

我只列出更改过的代码。如下:
//childfrm.h
class cchildframe : public cframewnd
{
protected:  // control bar embedded members
 cstatusbar  m_wndstatusbar;
 ctoolbar    m_wndtoolbar;
 afx_msg int oncreate(lpcreatestruct lpcreatestruct);
 //{{afx_msg(cchildframe)
 afx_msg void onclose();
 //}}afx_msg
};

//childfrm.cpp
implement_dyncreate(cchildframe, cframewnd)

begin_message_map(cchildframe, cframewnd)
 //{{afx_msg_map(cchildframe)
 on_wm_create()
 on_wm_close()
 //}}afx_msg_map
end_message_map()

static uint indicators[] =
{
 id_separator,           // status line indicator
 id_indicator_caps,
 id_indicator_num,
 id_indicator_scrl,
};

bool cchildframe::precreatewindow(createstruct& cs)
{
 if( !cframewnd::precreatewindow(cs) )
  return false;

 return true;
}
/////////////////////////////////////////////////////////////////////////////
// cchildframe message handlers
int cchildframe::oncreate(lpcreatestruct lpcreatestruct)
{
 if (cframewnd::oncreate(lpcreatestruct) == -1)
  return -1;
 
 if (!m_wndtoolbar.createex(this, tbstyle_flat, ws_child | ws_visible | cbrs_top
  | cbrs_gripper | cbrs_tooltips | cbrs_flyby | cbrs_size_dynamic) ||
  !m_wndtoolbar.loadtoolbar(idr_mainframe))
 {
  trace0("failed to create toolbar\n");
  return -1;      // fail to create
 }

 if (!m_wndstatusbar.create(this) ||
  !m_wndstatusbar.setindicators(indicators,
    sizeof(indicators)/sizeof(uint)))
 {
  trace0("failed to create status bar\n");
  return -1;      // fail to create
 }

 // todo: delete these three lines if you don&t want the toolbar to
 //  be dockable
 m_wndtoolbar.enabledocking(cbrs_align_any);
 enabledocking(cbrs_align_any);
 dockcontrolbar(&m_wndtoolbar);

 return 0;
}

void cchildframe::onclose()
{
 cframewnd::onclose();
// afxgetmainwnd()->postmessage(wm_command,id_close_child,0);
}

好了,现在应该可以编译通过了。怎样,不错吧?
可是,你很快就发现,怎么我的程序没有关闭?是啊,主窗口被藏起来了,还没有被关闭。原来,在所有窗口都关闭的情况下,主窗口也应该

被关闭。于是,我选择了个时机cchildframe::onclose(),向主窗口发送一个消息,让主窗口自己检测是否还存在有cchildframe窗口:

void cchildframe::onclose()
{
 cframewnd::onclose();
 afxgetmainwnd()->postmessage(wm_command,id_close_child,0); //id_close_child是自定义消息
}
相应,cmainframe有函数对应处理这个消息:
bool cmainframe::oncommand(wparam wparam, lparam lparam)
{
 if(wparam == id_close_child)
 {
  checkchildwnd();
  return true;
 }
 
 return cmdiframewnd::oncommand(wparam, lparam);
}

void cmainframe::checkchildwnd()
{
 cwinapp * papp = afxgetapp();
 position ps = papp->getfirstdoctemplateposition();
 assert(ps != null);
 cdoctemplate * pdoctemplate = papp->getnextdoctemplate(ps);
 ps = pdoctemplate->getfirstdocposition();
 if(ps == null)
  postmessage(wm_close);
}

基本问题解决。

这样做有什么好处?
由于多个视图公用一个工具栏和状态栏,导致在视图切换的时候要去更新状态栏和工具栏,特别是不同的视图有不同的状态栏的时候,非常痛

苦。做成这样的单文档界面的方式,就省下了这一步。
当然,也应该有它的不足之处,希望各位来信告知,同时希望各位能把它涉及到的问题或bug,一并来信告知。

兰征鹏
zlan@corp.netease.com

 

本文关键:,多文档,单文档,WORD,窗口形式,
  相关方案
Google
 

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

go top