7.2文档及其序列化 7.23SDI序列化过程 创建空文档 应用程序类的 IInitInstance函数在调用了 AddDocTemplatel函数之后,会通过 CWinApp: ProcessshellCommand间接调用 CWinApp的另一个非常有用的 成员函数 On FileNew,并依次完成下列工作: (1)构造文档对象,但并不从磁盘中读数据。 (2)构造主框架类 MAin Frame的对象,并创建该主框架窗口,但不显示 (3)构造视图对象,并创建视图窗口,也不显示。 (4)通过内部机制,使文档、主框架和视图“对象”之间“真正”建立联系 AdddocTemplate函数建立的是“类”之间的联系 (5)调用文档对象的 CDocument: OnNew Document虚成员函数,并调用 CDocument:;: Delete Contents(清除文档对象的内容)虚函数 (6)调用视图对象的cvew: OninitialUpdate虚成员函数 (刀)调用框架对象的 CFrameWnd: Active Frame虚成员函数,以便显示出具 有菜单、工具栏、状态栏以及视图窗口的主框架窗口 MFC AppWizard为用户在文档类中自动产生 OnNew Document虚函数的重载, 用户利用此函数框架可以对文档对象进行初始化
7.2文档及其序列化 7.2.3 SDI序列化过程 ➢ 创建空文档 应用程序类的InitInstance函数在调用了AddDocTemplate函数之后,会通过 CWinApp:: ProcessShellCommand间接调用CWinApp的另一个非常有用的 成员函数OnFileNew,并依次完成下列工作: (1)构造文档对象,但并不从磁盘中读数据。 (2)构造主框架类CMainFrame的对象,并创建该主框架窗口,但不显示。 (3)构造视图对象,并创建视图窗口,也不显示。 (4)通过内部机制,使文档、主框架和视图“对象”之间“真正”建立联系。 AddDocTemplate函数建立的是“类”之间的联系。 (5)调用文档对象的CDocument::OnNewDocument虚成员函数,并调用 CDocument:: DeleteContents(清除文档对象的内容)虚函数。 (6)调用视图对象的CView::OnInitialUpdate虚成员函数。 (7)调用框架对象的CFrameWnd::ActiveFrame虚成员函数,以便显示出具 有菜单、工具栏、状态栏以及视图窗口的主框架窗口。 MFC AppWizard为用户在文档类中自动产生OnNewDocument虚函数的重载, 用户利用此函数框架可以对文档对象进行初始化
7.2文档及其序列化 >打开文档 MFC AppWizard创建应用程序时,它会自动将“文件(Fe)菜单中的“打开 (Open)”命令(ID号为 ID FILE_OPEN)映射到 CWinApp的 OnFileOpen成员函 数。这一结果可以从应用类(Cpp)的消息入口处得到验证: BEGIN_MESSAGE_ MAP(CEX_SdiApp, CWinApp ON_COMMAND(ID_FILE_NEW, CWinApp: OnFileNew) ON_COMMANDID_FILE_OPEN, CWinApp: OnFileOpen) // Standard print setup command ON_ COMMAND(ID_FILE_ PRINT_ SETUP, CWinApp: On FilePrintSetup) END_MESSAGE_MAPO OnFileOpen函数还会进一步完成下列工作 (1)弹出通用“打开”对话框,供用户选择一个文件 (2)调用文档对象的 CDocument: OnOpen Document虚成员函数。该函数将 打开文件,并调用 Delete Contents清除文档对象的内容,然后创建一个 CArchive对象用于数据的读取,接着又自动调用 Serialize函数 (3)调用视图对象的Cew: OnInitialUpdate虚成员函数
7.2文档及其序列化 ➢ 打开文档 MFC AppWizard创建应用程序时,它会自动将“文件(File)”菜单中的“打开 (Open)”命令(ID号为ID_FILE_OPEN)映射到CWinApp的OnFileOpen成员函 数。这一结果可以从应用类(.cpp)的消息入口处得到验证: BEGIN_MESSAGE_MAP(CEx_SdiApp, CWinApp) …… ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP() OnFileOpen函数还会进一步完成下列工作: (1)弹出通用“打开”对话框,供用户选择一个文件。 (2)调用文档对象的CDocument:: OnOpenDocument虚成员函数。该函数将 打开文件,并调用DeleteContents清除文档对象的内容,然后创建一个 CArchive对象用于数据的读取,接着又自动调用Serialize函数。 (3)调用视图对象的CView::OnInitialUpdate虚成员函数
7.2文档及其序列化 MFC为我们重载了 Serialize函数,使得我们不必使用CFle类就可以完成相应 的文档操作。例如,在文档类中有这样的代码 void CEx_ SdiDoc. Serialize(CArchive& ar) if (ar. IsStoring //TODO: add storing code here else //TODO: add loading code here 只需根据 ar StOring(结果的“真”与“假”就可决定向文档写与读数据。 例如,在此判断体中,可以增加一些代码来读取文档中的数据: void CEx_ SdiDoc. Serialize(cArchive& ar) if (ar Is Storing)& else for(int i=0; i<sizeof(_ch); i++) ar>>m_ch[] CString str str Format(T(%s),m_ch); AfxMessage Box(str)
7.2文档及其序列化 MFC为我们重载了Serialize函数,使得我们不必使用CFile类就可以完成相应 的文档操作。例如,在文档类中有这样的代码: void CEx_SdiDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here } } 只需根据ar.IsStoring()结果的“真”与“假”就可决定向文档写与读数据。 例如,在此判断体中,可以增加一些代码来读取文档中的数据: void CEx_SdiDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) {} else { for (int i=0; i<sizeof(m_ch); i++) ar>>m_ch[i]; CString str; str.Format(_T(“%s”), m_ch); AfxMessageBox(str); } }
7.2文档及其序列化 >保存文档 MFC AppWizard创建应用程序时,会自动将“文件(File)菜单中的“保存 (Save)命令与文档类 CDocument的 OnFilesave函数在内部关联起来,在程 序框架中看不到相应的代码。 On File Savel函数还会进一步完成下列工作 (1)弹出通用“保存”对话框,让用户提供一个文件名。 (2)调用文档对象的 CDocument: On Document虚成员函数,接着又自 动调用 Serialize函数,将 CArchive对象的内容保存在文档中 需要说明的是: 只有在保存文档之前还没有存过盘或读取的文档是“只读”的, On Filesave函数才会弹出通用“保存”对话框。否则,只执行第二步 文件(Fie)菜单中还有一个“另存为( Save as)”命令,它是与文档类 CDocument的 On FilesayeAs函数相关联。不管文档有没有保存过, OnFilesaveAs都有会执行上述两个步骤。 可以用 ClassWizard来重载 CDocument: OnSave Document函数,并可在 Serialize函数体的 ar. Isstorinr(为“真”的条件语句处添加代码来在文档中 保存用户自己的数据
7.2文档及其序列化 ➢ 保存文档 MFC AppWizard创建应用程序时,会自动将“文件(File)”菜单中的“保存 (Save)”命令与文档类CDocument的OnFileSave函数在内部关联起来,在程 序框架中看不到相应的代码。OnFileSave函数还会进一步完成下列工作: (1)弹出通用“保存”对话框,让用户提供一个文件名。 (2)调用文档对象的CDocument::OnSaveDocument虚成员函数,接着又自 动调用Serialize函数,将CArchive对象的内容保存在文档中。 需要说明的是: ◆ 只有在保存文档之前还没有存过盘或读取的文档是“只读”的, OnFileSave函数才会弹出通用“保存”对话框。否则,只执行第二步。 ◆ “文件(File)”菜单中还有一个“另存为(Save As)”命令,它是与文档类 CDocument的OnFileSaveAs函数相关联。不管文档有没有保存过, OnFileSaveAs都有会执行上述两个步骤。 可以用ClassWizard来重载CDocument::OnSaveDocument函数,并可在 Serialize函数体的ar.IsStorinr()为“真”的条件语句处添加代码来在文档中 保存用户自己的数据
7.2文档及其序列化 >关闭文档 试图关闭文档时,应用程序会根据文档是否修改进一步完成下列任务: 若文档内容已被修改,则弹出一个消息对话框,询问用户是否需要将文 档保存。若用户选择“是”,则应用程序执行 On File save过程。 调用 CDocument: Onclose document虚成员函数,关闭所有与该文档相 关联的文档窗口及相应的视图,调用文档类 CDocument的 Delete Contents清除文档数据。 MFC应用程序通过 CDocument的数据成员 m bModified的逻辑值来判断用户 是否对文档进行修改,如果 m bModified为“真”,则表示文档被修改 protected类型的 m bModified标记是通过 CDocument的 SetModifiedFlag和 Is Modified成员函数被访问的。当文档创建、从磁盘中读出以及文档存盘时 文档的这个标记就被置为 FALSE(假):而当文档数据被修改时,必须使用 SetModified Flag函数将该标记置为TRUE。关闭文档时,应用程序才会显示 询问消息对话框
7.2文档及其序列化 ➢ 关闭文档 试图关闭文档时,应用程序会根据文档是否修改进一步完成下列任务: ▪ 若文档内容已被修改,则弹出一个消息对话框,询问用户是否需要将文 档保存。若用户选择“是”,则应用程序执行OnFileSave过程。 ▪ 调用CDocument::OnCloseDocument虚成员函数,关闭所有与该文档相 关联的文档窗口及相应的视图,调用文档类CDocument的 DeleteContents清除文档数据。 ◆ MFC应用程序通过CDocument的数据成员m_bModified的逻辑值来判断用户 是否对文档进行修改,如果m_bModified为“真”,则表示文档被修改。 ◆ protected类型的m_bModified标记是通过CDocument的SetModifiedFlag和 IsModified成员函数被访问的。当文档创建、从磁盘中读出以及文档存盘时, 文档的这个标记就被置为FALSE(假);而当文档数据被修改时,必须使用 SetModifiedFlag函数将该标记置为TRUE。关闭文档时,应用程序才会显示 询问消息对话框