如何模拟《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,一并来信告知。