在多文档程序中给视图指定标题信息

1 在多文档程序中给视图指定标题信息

       要定制MDI程序中子框架的标题,想来是一个比较简单的事情,按照习惯,SetWindowText就可以设置窗口的标题,然而在实际实现时,却并不是这么回事,首先时调用这个函数的时机,也就是在什么地方调用这个函数,另外就是这个函数真的会起作用么?要弄清楚这个问题,我们首先就要了解MDI程序中子框架的创建过程,在了解了这个创建过程之后,再来考虑解决办法。

1.1     子框架窗口的创建过程

MDI程序中,文档模板类CDocTemplate类的CreateNewFrame成员函数是子框架窗口开始创建的起点(当然,如果说OpenDocumentFile为起点也不为过,因为这个函数也调用CreateNewFrame来创建子框架创建及视图),因此,就从CreateNewFrame函数为起点,来跟踪子框架的创建过程。

于是,我们看到其执行线索是这样的:

多文档程序子框架及其视图创建过程

1:调用CDocTemplate::CreateNewFrame启动子框架的创建流程

       1.1:使用动态创建技术,在内存中分配空间,创建CChildFrame对象【doctempl.cpp260

       1.2:以WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE为缺省风格,调用CMDIChildWnd::LoadFrame从资源创建子框架【doctempl.cpp273

              1.2.1  调用CFrameWnd::GetIconWndClass注册子框架窗体类【winmdi.cpp619

                     1.2.1.1 调用CChildFrame::PreCreateWindowwinfrm.cpp662

                     1.2.1.2 调用AfxRegisterWndClass注册窗体类【winfrm.cpp672

              1.2.2 调用CMDIChildWnd::Create函数创建子框架窗体【winmdi.cpp619行】

                     1.2.2.1 调用CChildFrame::PreCreateWindowwinmdi.cpp528

                     1.2.2.2 构造MDICREATESTRUCT结构【winmdi.cpp537

                     1.2.2.3 MDI的客户窗口发送WM_MDICREATE消息创建子框架来创建边框窗口【winmdi.cpp550

                            其中又发送了WM_NCCREATEWM_CREATE消息给子框架对象,这样就导致对应的CMDIChildWnd::OnNcCreate函数、CChildFrame::OnCreate 函数 被调用

                            1.2.2.3.1 CMDIChildWnd::OnNcCreatewinmdi.cpp1026

                                   1.2.2.3.1.1 调用CFrameWnd::OnNcCreate,汇编代码

                                   1.2.2.3.1.2 调用PreCreateWindow

                                   1.2.2.3.1.3 调用SetWindowLong,设置窗体风格

                            1.2.2.3.2 CChildFrame::OnCreate (如果在CChildFrame中重载)

                                   1.2.2.3.2.1 调用CMDIChildWnd::OnCreate函数

                                          1.2.2.3.2.1.1 调用OnCreateHelperwinmdi.cpp1046

                                                 1.2.2.3.2.1.1.1调用CWnd::OnCreatewinfrm.cpp632】汇编代码

                                                 1.2.2.3.2.1.1.2调用:OnCreateClientwinfrm.cpp636

                                                        1.2.2.3.2.1.1.2.1 调用CreateViewwinfrm.cpp618】创建视图对象

              1.3 至此已经创建了子框架对象,视图对象;CreateNewFrame函数返回;

       2 调用CDocTemplate::InitialUpdateFrame初始化边框,该函数在【doctempl.cpp323

        2.1调用CFrameWnd::InitialUpdateFramewinfrm.cpp732

            2.1.1将第一个视设置为活动视【winfrm.cpp742

            2.1.2给所有相关视图及控件发送WM_INITIALUPDATE消息【winfrm.cpp749】,这样导致视图的OnInitialUpdate函数被调用

                2.1.2.1 CXXXView::OnInitialUpdate:(该函数可以被重载的)

                    2.1.2.1.1调用CView::OnUpdate函数

                        2.1.2.1.1.1调用CView::Invalidate(汇编代码)

            2.1.3调用视图对象的OnActivateFrame以提供保存焦点的机会【winfrm.cpp753

            2.1.4调用CMDIChildWnd::ActivateFrame激活边框【winfrm.cpp764

            2.1.5调用CMDIChildWnd::OnUpdateFrameTitlewinfrm.cpp764

                2.1.5.1调用:CMDIFrameWnd::OnUpdateFrameTitle设置父窗体的标题

                    2.1.5.1.1如果具有FWS_ADDTOTITLE风格,则设置标题

                2.1.5.2如果具有FWS_ADDTOTITLE风格,则设置子框架的标题【winmdi.cpp922  

              2.2 CDocTemplate::InitialUpdateFrame执行完毕

1.2 修改标题的方法

       方法1:去掉     FWS_ADDTOTITLE的窗体风格

从上述的“子框架窗口的创建过程”可以发现,和子框架的标题设置有关的是CDocTemplate::InitialUpdateFrame部分,在该函数执行的最后一步,会调用OnUpdateFrameTitle函数来设置子框架的标题信息。由于这个函数是窗体显示前的最后一步,因此,要是我们只是简单的直接在视图类中处理WM_INITIALUPDATE消息,即OnInitialUpdate中来调用SetWindowsText来设置子框架的标题的话,所设置的信息又会被OnUpdateFrameTitle所设置的标题覆盖。

不过,从OnUpdateFrameTitle的实现代码可以发现,在该函数中,进行了是否设置了FWS_ADDTOTITLE风格的判断,如果具有该风格,就给窗口设置一个默认的标题信息。在默认的情况下,CDocTemplateCreateNewFrame函数以WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE为缺省风格来调用LoadFrame函数创建子框架,这样窗口的风格中就包含了FWS_ADDTOTITLE。不过,从上面的创建过程,也可以发现,在真正开始创建子框架之前,MFC会调用PreCreateWindow这个可被重载的函数,这样就给我们提供了一个机会来修改子框架的创建风格,于是,我们就找到了一个修改标题的方法,这个方法其实很简单,实施步骤如下:       

第一步:重载CMDIChildFramePreCreateWindow函数,去掉FWS_ADDTOTITLE

       cs.style &= ~FWS_ADDTOTITLE;

       第二步:处理视图的WM_INITIALUPDATE消息,在其中调用SetWindowText来把标题设置成想要的内容

 

  方法2:重载OnUpdateFrameTitle函数

       该函数是CMDIFrameWnd类的一个虚函数,在以前版本的MFC中,这个函数没有暴露出来,不过到了4.2之后,这个函数就已经可以方便的通过ClassWizard来进行重载了,因此,修改标题的最简单的方法就是重载此函数,在此函数中设置标题的内容。

       不过,在重载此方法的时候,可以不调用基类的方法,如果要调用,则自己设置标题信息的代码一定要放置在基类方法的调用之后,自己设置的标题才不会被基类方法设置点标题覆盖。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值