Hello, I am trying to make a submenu to display at runtime a list of unknown number of files. The files are contained in a directory specified at compile time. I want this to look like the Windows Start>>Documents menu where the user can pick the file off the menu and have it open. How can I do this using MFC?
I'll worry about that later, right now I need to see if it can be done and how. We're still in the first phases of the project. But for the sake of argument, lets say I limit them to 20 files.
start with the CMenu class and work from there. When the user selects the main menu item, for example File, then generate the list of files and dynamically create the new menu with the CMenu object. You'll have to read MSDN about that class and search MSDN downloads or the MSDN CD that came with your compiler for examples. You might also look at www.codeproject.com for examples.
I think the difficult part for me is I don't know how to get a directory list. I have tried using the CListBox:ir() and the CComboBox:ir thinking that once I get the directory listing I can access them one at a time and populate a menu. Another thing holding me back is CMenu needs to have a controller ID and I don't know how to create these dynamically. If I simply plug in numbers, what's to stop Class Wizard from creating dialogs with the same number? I am also dealing with the terminology; do I create a sub menu, a child menu or a pop up menu?
Thanks for pointing me to the codeproject web page. That could be useful.
Originally posted by xucaen
. Another thing holding me back is CMenu needs to have a controller ID and I don't know how to create these dynamically. If I simply plug in numbers, what's to stop Class Wizard from creating dialogs with the same number? I am also dealing with the terminology; do I create a sub menu, a child menu or a pop up menu?
If all you want to do is like a RecentFile List in the File menu, then here is another idea:
// This adds the pathname c:\temp\test.doc to the top of
// the most recently used (MRU) list in the File menu.
AfxGetApp()->AddToRecentFileList("c:\\temp\\test.doc");
Thank you so much for the CreateFileList() function. This is exactly waht I need to get my file list.
I didn't know about the AfxGetApp()->AddToRecentFileList(), this will be useful too as the clients will probably want this.
I'm attaching a file that show an example of what I hope to do with my menu. Once getting a file list I want to populate a menu.
This is not a complete solution but should get you going in the right direction. First create an event handler as shown below because that is what gets called when someone clicks the Transactions menu item. Then you will need to modity the menu to add additional menu items in the "External Lists" popup-menu. I think the id's can be any arbitrary number because they are only for your use and are only good for the menu. No problem if they already duplicate a number in the resource file.
Code:
void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
CMDIFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
// TODO: Add your message handler code here
CString str;
int nMenuCount = pPopupMenu->GetMenuItemCount();
for(int i = 0; i < nMenuCount; i++)
{
pPopupMenu->GetMenuString(i, str, MF_BYPOSITION);
if(str == "External Lists")
break;
}
}
You have been so helpful! Thank you! I am now able to dynamically populate a popup menu with a file list.
Now all I need to figure out is how to get the item selected. I'm searching thru MSDN for a function or some way of capturing which item is selected from the menu. I'm going to experiment with OnCommand() to see if I can get the item selected.
Thanks again!!
Jim
Last edited by xucaen; January 24th, 2003 at 12:27 PM.
I am using the function you showed me to create my file list. It works beautifully! I am noticing, however, that any new files added to the directory while my app is running never show up in the list even though I am calling this function every time the menu is selected. Is there a way to refresh before getting the file list?
Here is the function I am using;
#define MAX_FILE_LIST 100
.
.
.
void CreateFileList(string dirname, vector<string>* list)
{
WIN32_FIND_DATA data;
HANDLE hFile = FindFirstFile(dirname.c_str(), &data);
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
if(!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
// This is not a directory, so must be a file
list->push_back(data.cFileName);
}
} while( list->size() < MAX_FILE_LIST && FindNextFile(hFile, &data) );
FindClose(hFile);
}
}
Thanks!!
Jim
Last edited by xucaen; January 27th, 2003 at 04:06 PM.
I suspect you have something else wrong. I wrote a small test program and did not see that behavior. To run this test you first need to create the directory c:\tmp, unless you already have one. The first time you see "Press any key...", copy some more files into the directory before pressing a key.
Maybe your list is filling up with file names?
Code:
#include "stdafx.h"
#include <windows.h>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
#define MAX_FILE_LIST 100
void CreateFileList(string& dirname, vector<string>& list)
{
WIN32_FIND_DATA data;
HANDLE hFile = FindFirstFile(dirname.c_str(), &data);
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
if(!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
// This is not a directory, so must be a file
list.push_back(data.cFileName);
}
} while( list.size() < MAX_FILE_LIST && FindNextFile(hFile, &data) );
FindClose(hFile);
}
}
void ShowList(vector<string>& list)
{
vector<string>::iterator it;
for(it = list.begin(); it < list.end(); it++)
{
cout << *it << endl;
}
}
int main(int argc, char* argv[])
{
vector<string> lst;
string name = "c:\\tmp\\*.*";
CreateFileList(name, lst);
ShowList(lst);
cout << "Press any key to continue.";
cin.ignore();
cout << endl;
CreateFileList(name, lst);
ShowList(lst);
cout << "Press any key to continue.";
cin.ignore();
return 0;
}
Your example does work. Interesting... It must have something to do with the menu I'm populating. Maybe something in Windows is keeping it from refreshing, whereas a DOS prompt automatically refreshes or it accesses the directory differently? I'll keep working on it. I'll post what I find.
Well, I found out why my file list isn't being refreshed; OnInitMenuPopup() is only called once, so CreateFileList() only gets called once. So now I need a way to either call OnInitMenuPopup() everytime the menu is accessed or find a different way to populate my menu.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.