打开文件的步骤如下:

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

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

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. PHPCMS v9 超级安全防范教程!

    一.目录权限设置很重要:可以有效防范黑客上传木马文件.如果通过 chmod 644 * -R 的话,php文件就没有权限访问了.如果通过chmod 755 * -R 的话,php文件的权限就高了. 所 ...

  2. NSOperationQueue与GCD的使用原则和场景

    首先,我们要明确NSOperationQueue与GCD之间的关系: NSOpertaionQueue用GCD构建封装的,是GCD的高级抽象. 其次,我们要区别两者的不同: GCD仅仅支持FIFO队列 ...

  3. Netty服务端与客户端(源码一)

    首先,整理NIO进行服务端开发的步骤: (1)创建ServerSocketChannel,配置它为非阻塞模式. (2)绑定监听,配置TCP参数,backlog的大小. (3)创建一个独立的I/O线程, ...

  4. CORBA IOR学习

    Interoperable Object References: IOR IOR用于表示一个对象引用,我们知道,当我们在客户端一个CORBA对象的时候,接触的并不是真正的对象,而是这个对象的代理(Pr ...

  5. 【转】ORACLE定期清理INACTIVE会话

    源地址:http://www.cnblogs.com/kerrycode/p/3636992.html ORACLE数据库会话有ACTIVE.INACTIVE.KILLED. CACHED.SNIPE ...

  6. SQL: ROW_NUMBER

  7. 实体写到redis写不进去--误把类当成实体类

    之前一直都把实体写入redis都没有问题,今天再次这样干,结果却是怎么写都写不进去,redis里的值老是为空 最后才发现把类当成了实体类,当然写不进去了. 把类: /// <summary> ...

  8. ThinkPHP 关于namespace的事儿

    如题,php通常是不允许函数重名的,例如a.php中有一个getName(),b.php中有一个getName(),在require_once a.php和b.php后就会报getName重复定义的错 ...

  9. Python-Numpy函数-tile函数

    tile函数位于python模块 numpy.lib.shape_base中,他的功能是重复某个数组.比如tile(A,n),功能是将数组A重复n次,构成一个新的数组,我们还是使用具体的例子来说明问题 ...

  10. unity3d加载默认工程秒退怎么办

    加载Unity3D工程时出现秒退, 怎么尝试都没有用(已经确定了项目路径名称全部为英文). 然后就再也没办法打开Unity3D了,因为一打开它就会默认加载上回的工程. 解决办法: 把最后一次加载的工程 ...