ID_FILE_NEW消息和ID_FILE_OPEN消息

来源:互联网 发布:09年 linux 服务器份额 编辑:程序博客网 时间:2024/05/18 02:37

转自http://kb.cnblogs.com/a/2357724/和http://blog.csdn.net/godknows007/article/details/6192925  有详细代码        

          MFC默认会发送ID_FILE_NEW消息,调用CWinAppEx::OnFileNew(),在这个函数里会有m_pDocManager-> OnFileNew(); m_pDocManager是CWinApp对象的一个指向CDocManager对象的指针变量,CMutiDocManager类负责Document的创建和管理。不论ID_FILE_NEW消息和ID_FILE_OPEN消息,CMutiDocManager类都会建立文档对象。如果是ID_FILE_OPEN消息,系统默认会有ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen) 也就是说会有m_pDocManager-> OnFileOpen();


          看一下m_pDocManager-> OnFileNew();这个函数里面主要做什么。里面主要有CMultiDocTemplate::OpenDocumentFile,而这个函数主要是创建ducument、View、FrameWnd对象, 主要有CDocument* pDocument = CreateNewDocument();CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);SetDefaultTitle(pDocument);pDocument->OnNewDocument();pDocument->OnOpenDocument(lpszPathName) CDocTemplate::CreateNewDocument()主要有CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();AddDocument(pDocument);

          看一下m_pDocManager-> OnFileOpen();这个函数里面主要做什么。里面主要有两个函数,其一CDocManager::DoPromptFileName的作用就是弹出文件选择对话框,还有就是AfxGetApp()->OpenDocumentFile(newName);如果要改写有两种办法

        

第一种:重写CWinApp::OnFileOpen

 示例如下:

 

1 CYourApp::OnFileOpen()
2 {
3     CString newName;
4     // 1. 在这里弹出自己的打开文件对话框
5     // 2. 直接调用OpenDocumentFile(newName)
6     OpenDocumentFile(newName);
7 }

 

 这种方式的缺点是,如果要定制保存文件对话框,还得重写其他的某个函数,如CDocument::DoSave。

第二种: 重写CDocManager::DoPromptFileName

这种方式会同时改变打开文件对话框和保存文件对话框,因为打开和保存时的对话框都是通过此函数弹出的。 

这种方式需要两步:

1. 自定义一个CDocManager的子类,例如,CYourDocManager,在其中重写DoPromptFileName方法

2.  在CYourApp::InitInstance函数中找到AddDocTemplate,并在它的前面加上这样一行:m_pDocManager  = new CYourDocManager;

     因为在AddDocTemplate中先判断m_pDocManager是否为Null,若为Null则创建一个。我们在它前边将m_pDocManager实例化,

     这样之后就会调用我们定制的DoPromptFileName函数了。

 

 2. CWinApp::OpenDocumentFile 

 在获取要打开文件的路径后框架调用了这个函数,并在这个函数中完成了读取文件数据并显示的操作。

通过跟踪MFC的源码,我们会发现真正打开文件是在CDocument::OnOpenDocument中进行的,

CDocument::OnOpenDocument的默认行为是先调用DeleteContents成员函数来确保文档空白,然后调用Serialize函数读取文件数据。

因此如果你的程序有打开文件的需求,则必须在你的文档类中重写Serialize函数。 


上文中,我们已经解决了前两个定制的需求,现在来解决第三个,如果我们在打开文档后需要进行某些操作,如初始化, 我们可以对三个函数进行重写:

1. CDocument::OnOpenDocument

    在Document中我们可以获取它关联的View,如果打开文档后需要对View进行某些初始化或者其他的一些初始化,则可以重写这个函数,示例如下:

1 BOOL CMyDoc::OnOpenDocument(LPCTSTR lpszPathName)

2 {
3    if (!CDocument::OnOpenDocument(lpszPathName))
4       return FALSE;
5    // 进行初始化 

6    return TRUE;
7 }

也可以对下面两个函数进行重写以进行某些初始化 

2. CWinApp::OpenDocumentFile

默认行为:CDocManager::OpenDocumentFile -->CDocument::OnOpenDocument

也就是说它最终还要调用CDocument::OnOpenDocument。 其中,CDocManager::OpenDocumentFile真正创建了Document。


 

         注意:不要在CMyApp中添加这两个消息的事件处理,因为系统已经为你做了,你添加了也不会被调用。而且在其他类上添加他们的事件处理函数也只有在新建了文档对象后才有效,也就是如果你把系统默认的新建文档去掉后,第一个打开消息只会是CMyApp或者CWinAppEx的OnFileNew()。如果要改写就只需要把ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew 改为ON_COMMAND(ID_FILE_NEW, &CMyApp::OnFileNew 然后中重写OnFileNew()。如果要开始不打开一个文档可以C****App::InitInstance()函数中加入cmdInfo.m_nShellCommand=CCommandLineInfo::FileNothing;