使用目錄內容建立菜單
發表于:2007-07-14來源:作者:點擊數:
標簽:
目的:根據目錄內容,建立一個菜單。菜單項為目錄中的文件和子目錄(以彈出方式顯示)。 解決方案 :遍歷子目錄,建立一個文件路徑數組。菜單項的ID是數組的索引。當用戶單擊某個菜單項時,從數組中讀取文件路徑并執行相應的操作。 細節: 首先,我們需要一
目的:根據目錄內容,建立一個菜單。菜單項為目錄中的文件和子目錄(以彈出方式顯示)。
解決方案:遍歷子目錄,建立一個文件路徑數組。菜單項的ID是數組的索引。當用戶單擊某個菜單項時,從數組中讀取文件路徑并執行相應的操作。
細節:
首先,我們需要一個菜單。新建立的菜單將作為此菜單的子菜單。
CMenu* pmenuFavorites=new CMenu;
pmenuFavorites->CreatePopupMenu();
然后讀取目錄,建立菜單
BuildFavoritesMenu(szPath, 0, pmenuFavorites);
最后,將菜單連接到已有菜單上面去
CMenu* pMenu=m_menuPopup.GetSubMenu(0);
pMenu->ModifyMenu(m_iMenuPosition,MF_BYPOSITION|MF_POPUP| MF_STRING,(UINT)(pmenuFavorites->GetSafeHmenu()),_T("動態菜單"));
pmenuFavorites->Detach();
delete pmenuFavorites;
其它的都很簡單,但是建立這個菜單很麻煩
申明一個變量來存文件路徑
CStringArray m_astrFavoriteURLs;
int CWorkBenchDlg::BuildMenu(LPCTSTR pszPath, int nStartPos, CMenu* pMenu)
{
CString strPath(pszPath);//path to start from
CString strPath2;//path to start from,with trailing backslash
CString str;//menu item text
WIN32_FIND_DATA wfd;
HANDLE h;
int nPos;
int nEndPos;
int nNewEndPos;
int nLastDir;
TCHAR buf[INTERNET_MAX_PATH_LENGTH];
CStringArray astrFavorites;
CStringArray astrDirs;
CMenu* pSubMenu;
// make sure there's a trailing backslash
if(strPath[strPath.GetLength() - 1] != _T('\\'))
strPath += _T('\\');
strPath2 = strPath;
strPath += _T("*.*");
// now scan the directory, first for files and then for subdirectories
//make a array of full pathnames.
h = FindFirstFile(strPath, &wfd);
if(h != INVALID_HANDLE_VALUE)
{
nEndPos = nStartPos;
do
{
if((wfd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))==0)
{
str = wfd.cFileName;//file name
lstrcpy(buf,strPath2 + str);//file full pathname
if(str.Right(4) .CompareNoCase(_T(".url"))==0)
{
// an .URL file is formatted just like an .INI file, so we can
// use GetPrivateProfileString() to get the information we w
ant
//fill the buf with URL
::GetPrivateProfileString(_T("Inte
.netShortcut"), _T("URL"),
_T(""), buf, INTERNET_MAX_PATH_LENGTH,
strPath2 + str);
str = str.Left(str.GetLength() - 4);//the name of URL
}
if(str.Right(4) .CompareNoCase( _T(".lnk"))==0)
{
//fill the buf with link target
CGlobal::ResolveShortCut(NULL,strPath2 + str,buf);
str = str.Left(str.GetLength() - 4);
}
//TODO:add other format process here
//這里對.url文件和.lnk文件做了處理,去掉了擴展名。lnk文件的處理參見http://support.microsoft.com/support/kb/articles/Q130/6/98.asp ??梢詫ζ渌袷降奈募M行處理并更改菜單文字。
// scan through the array and perform an insertion sort
// to make sure the menu ends up in alphabetic order
for(nPos = nStartPos ; nPos < nEndPos ; ++nPos)
{
if(str.CompareNoCase(astrFavorites[nPos]) < 0)
break;
}
astrFavorites.InsertAt(nPos, str);
m_astrFavoriteURLs.InsertAt(nPos, buf);
++nEndPos;
}
} while(FindNextFile(h, &wfd));
FindClose(h);
// Now add these items to the menu
for(nPos = nStartPos ; nPos < nEndPos ; ++nPos)
{
pMenu->AppendMenu(MF_STRING | MF_ENABLED, 0xe00 + nPos, astrFavorites[nPos]);
}
// now that we've got all files, check the subdirectories for more
nLastDir = 0;
h = FindFirstFile(strPath, &wfd);
ASSERT(h != INVALID_HANDLE_VALUE);
do
{
if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// ignore the current and parent directory entries
if(lstrcmp(wfd.cFileName, _T(".")) == 0 || lstrcmp(wfd.cFileName, _T("..")) == 0)
continue;
for(nPos = 0 ; nPos < nLastDir ; ++nPos)
{
if(astrDirs[nPos].CompareNoCase(wfd.cFileName) > 0)
break;
}
pSubMenu = new CMenu;
pSubMenu->CreatePopupMenu();
// call this function recursively.
nNewEndPos = BuildFavoritesMenu(strPath2 + wfd.cFileName, nEndPos, pSubMenu);
if(nNewEndPos != nEndPos)
{
// only intert a submenu if there are in fact files in the subdirectory
nEndPos = nNewEndPos;
pMenu->InsertMenu(nPos, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT)pSubMenu->m_hMenu, wfd.cFileName);
pSubMenu->Detach();
astrDirs.InsertAt(nPos, wfd.cFileName);
++nLastDir;
}
delete pSubMenu;
}
} while(FindNextFile(h, &wfd));
FindClose(h);
}
return nEndPos;
}
好了,菜單建立完了。萬事大吉?沒有。還要寫命令處理函數。
afx_msg void OnMenu(UINT nID)
{
ShellExecute(NULL,NULL,m_astrFavoriteURLs[nID-0xe00],NULL,NULL,SW_SHOWDEFAULT);
}
和消息映射
……
//}}AFX_MSG_MAP
ON_COMMAND_RANGE(0xe00, 0xfff, OnMenu)
END_MESSAGE_MAP()
這里我使用了0xe00到0xfff作為命令ID的范圍,所以最多有512個文件菜單項(夠用嗎?不夠用自己寫一個數好了)。因為通常命令的ID大于327xx,所以不會和其他菜單沖突(倒是可能會和按鈕ID沖突,自己注意一下資源ID范圍就OK啦)。
好了,編譯,運行,通過!
唯一的遺憾是沒有文件的圖標。由于我對操作系統不是很熟悉,不知道怎么才能得到文件的圖標并畫到菜單上面去。歡迎各方高人指教!
在
Windows ME和Visual C++6 SP5下
測試通過。
原文轉自:http://www.anti-gravitydesign.com