您当前的位置:首页 > 计算机 > 编程开发 > VC/VC++

MFC最近文件列表的问题和改进方法

时间:08-26来源:作者:点击数:

在改进cnbook时发现MFC的一个小问题。MFC框架支持最近文件列表。我们不用写一行代码就可以实现文件列表功能。

在资源文件的菜单资源中,ID_FILE_MRU_FILE1表示最近文件列表:

		MENUITEM "最近文件",                 ID_FILE_MRU_FILE1,GRAYED
		MENUITEM SEPARATOR
		MENUITEM "退出(&X)",                       ID_APP_EXIT

MFC会在这个位置插入文件列表。默认情况下,最近文件列表是文件菜单的第一级菜单项。在最近文件比较多时,会造成文件菜单过长,不美观。所以,有时我们希望把最近文件列表放在子菜单项中,例如:

		POPUP "最近文件(&F)"
		BEGIN
			MENUITEM "最近文件",                 ID_FILE_MRU_FILE1,GRAYED
		END
		MENUITEM SEPARATOR
		MENUITEM "退出(&X)",                       ID_APP_EXIT

但运行结果却不是我们所期待的:

通过查看MFC的源代码,我们可以找到负责文件列表显示的函数CRecentFileList::UpdateMenu。大概看一下这个函数,就会发现这个函数没有考虑最近文件列表放在子菜单项中的情况。它总是在前一个菜单项的后面插入最近文件的菜单项,即使前一个菜单项在上一级。这就造成将ID_FILE_MRU_FILE1作为子菜单的第一项时会发生错误。

Todd C. Gleason在1998年使用VC5时就发现了这个问题并提出了解决办法。 不过,在VC8中这个问题依然存在。Todd C. Gleason的解决办法就是:

  • 写一个CRecentFileList的派生类(VIRecentFileList),重载函数UpdateMenu,增加对子菜单项的支持。只要将文件VIRecentFileList.cpp和VIRecentFileList.h加入工程就可以了。
  • 在App类中重载LoadStdProfileSettings函数,使用VIRecentFileList类。在.h中增加:
    protected:
    	void LoadStdProfileSettings(UINT nMaxMRU);
    

    在.c中首先包含VIRecentFileList.h:

    #include "VIRecentFileList.h"
    

    然后实现LoadStdProfileSettings函数:

    static const TCHAR _afxFileSection[] = _T("Recent File List");
    static const TCHAR _afxFileEntry[] = _T("File%d");
    static const TCHAR _afxPreviewSection[] = _T("Settings");
    static const TCHAR _afxPreviewEntry[] = _T("PreviewPages");
    
    void CMruApp::LoadStdProfileSettings(UINT nMaxMRU)
    {
     ASSERT_VALID(this);
     ASSERT(m_pRecentFileList == NULL);
    
     if (nMaxMRU != 0)
     {
      // create file MRU since nMaxMRU not zero
    
      // Here's the important part--overriding CRecentFileList
      m_pRecentFileList = new VIRecentFileList(0, _afxFileSection, _afxFileEntry, nMaxMRU);
    
      m_pRecentFileList->ReadList();
     }
     // 0 by default means not set
     m_nNumPreviewPages = GetProfileInt(_afxPreviewSection, _afxPreviewEntry, 0);
    }
    

好了,看看结果是不是我们想要的:

Todd的代码是用于VC5环境的,在VC6或VC8使用要做一些细微改动。另外在清空文件列表后:

void CTextProApp::OnClrMru()
{
	int i;
	for (i = 0; i < m_pRecentFileList->m_nSize; i++) {
		m_pRecentFileList->m_arrNames[i].Empty();
	}
}

MFC和Todd的UpdateMenu函数都不能正确显示。我也做了些修改。 完整的例子可以从这里下载。

推荐内容
相关内容
栏目更新
栏目热门