如何在文件菜单中控制最近打开的文件?

有文参考:  
  http://www.fmdstudio.net/articles/mfcsrc/01912235946.htm  
   
  MFC框架中对最近文件列表的支持  
   
  MFC建立的标准框架程序中有记录最近操作文件的能力,这些最近文件的路径被记录到注册表,在程序运行时,又将添加到文件菜单中。    
   
  在CWinApp中有个   CRecentFileList*   m_pRecentFileList;指针管理这些信息。    
   
  以下对此过程进行分析,采用类似的方法,可以保存其他一些固定条数的最近数据。    
   
   
  1.CRecentFileList对象的建立,记录读入、记录保存、对象销毁。    
   
  ①建立与记录的读入    
   
  如果在CWinApp派生类中InitInstance()中调用了LoadStdProfileSettings,则CRecentFileList被建立,时程序具有管理最近文件列表的能力。    
   
  同时,从注册表中读入以前的记录。    
   
  void   CWinApp::LoadStdProfileSettings(UINT   nMaxMRU)   //缺省为4  
  {  
  ...  
  if   (nMaxMRU   !=   0)  
  {  
  //建立CRecentFileList对象,初始化为管理nMaxMRU条文件信息  
  m_pRecentFileList   =   new   CRecentFileList(0,   _afxFileSection,   _afxFileEntry,nMaxMRU);  
  //读入记录  
  m_pRecentFileList->   ReadList();  
  }  
  ...  
  }  
   
  CRecentFileList对象中的主要数据成员    
   
  CRecentFileList包含一个CString指针   CString*   m_arrNames;   ,它用来指向一个CString对象数组,正是这个数组记录了最近的文件名。    
   
  另外,成员   int   m_nSize   指出了记录的个数。    
   
  在对象创建时,构造函数完成初始化,包括CString数组的建立等。    
   
  ②记录的保存、CRecentFileList的销毁。    
   
  ExitInstance()中将调用SaveStdProfileSettings(),SaveStdProfileSettings()中有m_pRecentFileList->WriteList();操作,完成记录的保存。    
   
  在CWinApp析构时将delete   m_pRecentFileList;销毁对象。    
   
  CRecentFileList::CRecentFileList(UINT   nStart,   LPCTSTR   lpszSection,  
  LPCTSTR   lpszEntryFormat,   int   nSize,   int   nMaxDispLen)  
  {  
  ASSERT(nSize   !=   0);  
  m_arrNames   =   new   CString[nSize];   //建立CString数组。  
  m_nSize   =   nSize;  
   
  m_nStart   =   nStart;  
  m_strSectionName   =   lpszSection;  
  m_strEntryFormat   =   lpszEntryFormat;  
  m_nMaxDisplayLength   =   nMaxDispLen;  
  }  
   
  3.记录的添加    
   
  文档保存时,将调用SetPathName(..),SetPathName(..)中将调用应用程序类中的AddToRecentFileList    
   
  AddToRecentFileList中执行m_pRecentFileList->Add(lpszPathName)将文件名添加到字符串数组    
   
  void   CRecentFileList::Add(LPCTSTR   lpszPathName)  
  {  
  ASSERT(m_arrNames   !=   NULL);  
  ASSERT(lpszPathName   !=   NULL);  
  ASSERT(AfxIsValidString(lpszPathName));  
   
  //   fully   qualify   the   path   name  
  TCHAR   szTemp[_MAX_PATH];  
  AfxFullPath(szTemp,   lpszPathName);     //得到文件全路径  
   
  //   查找,看是否已经有此文件名  
  for   (int   iMRU   =   0;   iMRU   <   m_nSize-1;   iMRU++)  
  {  
  if   (AfxComparePath(m_arrNames[iMRU],   szTemp))  
  break;             //   iMRU   will   point   to   matching   entry  
  }  
  //   其前面的各项后移  
  for   (;   iMRU   >   0;   iMRU--)  
  {  
  ASSERT(iMRU   >   0);  
  ASSERT(iMRU   <   m_nSize);  
  m_arrNames[iMRU]   =   m_arrNames[iMRU-1];  
  }  
  //添加到起始位置  
  m_arrNames[0]   =   szTemp;  
  }  
   
  4.记录的删除    
   
  如果用户从菜单中选择打开某记录对应的文件,单该文件已经不存在,则将删除该无效记录。    
   
  void   CRecentFileList::Remove(int   nIndex)  
  {  
  ASSERT(nIndex   >=   0);  
  ASSERT(nIndex   <   m_nSize);  
   
  m_arrNames[nIndex].Empty();  
  for   (int   iMRU   =   nIndex;   iMRU   <   m_nSize-1;   iMRU++)  
  m_arrNames[iMRU]   =   m_arrNames[iMRU+1];   //其后各项前移  
   
  ASSERT(iMRU   <   m_nSize);  
  m_arrNames[iMRU].Empty();  
  }  
   
  5.记录数据的保存    
  void   CRecentFileList::WriteList()  
  {  
  ASSERT(m_arrNames   !=   NULL);  
  ASSERT(!m_strSectionName.IsEmpty());     //   m_strSectionName   :   _T("Recent   File   List")  
  ASSERT(!m_strEntryFormat.IsEmpty());     //   m_strEntryFormat   :   _T("File%d")      
  LPTSTR   pszEntry   =   new   TCHAR[m_strEntryFormat.GetLength()+5];  
  CWinApp*   pApp   =   AfxGetApp();  
  pApp->   WriteProfileString(m_strSectionName,   NULL,   NULL);   //写入Recent   File   List键  
  for   (int   iMRU   =   0;   iMRU   <   m_nSize;   iMRU++)  
  {  
  wsprintf(pszEntry,   m_strEntryFormat,   iMRU   +   1);     //得到号吗字符串  
  if   (!m_arrNames[iMRU].IsEmpty())  
  {  
  pApp->   WriteProfileString(m_strSectionName,   pszEntry,       //在写值名pszEntry,对应值为文件名。  
  m_arrNames[iMRU]);  
  }  
  }  
  delete[]   pszEntry;  
  }  
   
  6.记录数据的读取    
   
  void   CRecentFileList::ReadList()  
  {  
  ASSERT(m_arrNames   !=   NULL);  
  ASSERT(!m_strSectionName.IsEmpty());  
  ASSERT(!m_strEntryFormat.IsEmpty());  
  LPTSTR   pszEntry   =   new   TCHAR[m_strEntryFormat.GetLength()+5];  
  CWinApp*   pApp   =   AfxGetApp();  
  for   (int   iMRU   =   0;   iMRU   <   m_nSize;   iMRU++)  
  {  
  wsprintf(pszEntry,   m_strEntryFormat,   iMRU   +   1);     //得到值名字符串  
  m_arrNames[iMRU]   =   pApp->   GetProfileString( //取值名下的值,此即个记录,若值不存在,则为NULL  
  m_strSectionName,   pszEntry,   &afxChNil);  
  }  
  delete[]   pszEntry;  
  }  
   
   
  7.将记录添加到菜单项    
   
  菜单资源中文件菜单下有ID为ID_FILE_MRU_FILE1的菜单项,用于在此处添加最近文件菜单项。    
   
  命令更新机制根据ON_UPDATE_COMMAND_UI(ID_FILE_MRU_FILE1,   OnUpdateRecentFileMenu)将经常调用到  
   
  CWinApp::OnUpdateRecentFileMenu(..)    
   
  OnUpdateRecentFileMenu中调用void   CRecentFileList::UpdateMenu(CCmdUI*   pCmdUI)    
   
  void   CRecentFileList::UpdateMenu(CCmdUI*   pCmdUI)  
  {  
  ASSERT(m_arrNames   !=   NULL);  
   
  CMenu*   pMenu   =   pCmdUI->   m_pMenu;   //由pCmdUI直接找到菜单  
  if   (m_strOriginal.IsEmpty()   &&   pMenu   !=   NULL)  
  pMenu->   GetMenuString(pCmdUI->   m_nID,   m_strOriginal,   MF_BYCOMMAND);  
   
  if   (m_arrNames[0].IsEmpty())  
  {  
  //   no   MRU   files  
  if   (!m_strOriginal.IsEmpty())  
  pCmdUI->   SetText(m_strOriginal);  
  pCmdUI->   Enable(FALSE);  
  return;  
  }  
   
  if   (pCmdUI->   m_pMenu   ==   NULL)  
  return;  
   
  for   (int   iMRU   =   0;   iMRU   <   m_nSize;   iMRU++)       //删除所有最新文件菜单项  
  pCmdUI->   m_pMenu->   DeleteMenu(pCmdUI->   m_nID   +   iMRU,   MF_BYCOMMAND);  
   
  TCHAR   szCurDir[_MAX_PATH];  
  GetCurrentDirectory(_MAX_PATH,   szCurDir);  
  int   nCurDir   =   lstrlen(szCurDir);  
  ASSERT(nCurDir   >=   0);  
  szCurDir[nCurDir]   =   '//';  
  szCurDir[++nCurDir]   =   '/0';  
   
  CString   strName;  
  CString   strTemp;  
  for   (iMRU   =   0;   iMRU   <   m_nSize;   iMRU++)  
  {  
  if   (!GetDisplayName(strName,   iMRU,   szCurDir,   nCurDir))  
  break;  
   
  //   double   up   any   '&'   characters   so   they   are   not   underlined  
  LPCTSTR   lpszSrc   =   strName;  
  LPTSTR   lpszDest   =   strTemp.GetBuffer(strName.GetLength()*2);  
  while   (*lpszSrc   !=   0)  
  {  
  if   (*lpszSrc   ==   '&')  
  *lpszDest++   =   '&';  
  if   (_istlead(*lpszSrc))  
  *lpszDest++   =   *lpszSrc++;  
  *lpszDest++   =   *lpszSrc++;  
  }  
  *lpszDest   =   0;  
  strTemp.ReleaseBuffer();  
   
  //   insert   mnemonic   +   the   file   name  
  TCHAR   buf[10];  
  wsprintf(buf,   _T("&%d   "),   (iMRU+1+m_nStart)   %   10);  
  pCmdUI->   m_pMenu->   InsertMenu(pCmdUI->   m_nIndex++,  
  MF_STRING   |   MF_BYPOSITION,   pCmdUI->   m_nID++,  
  CString(buf)   +   strTemp);     //添加菜单项  
  }  
   
  //   update   end   menu   count  
  pCmdUI->   m_nIndex--;   //   point   to   last   menu   added  
  pCmdUI->   m_nIndexMax   =   pCmdUI->   m_pMenu->   GetMenuItemCount();  
   
  pCmdUI->   m_bEnableChanged   =   TRUE;         //   all   the   added   items   are   enabled  
  }  
   
  8.对最近文件菜单项的相应    
   
  系统通过消息映射   ON_COMMAND_EX_RANGE(ID_FILE_MRU_FILE1,   ID_FILE_MRU_FILE16,   OnOpenRecentFile)    
   
  调用OnOpenRecentFile,命令ID作为参数传入    
   
  BOOL   CWinApp::OnOpenRecentFile(UINT   nID)  
  {  
  ASSERT_VALID(this);  
  ASSERT(m_pRecentFileList   !=   NULL);  
   
  ASSERT(nID   >=   ID_FILE_MRU_FILE1);  
  ASSERT(nID   <   ID_FILE_MRU_FILE1   +   (UINT)m_pRecentFileList->   GetSize());  
  int   nIndex   =   nID   -   ID_FILE_MRU_FILE1;  
  ASSERT((*m_pRecentFileList)[nIndex].GetLength()   !=   0);  
   
  TRACE2("MRU:   open   file   (%d)   '%s'./n",   (nIndex)   +   1,  
  (LPCTSTR)(*m_pRecentFileList)[nIndex]);  
   
  if   (OpenDocumentFile((*m_pRecentFileList)[nIndex])   ==   NULL)  
  m_pRecentFileList->   Remove(nIndex);  
   
  return   TRUE;   
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值