zoukankan      html  css  js  c++  java
  • MFC框架中对最近文件列表的支持

    http://www.fmdstudio.net/articles/mfcsrc/01912235946.htm

    http://topic.csdn.net/t/20010917/21/291003.html

    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;


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/carl2380/archive/2010/07/07/5717466.aspx

  • 相关阅读:
    “数学题”——传钱
    kafka笔记——入门介绍
    SpringBoot集成Dubbo+Zookeeper
    MySql基本语法
    动态规划
    总结
    Java反射
    软件清单
    Java IO操作
    Spring Boot AOP的使用
  • 原文地址:https://www.cnblogs.com/carl2380/p/1995012.html
Copyright © 2011-2022 走看看