如何支持每种 MFC 文档类型的两个文件扩展名

用视图体系结构具有最多个文件扩展名与每个文档类型关联的 Microsoft 基础类 (MFC) 文档生成的应用程序。 此默认文件扩展名,如果指定,则存储在字符串表中存储的文档模板字符串。

它通常非常有用,将两种文件扩展名与给定的文档类型相关联。本文介绍了一种技术,您可以使用来允许两种文件扩展名的文档模板字符串中存储。通过派生类和函数重写,就可以将这两个文件扩展名与文档模板相关联。


分步过程

使用以下步骤可以将两种文件扩展名与 SDI 或 MDI 应用程序中的单个文档类型相关联。

  1. 修改字符串表项,以使其包含两种文件扩展名。两个扩展都将输入到 filterExt 字段之间用分号 (例如,.aaa ;。bbb)。文档模板字符串可能与此类似:
       \nExts\nExts\nFiles (*.aaa; *.bbb)\n.aaa;.bbb\nExts.Doc\nExts Doc.
    					
  2. 派生类从 CMultiDocTemplate 的 MDI 应用程序或 CSingleDocTemplate 的 SDI 应用程序。将此类添加到项目中,并在 InitInstance 函数中创建的文档模板时使用它。您将需要创建的构造函数只调用基类构造函数。
       CMyMultiDocTemplate::CMyMultiDocTemplate(
          UINT nIDResource, CRuntimeClass* pDocClass,
          CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass ) :
          CMultiDocTemplate(nIDResource, pDocClass, pFrameClass, pViewClass)
          { };
    					
  3. 重写从 CMultiDocTemplate 或 CSingleDocTemplate 在步骤 2 中的派生类中的 GetDocString 函数。
       BOOL CMyMultiDocTemplate::GetDocString(CString& rString,
                                enum DocStringIndex i) const
       {
            CString strTemp,strLeft,strRight;
            int nFindPos;
            AfxExtractSubString(strTemp, m_strDocStrings, (int)i);
    
            if(i == CDocTemplate::filterExt)  {
              nFindPos=strTemp.Find(';');
              if(-1 != nFindPos) {
                //string contains two extensions
                strLeft=strTemp.Left(nFindPos+1);
                strRight=strTemp.Right(lstrlen((const
                char*)strTemp)-nFindPos-1);
                strTemp=strLeft+strRight;
              }
            }
        rString = strTemp;
        return TRUE;
       }
    					
  4. 以便识别这两种文件扩展名打开文件时,重写 CMyMultiDocTemplate::MatchDocType。
       CDocTemplate::Confidence CMyMultiDocTemplate::MatchDocType(const
            char* pszPathName, CDocument*& rpDocMatch)
       {
            ASSERT(pszPathName != NULL);
            rpDocMatch = NULL;
    
            // go through all documents
            POSITION pos = GetFirstDocPosition();
            while (pos != NULL)
            {
               CDocument* pDoc = GetNextDoc(pos);
               if (pDoc->GetPathName() == pszPathName) {
                  // already open
                  rpDocMatch = pDoc;
                  return yesAlreadyOpen;
               }
            }  // end while
    
            // see if it matches either suffix
            CString strFilterExt;
            if (GetDocString(strFilterExt, CDocTemplate::filterExt) &&
              !strFilterExt.IsEmpty())
            {
               // see if extension matches
               ASSERT(strFilterExt[0] == '.');
               CString ext1,ext2;
               int nDot = CString(pszPathName).ReverseFind('.');
               const char* pszDot = nDot < 0 ? NULL : pszPathName + nDot;
    
               int nSemi = strFilterExt.Find(';');
               if(-1 != nSemi)   {
                 // string contains two extensions
                 ext1=strFilterExt.Left(nSemi);
                 ext2=strFilterExt.Mid(nSemi+2);
                 // check for a match against either extension
                 if (nDot >= 0 && (lstrcmpi(pszPathName+nDot, ext1) == 0
                     || lstrcmpi(pszPathName+nDot,ext2) ==0))
                   return yesAttemptNative; // extension matches
               }
               else
               { // string contains a single extension
                 if (nDot >= 0 && (lstrcmpi(pszPathName+nDot,
                     strFilterExt)==0))
                 return yesAttemptNative;  // extension matches
               }
            }
            return yesAttemptForeign; //unknown document type
       }
    					
  5. 要保存和正确保存为函数,DoSave 函数 CDocument 派生类中的重写。只需剪切并粘贴到您的派生类的从 Mfc\Src\Doccore.cpp CDocument::DoSave() 的 MFC 实现。

    替换这些行:
            // append the default suffix if there is one
            CString strExt;
            if (pTemplate->GetDocString(strExt, CDocTemplate::filterExt) &&
                !strExt.IsEmpty())
            {
               ASSERT(strExt[0] == '.');
               newName += strExt;
            }
    						
    与这些行:
            // append the default suffix if there is one
            CString strExt;
            if (pTemplate->GetDocString(strExt, CDocTemplate::filterExt) &&
                !strExt.IsEmpty())
            {
              ASSERT(strExt[0] == '.');
    
              int nSemi;                       //added
              if(nSemi = strExt.Find(';'));    //added
              strExt = strExt.Left(nSemi);     //added
    
              newName += strExt;
            }
    						
    另存为处理具有两个扩展名的文档字符串中指定的文档类型时,三种添加代码行的代码默认情况下返回第一个扩展名。如果是文件要保存的文档字符串中指定的第二个扩展,用户必须键入通过此扩展。

    您需要将下面的代码行:
          CATCH_ALL(e)
          {
          TRACE0("Warning: failed to delete file after failed SaveAs.\n");
          DELETE_EXCEPTION(e);
          }
    						
    使用:
          CATCH_ALL(e)
          {
          TRACE0("Warning: failed to delete file after failed SaveAs.\n");
          e->Delete();     //modified
          }
    						
    这是必要的因为在此上下文中未定义的 DELETE_EXCEPTION() 宏。
  6. (仅适用于 16 位版本)使用类向导来提供文档派生的类中的 OnFileSave 和 OnFileSaveAs 命令处理程序。这是有必要的因为在 Visual C++ 16 位版本中,DoSave 函数不是虚拟。只是剪切和粘贴命令处理程序从 Mfc\Src\Doccore.cpp 这两个函数的基类版本的内容。生成函数调用 DoSave,而不是基类版本的本地副本。它可能需要添加 #include"io.h",向项目提供的 _access 函数的定义。
本文摘自微软microsoft帮助网页

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值