用ini文件实现最近文件MRU
作者:风林
作者网站:
作者邮箱:
VC++的MFC对最近文件进行了包装,它使用户无需编写任何代码就可实现最近文件菜单。但这种方法也有缺陷:
①用户程序必须使用文档、视图结构,只能利用它提供的文档打开和保存文件,如果你使用自己编写的函数打开和保存文件,绕过了它的文档,则最近文件将无法使用。
②这种最近文件保存在注册表中,不易清除,容易形成注册表中垃圾,也没有提供用户清除最近文件的权利,不利于用户隐私的保护。
用ini文件实现最近文件可以解决上述问题,而且用编程控制MRU更灵活,可以提供更多功能。
一、ini文件的结构和访问方法:
ini文件是纯文本文件,我们可以编程访问它,也可用任一种文本编辑软件打开它。如某RAV.ini文件打开后如下:
[INSTALLED] FWBASE2K=1 FWBASENT=1 ToInstall= CodePage=936 Closed= [Setup] ShowBgBmp=0 [Skin] Current=1 Path=D:\Program Files\Rising\Rav\Skin\Skin1\Skin.xml [RAVMON] MONSTATUS=255 |
其中[]括起的称为段,段下面的各部分称为项,访问时用(段名,项名)可访问指定项的值。我们可利用API函数直接读写ini文件。
㈠ 读ini文件中的项值:
① 读整数值:
UINT GetPrivateProfileInt(LPCTSTR lpAppName,LPCTSTR lpKeyName,INT nDefault,LPCSTR lpFileName); |
lpAppName为段名,lpKeyName为项名,nDefault为找不到该项时返回的默认值,lpFileName为ini文件名
返回值:若成功,返回指定项后的整数值,若该项不存在,返回nDefault的值
如:读取RAV.ini文件中[INSTALLED]段的FWBASE2K项的值
int FwbBase2K = ::GetPrivateProfileInt("INSTALLED", "FWBASE2K", 0, "RAV.ini"); |
② 读字符串:
DWORD GetPrivateProfileString(LPCTSTR lpAppName,LPCTSTR lpKeyName,LPCTSTR lpDefault,LPTSTR lpReturnedString,DWORD nSize,LPCTSTR lpFileName); |
lpAppName为段名,lpKeyName为项名,lpDefault为找不到该项时返回的默认值,lpReturnedString指向接收结果的字符串缓冲区,nSize为缓冲区长度,lpFileName为ini文件名
执行结果:若成功,lpReturnedString指示的串中为读出的项值,若该项不存在,lpReturnedString中为lpDefault的值
如:读取RAV.ini文件中[Skin]段的Path项的值
CString PathName; ::GetPrivateProfileString("Skin", "Path", "", PathName.GetBuffer(MAX_PATH), MAX_PATH, "RAV.ini"); PathName.ReleaseBuffer(); |
㈡ 把数据写入ini文件:
写入时没有写入整数的函数,只有写入字符串的函数
BOOL WritePrivateProfileString(LPCTSTR lpAppName,LPCTSTR lpKeyName,LPCTSTR lpString,LPCTSTR lpFileName); |
lpAppName为段名,lpKeyName为项名,lpString为写入的字符串,lpFileName为ini文件名
返回值:若成功,返回true,否则返回false
若写入时,该ini文件不存在,则本函数会建立这个文件。
如:把RAV.ini文件中[INSTALLED]段的FWBASE2K项的值设置为2,由于这是整数,应先转换为字符串后再写入
CString str; str.Format("%d", 2); ::WritePrivateProfileString( "INSTALLED", "FWBASE2K", str, "RAV.ini" ); |
注意:实际应用中,在上述例子里的ini文件名应采用绝对路径名,否则可能找不到要读写的ini文件。
二、用ini文件实现最近文件MRU:
我设计了一个ini文件MruFile.ini保存最近文件,它的结构如下:
[Mru File] FileNum=当前文件数 1=路径名1 2=路径名2 3=路径名3 4=路径名4 |
这里只设计了4个最近文件,应用时可根据需要添加。
类CMruFile是自定义的一个MRU文件管理类,在它的头文件中有如下定义:
#define MAXNUM 4 //最大MRU文件数 CString m_IniFileName; //ini文件名 |
在MruFile.cpp中有如下函数:
//读取ini文件中的最近文件 void CMruFile::ReadMru() { m_CurNum = ::GetPrivateProfileInt("Mru File", "FileNum", 0, m_IniFileName); //读取当前文件数 CString no; for( int i=0; i no.Format( "%d", i+1 ); //求项名 ::GetPrivateProfileString("Mru File", no, "", m_PathName[i].GetBuffer(MAX_PATH), MAX_PATH, m_IniFileName); //读取路径名 m_PathName[i].ReleaseBuffer(); } SetMruMenu(); //修改MRU菜单 } |
//最近文件写入ini文件 void CMruFile::WriteMru() { CString no; no.Format( "%d", m_CurNum ); ::WritePrivateProfileString( "Mru File", "FileNum", no, m_IniFileName ); //写当前文件数 for( int i=0; i no.Format( "%d", i+1 ); ::WritePrivateProfileString("Mru File", no, m_PathName[i], m_IniFileName); //写路径名 } } |
//添加最近文件(nPathName-添加的文件路径名) SetMruMenu(); //修改MRU菜单 |
//清除最近文件 void CMruFile::ClearMru() { m_CurNum = 0; for( int i=0; i SetMruMenu(); WriteMru(); } |
//修改最近文件菜单 void CMruFile::SetMruMenu() { CMenu *pMenu = AfxGetMainWnd()->GetMenu(); //主菜单指针 CMenu *pFileMenu = pMenu->GetSubMenu(0); //“文件”菜单指针 CMenu *pMruMenu = pFileMenu->GetSubMenu(5); //“最近文件”菜单指针(5为最近文件菜单项在文件菜单中的位置) pMruMenu->RemoveMenu( ID_MRU1, MF_BYCOMMAND ); //删除各菜单项 pMruMenu->RemoveMenu( ID_MRU2, MF_BYCOMMAND ); pMruMenu->RemoveMenu( ID_MRU3, MF_BYCOMMAND ); pMruMenu->RemoveMenu( ID_MRU4, MF_BYCOMMAND ); if( m_CurNum>0 ) //重新插入各菜单项 pMruMenu->InsertMenu( ID_MRU_CLR, MF_BYCOMMAND, ID_MRU1, m_PathName[0] ); if( m_CurNum>1 ) pMruMenu->InsertMenu( ID_MRU_CLR, MF_BYCOMMAND, ID_MRU2, m_PathName[1] ); if( m_CurNum>2 ) pMruMenu->InsertMenu( ID_MRU_CLR, MF_BYCOMMAND, ID_MRU3, m_PathName[2] ); if( m_CurNum>3 ) pMruMenu->InsertMenu( ID_MRU_CLR, MF_BYCOMMAND, ID_MRU4, m_PathName[3] ); } |
这样一个用ini文件管理的最近文件类就做好了。使用时,需要根据程序所在路径设置ini文件路径名m_IniFileName,之后调用该类中的函数管理最近文件。
详细用法可参考示例程序。
文章来源于领测软件测试网 https://www.ltesting.net/