📄 recentdocumentlistfixed.h
字号:
template <class T, int t_cchItemLen = INTERNET_MAX_PATH_LENGTH>
class CRecentDocumentListFixedBase
{
public:
// Declarations
struct _DocEntry
{
TCHAR szDocName[t_cchItemLen];
bool operator==(const _DocEntry& de) const
{ return (lstrcmpi(szDocName, de.szDocName) == 0); }
};
enum
{
m_nMaxEntries_Min = 2,
m_nMaxEntries_Max = ID_FILE_MRU_LAST - ID_FILE_MRU_FIRST + 1,
m_cchMaxItemLen_Min = 6,
m_cchMaxItemLen_Max = t_cchItemLen
};
// Data members
CSimpleArray<_DocEntry> m_arrDocs;
int m_nMaxEntries; // default is 4
HMENU m_hMenu;
TCHAR m_szNoEntries[t_cchItemLen];
int m_cchMaxItemLen;
// Constructor
CRecentDocumentListFixedBase() : m_hMenu(NULL), m_nMaxEntries(4), m_cchMaxItemLen(100)
{
ATLASSERT(t_cchItemLen > m_cchMaxItemLen_Min);
}
// Attributes
HMENU GetMenuHandle() const
{
return m_hMenu;
}
void SetMenuHandle(HMENU hMenu)
{
ATLASSERT(hMenu == NULL || ::IsMenu(hMenu));
m_hMenu = hMenu;
if(m_hMenu == NULL || (::GetMenuString(m_hMenu, ID_FILE_MRU_FIRST, m_szNoEntries, t_cchItemLen, MF_BYCOMMAND) == 0))
lstrcpy(m_szNoEntries, _T("(empty)"));
}
int GetMaxEntries() const
{
return m_nMaxEntries;
}
void SetMaxEntries(int nMaxEntries)
{
ATLASSERT(nMaxEntries > m_nMaxEntries_Min && nMaxEntries < m_nMaxEntries_Max);
if(nMaxEntries < m_nMaxEntries_Min)
nMaxEntries = m_nMaxEntries_Min;
else if(nMaxEntries > m_nMaxEntries_Max)
nMaxEntries = m_nMaxEntries_Max;
m_nMaxEntries = nMaxEntries;
}
int GetMaxItemLength() const
{
return m_cchMaxItemLen;
}
void SetMaxItemLength(int cchMaxLen)
{
ATLASSERT((cchMaxLen >= m_cchMaxItemLen_Min && cchMaxLen <= m_cchMaxItemLen_Max) || cchMaxLen == -1);
if(cchMaxLen != -1)
{
if(cchMaxLen < m_cchMaxItemLen_Min)
cchMaxLen = m_cchMaxItemLen_Min;
else if(cchMaxLen > m_cchMaxItemLen_Max)
cchMaxLen = m_cchMaxItemLen_Max;
}
m_cchMaxItemLen = cchMaxLen;
T* pT = static_cast<T*>(this);
pT->UpdateMenu();
}
// Operations
BOOL AddToList(LPCTSTR lpstrDocName)
{
_DocEntry de;
if(lstrcpy(de.szDocName, lpstrDocName) == NULL)
return FALSE;
for(int i = 0; i < m_arrDocs.GetSize(); i++)
{
if(lstrcmpi(m_arrDocs[i].szDocName, lpstrDocName) == 0)
{
m_arrDocs.RemoveAt(i);
break;
}
}
if(m_arrDocs.GetSize() == m_nMaxEntries)
m_arrDocs.RemoveAt(0);
BOOL bRet = m_arrDocs.Add(de);
if(bRet)
{
T* pT = static_cast<T*>(this);
bRet = pT->UpdateMenu();
}
return bRet;
}
BOOL GetFromList(int nItemID, LPTSTR lpstrDocName)
{
int nIndex = m_arrDocs.GetSize() - (nItemID - ID_FILE_MRU_FIRST) - 1;
if(nIndex < 0 || nIndex >= m_arrDocs.GetSize())
return FALSE;
return (lstrcpy(lpstrDocName, m_arrDocs[nIndex].szDocName) != NULL);
}
BOOL RemoveFromList(int nItemID)
{
int nIndex = m_arrDocs.GetSize() - (nItemID - ID_FILE_MRU_FIRST) - 1;
BOOL bRet = m_arrDocs.RemoveAt(nIndex);
if(bRet)
{
T* pT = static_cast<T*>(this);
bRet = pT->UpdateMenu();
}
return bRet;
}
BOOL MoveToTop(int nItemID)
{
int nIndex = m_arrDocs.GetSize() - 1 - (nItemID - ID_FILE_MRU_FIRST);
if(nIndex < 0 || nIndex >= m_arrDocs.GetSize())
return FALSE;
_DocEntry de;
de = m_arrDocs[nIndex];
m_arrDocs.RemoveAt(nIndex);
BOOL bRet = m_arrDocs.Add(de);
if(bRet)
{
T* pT = static_cast<T*>(this);
bRet = pT->UpdateMenu();
}
return bRet;
}
BOOL ReadFromIniFile()
{
CIniSection pr;
pr.Open(_szIniFileName, _T("Recent Document List"));
DWORD dwRet;
LONG lRet = pr.QueryValue(dwRet, _T("DocumentCount"));
if(lRet == ERROR_SUCCESS || dwRet > 0 && dwRet < (ID_FILE_MRU_LAST - ID_FILE_MRU_FIRST + 1))
m_nMaxEntries = dwRet;
m_arrDocs.RemoveAll();
TCHAR szRetString[t_cchItemLen];
_DocEntry de;
for(int nItem = m_nMaxEntries; nItem > 0; nItem--)
{
TCHAR szBuff[11];
wsprintf(szBuff, _T("Document%i"), nItem);
DWORD dwCount = t_cchItemLen * sizeof(TCHAR);
lRet = pr.QueryValue(szRetString, szBuff, &dwCount);
if(lRet == ERROR_SUCCESS && (lstrcpy(de.szDocName, szRetString) != NULL))
m_arrDocs.Add(de);
}
pr.Close();
T* pT = static_cast<T*>(this);
return pT->UpdateMenu();
}
BOOL WriteToIniFile()
{
CIniSection pr;
pr.Open(_szIniFileName, _T("Recent Document List"));
LONG lRet = pr.SetValue(m_nMaxEntries, _T("DocumentCount"));
ATLASSERT(lRet == ERROR_SUCCESS);
// set new values
int nItem;
for(nItem = m_arrDocs.GetSize(); nItem > 0; nItem--)
{
TCHAR szBuff[11];
wsprintf(szBuff, _T("Document%i"), nItem);
TCHAR szDocName[t_cchItemLen];
GetFromList(ID_FILE_MRU_FIRST + nItem - 1, szDocName);
lRet = pr.SetValue(szDocName, szBuff);
ATLASSERT(lRet == ERROR_SUCCESS);
}
// delete unused keys
for(nItem = m_arrDocs.GetSize() + 1; nItem < (ID_FILE_MRU_LAST - ID_FILE_MRU_FIRST + 1); nItem++)
{
TCHAR szBuff[11];
wsprintf(szBuff, _T("Document%i"), nItem);
pr.DeleteValue(szBuff);
}
pr.Close();
return TRUE;
}
// Implementation
BOOL UpdateMenu()
{
if(m_hMenu == NULL)
return FALSE;
ATLASSERT(::IsMenu(m_hMenu));
int nItems = ::GetMenuItemCount(m_hMenu);
int nInsertPoint;
for(nInsertPoint = 0; nInsertPoint < nItems; nInsertPoint++)
{
MENUITEMINFO mi;
mi.cbSize = sizeof(MENUITEMINFO);
mi.fMask = MIIM_ID;
::GetMenuItemInfo(m_hMenu, nInsertPoint, TRUE, &mi);
if (mi.wID == ID_FILE_MRU_FIRST)
break;
}
ATLASSERT(nInsertPoint < nItems && "You need a menu item with an ID = ID_FILE_MRU_FIRST");
int nItem;
for(nItem = ID_FILE_MRU_FIRST; nItem < ID_FILE_MRU_FIRST + m_nMaxEntries; nItem++)
{
// keep the first one as an insertion point
if (nItem != ID_FILE_MRU_FIRST)
::DeleteMenu(m_hMenu, nItem, MF_BYCOMMAND);
}
CString strOut;
int nSize = m_arrDocs.GetSize();
nItem = 0;
if(nSize > 0)
{
for(nItem = 0; nItem < nSize; nItem++)
{
if(m_cchMaxItemLen == -1)
{
CString strIn(m_arrDocs[nSize - 1 - nItem].szDocName);
strIn.Replace(_T("&"), _T("&&"));
int nLen = strIn.GetLength();
wsprintf(strOut.GetBufferSetLength(nLen + 8), _T("&%i %s"), nItem + 1, strIn);
}
else
{
CString strIn(m_arrDocs[nSize - 1 - nItem].szDocName);
TCHAR szBuff[t_cchItemLen];
T* pT = static_cast<T*>(this);
pT; // avoid level 4 warning
bool bRet = pT->CompactDocumentName(szBuff, strIn, m_cchMaxItemLen);
strIn = szBuff;
strIn.Replace(_T("&"), _T("&&"));
bRet; // avoid level 4 warning
ATLASSERT(bRet);
int nLen = strIn.GetLength();
wsprintf(strOut.GetBufferSetLength(nLen + 8), _T("&%i %s"), nItem + 1, strIn);
}
strOut.ReleaseBuffer();
::InsertMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION | MF_STRING, ID_FILE_MRU_FIRST + nItem, strOut);
}
}
else // empty
{
::InsertMenu(m_hMenu, nInsertPoint, MF_BYPOSITION | MF_STRING, ID_FILE_MRU_FIRST, m_szNoEntries);
::EnableMenuItem(m_hMenu, ID_FILE_MRU_FIRST, MF_GRAYED);
nItem++;
}
::DeleteMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION);
return TRUE;
}
// Overrideable
// override to provide a different method of compacting document names
static bool CompactDocumentName(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen)
{
return AtlCompactPathFixed(lpstrOut, lpstrIn, cchLen);
}
};
class CRecentDocumentListFixed : public CRecentDocumentListFixedBase<CRecentDocumentListFixed>
{
public:
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -