打开文件的步骤如下:

弹出打开文件对话框 -> 获取选择的文件,并将文件显示在视图中。

我们程序中经常需要定制的操作如下:

1. 定制弹出的文件对话框,例如需要修改打开文件的类型或扩展名

2. 定制文件显示的行为

3. 定制文件打开后的行为

1. CWinApp::OnFileOpen

它是ID_FILE_OPEN消息的处理函数,在内部调用CDocManager::OnFileOpen。

下面是CWinApp::OnFileOpen的源码:

1 void CWinApp::OnFileOpen()
2 {
3     ENSURE(m_pDocManager != NULL);
4     m_pDocManager->OnFileOpen();  //CDocManager m_pDocManager; 
5 }

CDocManager::OnFileOpen的主要作用是弹出文件选择对话框,它的源码如下:


 1 void CDocManager::OnFileOpen()
 2 {
 3     // prompt the user (with all document templates)
 4     CString newName;
 5     if (!DoPromptFileName(newName, AFX_IDS_OPENFILE,
 6       OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, NULL))
 7     return; // open cancelled
 8 
 9     AfxGetApp()->OpenDocumentFile(newName);
10     // if returns NULL, the user has already been alerted
11 }

CDocManager::DoPromptFileName的作用就是弹出文件选择对话框。

写到这里我们已经可以解决第一个问题了---定制文件打开对话框。我们可以选择两种方式:

第一种:重写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。

3. CWinApp::OnFileOpen

具体将初始化的代码放在哪里,没有一个统一的标准,对于本人来说,在哪里初始化方便,便把初始化代码放在哪里。

C++ MFC打开文件的流程的更多相关文章

  1. MFC 打开文件对话框 打开单个文件

    CFileDialog的语法: CFileDialog(BOOL bOpenFileDialog,LPCTSTR lpszDefExt=NULL,LPCTSTR lpszFileName=NULL,D ...

  2. MFC打开文件对话框

    { CString FilePathName; CFileDialog dlg(TRUE);///TRUE为OPEN对话框,FALSE为SAVE AS对话框 if(dlg.DoModal()==IDO ...

  3. MFC 打开文件夹 调用其他程序 打开文件

    ShellExecute(NULL,TEXT("OPEN"),要打开的文件的路径,NULL,NULL,SW_SHOWNORMAL); ShellExecute(NULL, &quo ...

  4. MFC打开文件选择框和多选框,保存文件夹的选择,保存文件路径的选择

    CString defaultDir = "C:\\"; //默认打开的文件路径 CString fileName = ""; //默认打开的文件名 CStri ...

  5. MFC 打开文件夹选择框并获取文件夹路径

    CString FicowGetDirectory() { BROWSEINFO bi; char name[MAX_PATH]; ZeroMemory(&bi, sizeof(BROWSEI ...

  6. 第一个c程序和vs2017 在打开MFC rc文件时找不到rcdll.dl

    第一个c程序 #include<stdio.h> int main() { ; ; printf_s("请输入两个数字:"); scanf_s("%d,%d& ...

  7. MFC程序打开文件对话框出错的问题解决

    前几天从网上下了个图像分析的mfc小程序,是VC6的 用VC6在本地编译生成都没问题.执行起来弹出一个未处理的错误,程序崩溃退出. 想起来原来遇到过打开文件对话框方面的问题,当时项目时间紧张未能深究. ...

  8. MFC打开/保存文件对话框:CFileDialog

    MFC打开/保存文件对话框:CFileDialog CFileDialog   文件选择对话框的使用:首先构造一个对象并提供相应的参数,构造函数原型如下: CFileDialog::CFileDial ...

  9. MFC 打开外部EXE文件的三种方法

    目前知道三种方式:WinExec,ShellExecute ,CreateProcess,别人已经总结的很好了<vc中调用其他应用程序的方法(函数) winexec,shellexecute , ...

随机推荐

  1. STM8 EEPROM:

    stm8的EEPROM的搽除是写0,FLASH_PRO与FLASH_DATA写的秘钥顺序相反 EEPROM读写前要解锁的.这个很简单,在技术文档里讲得很清楚.我用一个宏定义来代表EEPROM单元.#d ...

  2. sql 中 left join 的使用

    left join .是以左表为基础,查询右表的值.如果在右表中没用没有数据,则为NULL. 这里有三张表. 线路bs_line:id,name(id主键) 线路段bs_seg:id,l_id,nam ...

  3. CRM Setstate plugin

    pre 事件 throw new InvalidPluginExecutionException("pre-StateCode:" + StateCode + ",pre ...

  4. 关于URLEnCode,URLDeCode,Base64,公钥私钥

    1.Base64非常适合http.mime协议,所以在一些类似webservice中可以用Base64. 用法如下:传出去之前先 Convert.ToBase64String(encryptedByt ...

  5. [Linux编程]__read_mostly变量含义

    1.定义 __read_mostly原语将定义的变量为存放在.data.read_mostly段中,原型在include/asm/cache.h 中定义: #define __read_mostly ...

  6. [转]CAP原理与最终一致性 强一致性 透析

    在足球比赛里,一个球员在一场比赛中进三个球,称之为帽子戏法(Hat-trick).在分布式数据系统中,也有一个帽子原理(CAP Theorem),不过此帽子非彼帽子.CAP原理中,有三个要素: 一致性 ...

  7. prototype.js简介

    prototype.js简介 2007-11-21 14:22 prototype.js是一个很强大的Javascript函数库,它可以让你很轻松的使用一些特效,实现AJAX的功能.虽然prototy ...

  8. SQL存储过程解密

    首先要建立一张表和一个存储过程: SQL_DECODE表: CREATE TABLE [dbo].[SQL_DECODE]( ,) NOT NULL, [SQLTEXT] [nvarchar](max ...

  9. backtrack下vim的使用

    root@bt:~# vim test.c //vim新建或者编辑test.c,执行后进入vim编辑器,按a键进入编辑状态,输入C代码 #include<stdio.h> void mai ...

  10. 谈谈Java面向对象的三大特性

    Java面向对象的三大特性就是指封装.继承.多态了. 一.封装: 概念:封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式. (举例:笔记本电脑就是一个封装体,Java语言中最小的封装体就是函数 ...