这一部分讨论了如何创建一个视图,该视图的Close按钮和相关的系统菜单命令都处于失效状态。
第一种技术:
第1步:使用ClassWizard来创建一个新的CMDIChildWnd派生类CNoCloseFrame,该类将实现“不要关闭”的行为。
第2步:使用ClassWizard重载在第1步中创建的类中的LoadFrame()函数,该函数的实现清单如下所示,它使“Close”系统菜单命令失效。
第3步:不要忘记在适当的文档模板中引用视图的框架类,以此得到想要的结果。
如果在某些时候,打算关闭那些视图框架窗口的特定窗口,那该怎么办呢?只要简单的调用PostMessage()给窗口发送1条WM_CLOSE消息就行了,如下程序清单:
void CNoCloseFrame::OnCloseFrame()
{
PostMessage( WM_CLOSE );
}
接着标准的MFC消息处理过程将负责关闭视图的框架窗口并释放相关的文档对象(如果该文档没有其他视图存在)。
第2中技术:在视图类中处理该行为
在视图类中使用Classwizard重载OnInitialUpdate()虚函数。该函数的实现如下面的程序清单所示,它使父框架窗口的“Close”系统菜单命令失效。
如同在第一种技术中解释的那样,可以调用PostMessage给视图的父框架窗口发送一条WM_CLOSE消息来关闭这些视图中某个特定是视图。
解释:
在什么时候调用LoadFrame()函数呢?该函数实际上执行了什么操作呢?要回答这些问题,我们需要深入到MFC内部,该过程使用 文档模板对象 创建视图窗口。该过程采用 4步构造处理 来创建框架窗口的C++对象 和 与其 关联的Windows窗口。
1、MFC调用 文档模板对象 的CreateNewFrame()函数
2、CreateNewFrame()通过调用 动态创建函数 CreateObject()来创建 合适的框架窗口 C++对象
3、接着CreateNewFrame()函数调用 框架窗口的LoadFrame()函数
4、LoadFrame()函数创建Windows窗口 并 链接相关的资源(资源模板ID)
CMDIChildWnd::LoadFrame()函数,它是与我们的讨论关系最为紧密的函数。然而,MFC还为CFrameWnd和CMDIFrameWnd类定义了不同的LoadFrame()实现。
当使用标准的“File->New”菜单命令创建一个新的文档对象时,调用LoadFrame函数的调用链如下:
CWinApp()::OnFileNew()=>CDocManager::OnFileNew()=>CMultiDocTemplate::OpenDocumentFile()=>CDocTemplate::CreateNewFrame()=>CNoCloseFrame::LoadFrame();
如果使用标准的“Windows->New Window”菜单命令为一个已有的文档创建新视图,那么函数调用链如下:
CMDIFrameWnd::OnWindowNew()=>CDocTemplate::CreateNewFrame()=>CNoCloseFrame::LoadFrame();
附加注释:
注意:前面的技术并不完全能够阻止用户的行为:如果用户按下ctrl+F4组合键或者退出应用程序时,仍然可以关闭视图。如果打算不惜一切代价阻止这种行为,或者保留“close”按钮有效,那么应该考虑使用下面两种技术中的一种:
1)在视图的框架窗口类中处理WM_CLOSE消息,并决定是否允许窗口关闭,如下面的程序清单:
2)在文档类中使用ClassWizard重载CDocument::CanCloseFrame()函数,程序清单如下所示:
如果决定使用后面这种技术,则应该意识到,是在文档 试图关闭 框架 之前调用的CDocument::CanCloseFrame();函数,而不是在通常的文档关闭过程之后(如果框架碰巧包含了所打开的特定文档的最后一个视图)。因此,当试图关闭文档的最后一个子窗口时,在调用CDocument::CanCloseFrame();函数前将提示用户保存文档。有时候,这可能导致奇怪的行为。