MFC最近文件列表的使用[转]

2023-05-16

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;

转载于:https://www.cnblogs.com/Dennis-mi/articles/3385878.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MFC最近文件列表的使用[转] 的相关文章

  • MFC中Tree(CTreeCtrl)中添加特定树项的图标

    我们可以为特定的树项目添加图标吗 我使用以下功能添加带有图标的项目 HTREEITEM InsertItem LPCTSTR lpszItem int nImage int nSelectedImage HTREEITEM hParent
  • C++ Builder vs Delphi vs MFC

    我正在学习MFC 发现它不太好用 我听说过很多关于 Delphi 的事 对 Delphi 的研究让我接触到了 C Builder C Builder 是否提供了 C MFC 的严肃且良好的替代方案 C Builder 比 MFC 更好吗 C
  • dll 中的 MFC LoadString 失败

    我在 dll 中有一个静态函数 它使用 LoadString 从资源加载字符串 当我从该 dll 调用此函数时 一切正常 但是 当我从其他模块 activeX 控件 调用此函数时 LoadString 失败并出现错误 ERROR RESOU
  • 菜单被裁剪

    我有一个MFC项目 它支持 40 多种语言 我的电脑上有两个显示器 它们都是不同尺寸的显示器和不同的分辨率 如果我将应用程序移至较小的显示器上 则不会显示完整的语言菜单 我知道它会显示滚动条 为什么不是呢 我的菜单是标准菜单 没有什么花哨
  • 在MFC项目中使用多个资源文件

    我在 VS2015 中使用 MFC C 11 并且有一组独立的 GUI 我想在多个项目中使用它们 我知道这可以通过创建一个 rc 文件来实现 该文件可以包含在每个项目的主 rc 文件中 使用多个资源文件 https msdn microso
  • 升级后的 MFC 应用程序看起来仍然很旧

    我有一个用 VC6 编写的 MFC 应用程序 我已将其升级到 VS2015 并且它可以构建并运行 该应用程序是一个主可执行文件 其中包含许多包含对话框的 DLL 然而应用仍然looks就像用 VC6 构建的一样 所有 GUI 组件都没有 W
  • 创建非托管常规 MFC DLL 并从托管 C++ .NET 应用程序调用它时出现问题

    我有几个关于 DLL 的问题 我尝试了很多 但无法获得完整的图片 大多数示例都是用 C 等编写的 使用 VS2005 中的向导 我创建了一个非托管 MFC 常规 DLL 由于剩余代码 必须是 MFC 然后我尝试将其导入 VS2005 管理的
  • 如何向 CMFCPopupMenu 添加图标?

    我想用CMFCPopupMenu用于右键单击期间的弹出菜单 如何添加图标CMFCPopupMenu 这是我在基本 MFC 应用程序中尝试的示例代码 CMFCPopupMenu TestCMFCPopMenu new CMFCPopupMen
  • MFC 是否提供了将文本放入剪贴板的快速方法?

    我们的代码库中的添加到剪贴板代码非常低级 分配全局内存等等 对于简单的情况 我只想将一些纯文本放在剪贴板上 是否有任何例程可以包装所有这些内容 一个例子是 CRichEditCtrl 具有 Copy 和 Cut 方法 可以自动将当前选择放入
  • 禁用/启用 MFC 功能包的功能区按钮

    我正在使用 MFC 功能包 并且功能区栏上有一些按钮 即 CMFCRibbonButton 的实例 问题是我想在某些条件下启用和禁用其中一些 但在运行时 我怎样才能做到这一点 因为没有具体的方法 我听说解决方案是在运行时附加 分离事件处理程
  • 如何通过单击 MainFrame 内的按钮来更改 MFC 视图

    我想通过单击窗口内的按钮来更改呈现的视图像这样 https i stack imgur com 3IA2o png 我的项目设置 我制作了一个没有文档 视图支持的 MFC 项目 SDI 我在设计器中又创建了两个视图并向它们添加了类 新的视图
  • MFC CMenu 工具提示未显示

    我尝试使用类似的东西来设置 CMenu 项的工具提示 如所述here https stackoverflow com questions 2400180 mfc how to add tooltip in cmenu items 但它只是显
  • 错误 C2248: 'CObject::CObject' : 无法访问类 'CObject' afxwin.h 中声明的私有成员

    我试图让班级负责在灰色背景上放置一些文本 Score h pragma once class Score public Score Score void UpdateScore int points void UpdateLives int
  • 如何在 MFC 中创建带圆角的进度控件?

    我需要在 MFC 应用程序中创建一个带圆角的进度条 我尝试过使用 CreateRoundRectRgn 和 SetWindowRgn 的组合 它具有使控件完全消失的效果 我还尝试使用透明的 GIF 覆盖层 该覆盖层将绘制在进度栏的顶部 但我
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • MFC 中位图背景绘制的线程类型

    我有一个 MFC 文档 视图 C 图形应用程序 它将所有绘图都绘制到离屏位图 然后将其复制到 OnDraw 方法中提供的 CDC 指针 在过去的几天里 我一直在寻找将绘图组件放置在单独的工作线程中 这样它就不会停止 GUI 当我执行此操作时
  • MFC CList 支持复制分配吗?

    我在 MSVC 中查找了 CList 定义afxtempl h http www cppdoc com example mfc classdoc MFC AFXTEMPL H html并记录在MSDN http msdn microsoft
  • Windows API 中逻辑坐标和设备坐标之间的混淆

    我一直在研究一个使用两个函数的 Visual Studio C Windows 应用程序项目SetWindowExt and SetViewportExt 我对这两个函数的作用以及为什么它们是必要的感到困惑 搜索这些函数 我得出了逻辑坐标和
  • 使用 MFC 对象初始化 std::map 无法编译

    MFC初学者看这里 我尝试过初始化std map像这样 在CView的标题中 myprogramView h std map
  • 在 MFC 中获取现有但非活动视图

    假设我想访问 MFC MDI 应用程序中文档类中的特定视图 如果它已打开 该视图当前可以是活动的 也可以是非活动的 如果我可以假设视图始终处于活动状态 我可以按照此说明进行操作 http support microsoft com kb 1

随机推荐