📄 chap7_5.htm
字号:
<p><font face="Times New Roman"><b>TRY</b></font></p> <p><font face="Times New Roman"><b>{</b></font></p> <p><font face="Times New Roman"><b>m_hDIB = ::ReadDIBFile(file);</b></font></p> <p><font face="Times New Roman"><b>}</b></font></p> <p><font face="Times New Roman"><b>CATCH (CFileException, eLoad)</b></font></p> <p><font face="Times New Roman"><b>{</b></font></p> <p><font face="Times New Roman"><b>file.Abort(); // will not throw an exception</b></font></p> <p><font face="Times New Roman"><b>EndWaitCursor();</b></font></p> <p><font face="Times New Roman"><b>ReportSaveLoadException(lpszPathName, eLoad,</b></font></p> <p><font face="Times New Roman"><b>FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);</b></font></p> <p><font face="Times New Roman"><b>m_hDIB = NULL;</b></font></p> <p><font face="Times New Roman"><b>return FALSE;</b></font></p> <p><font face="Times New Roman"><b>}</b></font></p> <p><font face="Times New Roman"><b>END_CATCH</b></font></p> <p><font face="Times New Roman"><b>InitDIBData();</b></font></p> <p><font face="Times New Roman"><b>EndWaitCursor();</b></font></p> <p><font face="Times New Roman"><b>if (m_hDIB == NULL)</b></font></p> <p><font face="Times New Roman"><b>{</b></font></p> <p><font face="Times New Roman"><b>// may not be DIB format</b></font></p> <p><font face="Times New Roman"><b>CString strMsg;</b></font></p> <p><font face="Times New Roman"><b>strMsg.LoadString(IDS_CANNOT_LOAD_DIB);</b></font></p> <p><font face="Times New Roman"><b>MessageBox(NULL, strMsg, NULL, MB_ICONINFORMATION | MB_OK);</b></font></p> <p><font face="Times New Roman"><b>return FALSE;</b></font></p> <p><font face="Times New Roman"><b>}</b></font></p> <p><font face="Times New Roman"><b>SetPathName(lpszPathName);</b></font></p> <p><font face="Times New Roman"><b>SetModifiedFlag(FALSE); // start off with unmodified</b></font></p> <p><font face="Times New Roman">return TRUE;</font></p> <p><font face="Times New Roman">}</font></p> <p><font face="Times New Roman">BOOL CDibDoc::OnSaveDocument(LPCTSTR lpszPathName)</font></p> <p><font face="Times New Roman">{</font></p> <p><font face="Times New Roman">CFile file;</font></p> <p><font face="Times New Roman">CFileException fe;</font></p> <p><font face="Times New Roman">if (!file.Open(lpszPathName, CFile::modeCreate |</font></p> <p><font face="Times New Roman">CFile::modeReadWrite | CFile::shareExclusive, &fe))</font></p> <p><font face="Times New Roman">{</font></p> <p><font face="Times New Roman">ReportSaveLoadException(lpszPathName, &fe,</font></p> <p><font face="Times New Roman">TRUE, AFX_IDP_INVALID_FILENAME);</font></p> <p><font face="Times New Roman">return FALSE;</font></p> <p><font face="Times New Roman">}</font></p> <p><font face="Times New Roman"><b>// replace calls to Serialize with SaveDIB function</b></font></p> <p><font face="Times New Roman"><b>BOOL bSuccess = FALSE;</b></font></p> <p><font face="Times New Roman"><b>TRY</b></font></p> <p><font face="Times New Roman"><b>{</b></font></p> <p><font face="Times New Roman"><b>BeginWaitCursor();</b></font></p> <p><font face="Times New Roman"><b>bSuccess = ::SaveDIB(m_hDIB, file);</b></font></p> <p><font face="Times New Roman"><b>file.Close();</b></font></p> <p><font face="Times New Roman"><b>}</b></font></p> <p><font face="Times New Roman"><b>CATCH (CException, eSave)</b></font></p> <p><font face="Times New Roman"><b>{</b></font></p> <p><font face="Times New Roman"><b>file.Abort(); // will not throw an exception</b></font></p> <p><font face="Times New Roman"><b>EndWaitCursor();</b></font></p> <p><font face="Times New Roman"><b>ReportSaveLoadException(lpszPathName, eSave,</b></font></p> <p><font face="Times New Roman"><b>TRUE, AFX_IDP_FAILED_TO_SAVE_DOC);</b></font></p> <p><font face="Times New Roman"><b>return FALSE;</b></font></p> <p><font face="Times New Roman"><b>}</b></font></p> <p><font face="Times New Roman"><b>END_CATCH</b></font></p> <p><font face="Times New Roman"><b>EndWaitCursor();</b></font></p> <p><font face="Times New Roman"><b>SetModifiedFlag(FALSE); // back to unmodified</b></font></p> <p><font face="Times New Roman"><b>if (!bSuccess)</b></font></p> <p><font face="Times New Roman"><b>{</b></font></p> <p><font face="Times New Roman"><b>// may be other-style DIB (load supported but not save)</b></font></p> <p><font face="Times New Roman"><b>// or other problem in SaveDIB</b></font></p> <p><font face="Times New Roman"><b>CString strMsg;</b></font></p> <p><font face="Times New Roman"><b>strMsg.LoadString(IDS_CANNOT_SAVE_DIB);</b></font></p> <p><font face="Times New Roman"><b>MessageBox(NULL, strMsg, NULL, MB_ICONINFORMATION | MB_OK);</b></font></p> <p><font face="Times New Roman"><b>}</b></font></p> <p><font face="Times New Roman"><b>return bSuccess;</b></font></p> <p><font face="Times New Roman">}</font></p> <p><font face="Times New Roman"><b>void CDibDoc::ReplaceHDIB(HDIB hDIB)</b></font></p> <p><font face="Times New Roman"><b>{</b></font></p> <p><font face="Times New Roman"><b>if (m_hDIB != NULL)</b></font></p> <p><font face="Times New Roman"><b>{</b></font></p> <p><font face="Times New Roman"><b>::GlobalFree((HGLOBAL) m_hDIB);</b></font></p> <p><font face="Times New Roman"><b>}</b></font></p> <p><font face="Times New Roman"><b>m_hDIB = hDIB;</b></font></p> <p><font face="Times New Roman"><b>}</b></font></p> <p><font face="Times New Roman">/////////////////////////////////////////////////////////////////////////////</font></p> <p><font face="Times New Roman">// CDibDoc diagnostics</font></p> <p><font face="Times New Roman">#ifdef _DEBUG</font></p> <p><font face="Times New Roman">void CDibDoc::AssertValid() const</font></p> <p><font face="Times New Roman">{</font></p> <p><font face="Times New Roman">CDocument::AssertValid();</font></p> <p><font face="Times New Roman">}</font></p> <p><font face="Times New Roman">void CDibDoc::Dump(CDumpContext& dc) const</font></p> <p><font face="Times New Roman">{</font></p> <p><font face="Times New Roman">CDocument::Dump(dc);</font></p> <p><font face="Times New Roman">}</font></p> <p><font face="Times New Roman">#endif //_DEBUG</font></p> <p><font face="Times New Roman">/////////////////////////////////////////////////////////////////////////////</font></p> <p><font face="Times New Roman">// CDibDoc commands</font></p> <p><font face="Times New Roman"> DIBLOOK</font><font >读入和保存标准的</font><font face="Times New Roman">Windows</font><font >设备无关位图。在内存中,位图以一个</font><font face="Times New Roman">HDIB</font><font >句柄表示。</font><font face="Times New Roman">DIBLOOK</font><font >没有重 载</font><font face="Times New Roman">CDocument::Serialize()</font><font >函数,而是重载了</font><font face="Times New Roman">CDocument::OnOpenDocument</font><font >和</font><font face="Times New Roman">CDocument::OnSaveDocument</font><font >函数。这两个函数使用框架传过来得文件路径名</font><font face="Times New Roman">pszPathName</font><font >,打开一个文件对象,读入或保存</font><font face="Times New Roman">DIB</font><font >数据。这就是说,</font><font face="Times New Roman">DIBLOOK</font><font >把本来在</font><font face="Times New Roman">Serialize()</font><font >中完成的对象保存和载入两个任务分别交与</font><font face="Times New Roman">OnSaveDocument()</font><font >函数和</font><font face="Times New Roman">OnOpenDocument()</font><font >函数去完成。如果读者希望绕过文档的串行化提供文档数据的保存和载入,也只需要重载这两个成员函数:</font><font face="Times New Roman">OnOpenDocument()</font><font >和</font><font face="Times New Roman">OnSaveDocument()</font><font >,通过文件路径参数打开文件,从中读取应用程序数据或向文件里写入应用程序数据。</font></p> <p><font > 在</font><font face="Times New Roman">OnOpenDocument()</font><font >中,还必需自己调用</font><font face="Times New Roman">DeleteContents()</font><font >清除原来文档的数据,并调用</font><font face="Times New Roman">SetModifiedFlag(FALSE)</font><font >。在</font><font face="Times New Roman">OnSaveDocument()</font><font >中也要调用</font><font face="Times New Roman">SetModifiedFlag(FALSE)</font><font >将文档修改标志改为</font><font face="Times New Roman">FALSE</font><font >。</font></p> <p><font >在</font><font face="Times New Roman">OnOpenDocument()</font><font >函数开始处(见清单</font><font face="Times New Roman">7.18</font><font >),有一些地方需要解释一下。</font></p> <p><font ><b>清单</b></font><font face="Times New Roman"><b>7.18 OnOpenDocument()</b></font><font ><b>函数</b></font></p> <p><font face="Times New Roman">BOOL CDibDoc::OnOpenDocument(LPCTSTR lpszPathName)</font></p> <p><font face="Times New Roman">{</font></p> <p><font face="Times New Roman"><b>CFile file;</b></font></p> <p><font face="Times New Roman"><b>CFileException fe;</b></font></p> <p><font face="Times New Roman"><b>if (!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite, &fe))</b></font></p> <p><font face="Times New Roman"><b>{</b></font></p> <p><font face="Times New Roman"><b>ReportSaveLoadException(lpszPathName, &fe,</b></font></p> <p><font face="Times New Roman"><b>FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);</b></font></p> <p><font face="Times New Roman"><b>return FALSE;</b></font></p> <p><font face="Times New Roman"><b>}</b></font></p> <p><font face="Times New Roman">......</font></p> <p><font face="Times New Roman">}</font></p> <p><font color="#3973DE" face="Times New Roman">7.5.1 </font><font color="#3973DE" >文件操作</font></p> <p><font color="#3973DE" >文件读写</font></p> <p><font face="Times New Roman"> OnOpenDocument</font><font >首先声明一个</font><font face="Times New Roman">CFile</font><font >类的对象。</font><font face="Times New Roman">CFile</font><font >是</font><font face="Times New Roman">MFC</font><font >提供的一个类,它提供了访问二进制文件的接口。可以使用带参数的</font><font face="Times New Roman">CFile</font><font >构造函数创建对象,在构造函数中指定了文件名和打开文件的模式,这样在对象创建的同时也就打开了这个文件;也可以象本例那样使用不带参数的</font><font face="Times New Roman">CFile</font><font >构造函数构造一个</font><font face="Times New Roman">CFile</font><font >对象,然后调用</font><font face="Times New Roman">CFile::Open()</font><font >打开一个文件。</font></p> <blockquote> <blockquote> <p><font face="Times New Roman"><b>BOOL</b> <b>CFile::Open(</b> <b>LPCTSTR</b> <i>lpszFileName</i><b>,</b> <b>UINT</b> <i>nOpenFlags</i><b>,</b> <b>CFileException*</b> <i>pError</i> <b>=</b> <b>NULL</b> <b>);</b></font></p> </blockquote> </blockquote> <p><font face="Times New Roman"> CFile::Open</font><font >成员函数带三个参数,第一个参数指定了要打开的文件的完整路径名,如“</font><font face="Times New Roman">c:\hello\hello.cpp</font><font >”;第二个参数指定打开文件的模式。</font></p> <p><font > 常见的文件打开模式有以下几种:</font></p> <p><font face="Times New Roman"> CFile::modeCreate</font><font >:创建一个新文件,如果该文件已经存在,则把该文件长度置为零</font></p> <p><font face="Times New Roman"> CFile::modeNoTruncate</font><font >:与</font><font face="Times New Roman">modeCreate</font><font >一起使用。告诉</font><font face="Times New Roman">CFile</font><font >,如果要创建的文件已经存在,则不再将文件长度设置为零。这对于系统设置文件、日志文件等特别有用,因为第一次启动系统时,这些文件通常不存在,需要创建,而下次则只需要修改文件。</font></p> <p><font face="Times New Roman"> CFile::modeRead</font><font >:打开文件用于读</font></p> <p><font face="Times New Roman"> CFile::modeWrite</font><font >:打开文件用于写</font></p> <p><font face="Times New Roman"> CFile::modeReadWrite</font><font >:打开文件且对文件可读可写</font></p> <p><font > 可以使用比特位或“</font><font face="Times New Roman">|</font><font >”对上述操作进行组合。比如,要打开文件写,可以用以下方式打开:</font></p> <p><font face="Times New Roman">CFile file;</font></p> <p><font face="Times New Roman">file.Open(</font><font >“</font><font face="Times New Roman">c:\\readme.txt</font><font >”</font><font face="Times New Roman">,CFile::modeCreate|CFile::modeWrite); </font></p> <p><font color="#3973DE" >读文件</font></p> <p><font > 既然已经打开了文件,就可以对文件进行读写操作了。要读取文件内容到内存,可以调用</font><font face="Times New Roman">CFile::Read()</font><font >。</font><font face="Times New Roman">CFile::Read()</font><font >函数原型如下:</font></p> <p><font size="2" face="Arial"><b>UINT</b> <b>Read(</b> <b>void*</b> <i>lpBuf</i><b>,</b> <b>UINT</b> <i>nCount</i> <b>);</b></font><br> Read函数包含两个参数,第一个参数是一个缓冲区指针,该缓冲区用于存放从文件读进来的内容。第二个参数是要读取的字节数。Read函数返回实际读入的字节数。例如:</p> <p>CFile file;</p> <p>char buf[100];</p> <p>int nBytesRead;</p> <p>nBytesRead=file.Read(buf,100);</p> <p><font color="#3973DE" >写文件</font></p> <p><font > 写文件与读文件操作方式类似,通过调用</font><font face="Times New Roman">CFile::Write</font><font >函数来完成。</font></p> <p><font face="Times New Roman">void Write( const void* lpBuf, UINT nCount );</font></p> <p><font face="Times New Roman">Write</font><font >函数第一个参数是指向要写入到文件中的缓冲区的指针,第二个参数是要写入到文件中的字节数。例如:</font></p> <p><font >CFile file;</font></p> <p><font >CString str(“This is a string.”);</font></p> <p><font >file.Write(str,str.GetLength());</font></p> <p><br> <font color="#3973DE" >关闭文件</font></p> <p><font > 在完成文件读写操作后,要调用CFile::Close成员函数及时将文件关闭。</font></p> <p><font >CFile file;</font></p> <p><font >//一些读写操作.....</font></p> <p><font >file.Close();</font></p> <p><font color="#3973DE">7.5.2异常处理</font></p> <p><font > 在打开和保存文件时,我们并未作传统的错误检查,而是采用一种异常机制来处理错误。</font></p> <p><font > 异常处理为异常事件提供了结构化、规范化的服务。它一般是指处理错误状态。</font></p> <p><font > 我们先回顾一下传统的错误处理方式。传统的错误处理方式通常有两种:</font></p> <p><font >1.返回错误值</font></p> <p><font >2.使用goto,setjmp/longjmp协助报告错误</font></p> <p><font > 对于第一种技术,要求程序员记住各种错误代码,并且加入大量的检查情况。由于大多数错误是很少会发生,这样处理的结果是代码冗余性很大,效率不高。</font></p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -