Click here to Skip to main content
16,012,025 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi guys
I got a problem with the code
I really have tried everything but in vain (I'm just a beginner in C++)
The task is to display all files in selected directory and all subdirectories as well.
I want to display all data in listview.(I have created it) But the code I found do it using _tprintf/(Looks very easy to remake the code,but I dont know how to change the parameters of function that using in Class constructor)...Give me an advice please.
Look in code(written by some other man):
Main function where he calls the FileEnumerator function:
#include "stdafx.h"
#include "FileEnumerator.h"

bool FileEnumeratorCallback(LPCTSTR lpszItemName, LPCTSTR lpszItemDir, LPWIN32_FIND_DATA lpItemFindData, LPVOID lpUserData)
{
	if(lpItemFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		_tprintf(_T("[%s]\n"), CString(lpszItemDir) +lpszItemName);	// use [] for directories
	else
		_tprintf(_T("%s\n"), CString(lpszItemDir) + lpszItemName);

	return true;	// return true to continue the enumeration. False to stop.
}

int _tmain(int argc, _TCHAR* argv[])
{		
	if(argc !=3)
		exit(_ftprintf(stderr, _T("\nUsage: %s <search dir=""> <search pattern="">\n\nExample:\n    %s   c:\\   *.cpp\n"), argv[0],argv[0]));

	// Invoke the enumerator class. 
	// The FileEnumeratorCallback function will be called for each file found that matches the search pattern.
	CFileEnumerator _EnumObj(FileEnumeratorCallback, argv[1], argv[2]);

	_EnumObj.RecurseSubDirectories() = true;	// Do not search sub-directories
	_EnumObj.ReportMatchingDirsAlso() = false;	// Report matching directories also while searching for files
	_EnumObj.IgnoreDots() = true;				// Report Dots also while recursing sub-directories
	
	_tprintf(_T("\n\nFile Listing for %s with pattern %s\n\tRecursion:[%s]\n\tReportMatchingDirs:[%s]\n\n"),
			argv[1],argv[2],_EnumObj.RecurseSubDirectories()?_T("ON"):_T("OFF"), _EnumObj.ReportMatchingDirsAlso()?_T("ON"):_T("OFF"));

	if(!_EnumObj.EnumerateFiles())	// List the files that match the search pattern
	{
		_tprintf(_T("\nEnumeration was stopped by user !!\n"));
	}

	_tprintf(_T("\n\nAll directories under %s \n\n"),argv[1]);

	if(!_EnumObj.ListAllDirectories())	// Lists all directories under the search directory (no pattern applied)
	{
		_tprintf(_T("\nEnumeration was stopped by user !!\n"));
	}

	return 0;
}

And the code proper:
#ifndef __FILE_ENUMERATOR_H_EEF8FBA5_B0F1_4682_9614_2027C16002F4
#define __FILE_ENUMERATOR_H_EEF8FBA5_B0F1_4682_9614_2027C16002F4

#include "PathHelper.h"

typedef bool (*PFN_EnumeratorCallback)(LPCTSTR lpszItemName, LPCTSTR lpszItemDir, LPWIN32_FIND_DATA lpszItemFindData, LPVOID lpUserData);

// Recursively enumerates the given directory for the specified file types. Invokes the supplied callback for each file found.
// Can be used to enumerate sub-directories too.
// (Does not support modifying the search properties while enumeration is in progress).
class CFileEnumerator
{
	CString	m_strSearchDir;		// The search directory.

	CString	m_strFileToSearch;	// Pattern of the file that should be searched for. Valid only for file enumeration

	bool	m_bRecurseSubDirectories;	// Indicates if sub-directories should be recursed during an enumeration

	bool	m_bIgnoreDots;	// Valid only for directory listing.

	bool	m_bReportMatchingDirsAlso;	// Valid only for File Listing. Indicates if the directories should be included in the reporting while searching for files

	PFN_EnumeratorCallback m_pfnEnumCallback;	// Callback function for the enumeration

	inline static bool EnumCallback(LPCTSTR, LPCTSTR, LPWIN32_FIND_DATA, LPVOID)
	{
		return false;	// returning false stops the enumeration at that point
	}
public:

	CFileEnumerator(PFN_EnumeratorCallback pfnEnumCallback = CFileEnumerator::EnumCallback,	// Callback function for the enumeration
					LPCTSTR lpszSearchDir = _T("."),	// Should be a directory path (excluding the file name and wild cards) eg. "c:\\" or "C:\\Dir1"
					LPCTSTR lpszFileToSearch = _T("*.*"),// Should be a file name or wild card eg. "*.*"
					bool bRecurseSubDirectories = true,// Should the sub-directories be recursed?
					bool bReportMatchingDirsAlso = true,// Should the matching directories also be reported while searching for files? - Valid only for file enumeration
					bool bIgnoreDots = true	// Should . and .. be informed ?? - Valid Only when Listing Directories
					)
	{
		m_pfnEnumCallback = pfnEnumCallback;
		m_strSearchDir = lpszSearchDir;
		m_strFileToSearch = lpszFileToSearch;
		m_bRecurseSubDirectories = bRecurseSubDirectories;
		m_bReportMatchingDirsAlso = bReportMatchingDirsAlso;
		m_bIgnoreDots = bIgnoreDots;
	}

	~CFileEnumerator(void)
	{
	}

	PFN_EnumeratorCallback& FileEnumeratorCallback()
	{
		return m_pfnEnumCallback;
	}

	bool& IgnoreDots()				{	return m_bIgnoreDots;	}	// Indicates if Dots will be processed for the Callback (only in sub-directory listing mode)

	bool& RecurseSubDirectories()	{	return m_bRecurseSubDirectories;	}	// Indicates if sub-directories will be recursively searched or not

	CString& FileToSearch()			{	return m_strFileToSearch;	}	// The Files being searched for

	LPCTSTR FileToSearch() const	{	return m_strFileToSearch;	}	// The Files being searched for

	CString& SearchDir()			{	return m_strSearchDir;	}	// The directory being searched

	LPCTSTR SearchDir() const		{	return m_strSearchDir;	}	// The directory being searched

	bool& ReportMatchingDirsAlso()	{	return m_bReportMatchingDirsAlso;	}	// Indicates if Directories should also be reported while searching for files if the pattern matches

	HANDLE FindFirstSubDir(LPCTSTR lpszDir, LPWIN32_FIND_DATA pFindData) const
	{
        HANDLE hFind = FindFirstFile(CString(lpszDir) + _T("*.*"), pFindData);
		if(hFind == INVALID_HANDLE_VALUE)	return hFind;

		do
		{
			if(PathIsDots(pFindData->cFileName))
			{
				if(m_bIgnoreDots == false)
					return hFind;
				continue;
			}

			if(!(pFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue;

			return hFind;

		}while(FindNextFile(hFind, pFindData));

		return INVALID_HANDLE_VALUE;
	}

	BOOL FindNextSubDir(HANDLE hFind, LPWIN32_FIND_DATA pFindData) const
	{
		while(FindNextFile(hFind, pFindData))
		{
			if(PathIsDots(pFindData->cFileName))	//!_tcscmp(pFindData->cFileName, _T(".")) || !_tcscmp(pFindData->cFileName, _T("..")))
			{
				if(m_bIgnoreDots == false)
					return true;
				continue;
			}

			if(!(pFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue;

			return true;
		}
		return false;
	}

	//
	// ListAllDirectories: Enumerates all directories in the SearchDir folder; Doesnt take FileToSearch() into account;
	// The optional lpUserData parameter would be sent back to the caller in the EnumeratorCallback.
	// (Does not support modifying the search properties while listing is in progress)
	// Returns true if search is complete. False if the callback requested to stop the search.
	bool ListAllDirectories(LPVOID lpUserData = NULL) const
	{
		WIN32_FIND_DATA ffData;

		CString strSearchDir((LPCTSTR)SearchDir());
		PathAddBackSlash(strSearchDir);

		HANDLE hFind = FindFirstSubDir(strSearchDir, &ffData);
		if(hFind == INVALID_HANDLE_VALUE) return true;

		bool bContinue = true;

		do
		{
			if(false == (*m_pfnEnumCallback)(ffData.cFileName, strSearchDir, &ffData, lpUserData))
				return false;

			if(m_bRecurseSubDirectories)
			{
				//if(PathIsDots(ffData.cFileName)) continue;

				CFileEnumerator feDir(m_pfnEnumCallback,
									strSearchDir + ffData.cFileName, 
									_T("*.*"), 
									m_bRecurseSubDirectories,
									m_bReportMatchingDirsAlso,
									m_bIgnoreDots);
				bContinue = feDir.ListAllDirectories(lpUserData);
			}
		}while(bContinue && FindNextSubDir(hFind, &ffData));

		FindClose(hFind);

		return true;
	}

	//
	// EnumerateFiles: Enumerates all files of type FileToSearch() in the SearchDir() folder;
	// Subdirectories will be considered for enumeration based on the RecurseSubDirectories() property.
	// The optional lpUserData parameter would be sent back to the caller in the EnumeratorCallback.
	// (Does not support modifying the search properties while enumeration is in progress)
	// Returns true if search is complete. False if the callback requested to stop the search.
	bool EnumerateFiles(LPVOID lpUserData = NULL) const
	{
		bool bContinue = true;

		CString strSearchDir((LPCTSTR)SearchDir());

		PathAddBackSlash(strSearchDir);

		WIN32_FIND_DATA ffData;

		HANDLE hFind = FindFirstFile(strSearchDir + (LPCTSTR)FileToSearch(), &ffData);
		if(hFind == INVALID_HANDLE_VALUE)
		{
			if(m_bRecurseSubDirectories)	// If this dir doesn't contain the wild card files, check in the subdirs
			{
				CFileEnumerator feDir(EnumCallback, 
										strSearchDir, 
										_T("*.*"), 
										m_bRecurseSubDirectories,
										m_bReportMatchingDirsAlso,
										true);	// important to ignore the dots for subdir enumeration
				hFind = feDir.FindFirstSubDir(strSearchDir, &ffData);
				if(hFind == INVALID_HANDLE_VALUE)	return true;
				do
				{
					bContinue = CFileEnumerator( m_pfnEnumCallback, 
												strSearchDir + ffData.cFileName,
												FileToSearch(),
												m_bRecurseSubDirectories,
												m_bReportMatchingDirsAlso,
												m_bIgnoreDots).EnumerateFiles(lpUserData);
				}while(bContinue && feDir.FindNextSubDir(hFind, &ffData));

				FindClose(hFind);

				return bContinue;
			}
			else
				return true;
		}

		do		// this directory contains some files that match the wild card..
		{
			if(PathIsDots(ffData.cFileName))
			{
				if(m_bIgnoreDots == false)
					bContinue = (*m_pfnEnumCallback)(ffData.cFileName, strSearchDir, &ffData, lpUserData);
				continue;
			}

			if((ffData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
			{
				if(m_bReportMatchingDirsAlso)	// Do we need to report the matching directories too?
					bContinue = (*m_pfnEnumCallback)(ffData.cFileName, strSearchDir, &ffData, lpUserData);
			}
			else
			{
				bContinue = (*m_pfnEnumCallback)(ffData.cFileName, strSearchDir, &ffData, lpUserData);
			}

		}while(bContinue && FindNextFile(hFind, &ffData));

		FindClose(hFind);

		if(bContinue && m_bRecurseSubDirectories) //List the files from sub-directories, if required
		{
			CFileEnumerator feDir(EnumCallback, 
									strSearchDir, 
									_T("*.*"), 
									m_bRecurseSubDirectories, 
									m_bReportMatchingDirsAlso,
									true);	// important to ignore the dots for subdir enumeration
			hFind = feDir.FindFirstSubDir(strSearchDir, &ffData);
			if(hFind == INVALID_HANDLE_VALUE)	return true;
			do
			{
				bContinue = CFileEnumerator( m_pfnEnumCallback, 
											strSearchDir + ffData.cFileName,
											FileToSearch(),
											m_bRecurseSubDirectories,
											m_bReportMatchingDirsAlso,
											m_bIgnoreDots).EnumerateFiles(lpUserData);
			}while(bContinue && feDir.FindNextSubDir(hFind, &ffData));

			FindClose(hFind);
		}

		return bContinue;
	}
};

#endif


As yoy see I 'd like to change _tprintf() and Insert smth like that
VOID InsertIN_LIST(HWND hFileListView,LVITEM lv,int& a,LPCTSTR lpszItemName){
lv.iItem=a;
ListView_InsertItem(hFileListView, &lv);
ListView_SetItemText(hFileListView, a, 1, (LPWSTR)lpszItemName);
a++;
}

I've tried:
1)
bool FileEnumeratorCallback(LPCTSTR lpszItemName, LPCTSTR lpszItemDir, LPWIN32_FIND_DATA lpItemFindData,LPVOID lpUserData,HWND hFileListView,LVITEM lv){bla-bla}}

And changed:
CFileEnumerator(PFN_EnumeratorCallback pfnEnumCallback = CFileEnumerator::EnumCallback,	// Callback function for the enumeration
					LPCTSTR lpszSearchDir = _T("."),	// Should be a directory path (excluding the file name and wild cards) eg. "c:\\" or "C:\\Dir1"
					LPCTSTR lpszFileToSearch = _T("*.*"),// Should be a file name or wild card eg. "*.*"
					HWND hFileListView=NULL,
					LVITEM lv=lv)//lv=NULL aint' work as well as lv={0}

But always got an Error: "lv" and "hFileListView" as undeclared identifiers.
Posted
Updated 12-May-12 23:16pm
v6

This is a bad idea to enumerate files direct to ListView in your class. Better change your file-enumerating function to return array (list of files), and then (in the form class):
C++
array<String^>^foodList = {"Juice","Coffee","Cereal & Milk","Fruit Plate","Toast & Jelly","Bagel & Cream Cheese"};
   array<String^>^foodPrice = {"1.09","1.09","2.19","2.49","1.49","1.49"}; //example array; you need to fetch items from function
   for ( int count = 0; count < foodList->Length; count++ )
   {
      ListViewItem^ listItem = gcnew ListViewItem( foodList[ count ] );
      listItem->SubItems->Add( foodPrice[ count ] );
      ListView1->Items->Add( listItem );

   }
   this->Controls->Add( ListView1 );


More at: ListView.ListViewItemCollection[^]
 
Share this answer
 
v2
JOHN 602 wrote:
But always got an Error: "lv" and "hFileListView" as undeclared identifiers



I learned the hard way to not use other peoples code.

You end up spending time trying to understand the code to make a change, or worst, that the code is defective, and you have to fix it.

I looked at the code, it's nice, programmable with many options, clever.

The code lists all the files in the folder path you pass to the class, but you have to create the listview object first, and get a valid handle to it, to pass along to the callback, so the callback can add the files and folders to it.

hFileListView and lv are probably NULL

I didn't see any code taht creates the Listview and at least 1 item ( lv ) that is assigned to it.
 
Share this answer
 
v2
Comments
JOHN 602 13-May-12 3:19am    
Here is the listview code(in separate file):
<pre>
hFileListView=CreateWindow(WC_LISTVIEW,
NULL,
WS_CHILD | WS_VISIBLE | LVS_REPORT|WS_HSCROLL|WS_BORDER|WS_VSCROLL
| ES_AUTOHSCROLL | ES_AUTOVSCROLL,
150,
70,
630,
220,
hWnd,
(HMENU) 500,
hInst,
NULL);
lvc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT;
lvc.fmt = LVCFMT_LEFT;
//Name
lvc.iSubItem = 0;
lvc.cx = 280;
lvc.pszText = TEXT("Name");
ListView_InsertColumn(hFileListView, 0, &lvc);
//Data Modified
lvc.iSubItem = 1;
lvc.cx = 150;
lvc.pszText = TEXT("Data Modified");
ListView_InsertColumn(hFileListView, 1, &lvc);
//Type
lvc.iSubItem = 2;
lvc.cx = 100;
lvc.pszText = TEXT("Type");
ListView_InsertColumn(hFileListView, 2, &lvc);
//Size
lvc.iSubItem = 3;
lvc.cx = 100;
lvc.pszText = TEXT("Size");
ListView_InsertColumn(hFileListView, 3, &lvc);
</pre>

How to bind listview handle with that class defined above.(I mean send it as a parameter in callback function).
Your listbox looks like mine

This is my Listbox code, it holds the selection until double click, I have a dialog create function, that I call in the dialogProc WM_CREATE, and a listview init that I call in WM_CREATE

All is does is create the listbox with column bars. Your callback would populate your listbox after it's created. Just food for thought.

VB
lv_ProjectOpen_FileSelect = CreateWindow(
    WC_LISTVIEW,
    NULL,
    WS_CHILD | WS_TABSTOP | WS_VISIBLE | LVS_ALIGNLEFT | LVS_REPORT | LVS_EDITLABELS | LVS_SINGLESEL | LVS_EX_TWOCLICKACTIVATE | LVS_EX_TRACKSELECT,
    20, 83,
    453, 270,
    hWndDlg,
   (HMENU) IDC_PROJECTOPEN_LISTVIEW,
    GetModuleHandle(NULL),
    NULL
    );
    SendMessage( lv_ProjectOpen_FileSelect, WM_SETFONT, (WPARAM)hFont_Button, FALSE);
    ShowWindow( lv_ProjectOpen_FileSelect, SW_SHOW);


And then I build the column bars in Listview Init

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Build the Columns for Detail or Report view
	
// Size Column
memset( &lv_ProjectOpen_Column_Size, 3, sizeof( lv_ProjectOpen_Column_Size ) );										
lv_ProjectOpen_Column_Size.mask = LVCF_WIDTH | LVCF_FMT | LVCF_TEXT | LVCF_MINWIDTH;
lv_ProjectOpen_Column_Size.fmt = LVCFMT_RIGHT,
lv_ProjectOpen_Column_Size.cxMin = 65;																		
lv_ProjectOpen_Column_Size.pszText = L"File Size";																
iColumn = ListView_InsertColumn( lv_ProjectOpen_FileSelect, 0, &lv_ProjectOpen_Column_Size ); 
	
// Type Column
memset( &lv_ProjectOpen_Column_Type, 2, sizeof( lv_ProjectOpen_Column_Type ) );										
lv_ProjectOpen_Column_Type.mask = LVCF_WIDTH | LVCF_FMT | LVCF_TEXT;
lv_ProjectOpen_Column_Type.fmt = LVCFMT_RIGHT,
lv_ProjectOpen_Column_Type.cx = 70;																		
lv_ProjectOpen_Column_Type.pszText = L"Type";																
iColumn = ListView_InsertColumn( lv_ProjectOpen_FileSelect, 0, &lv_ProjectOpen_Column_Type ); 
	
// Date Modified Column
memset( &lv_ProjectOpen_Column_DateMod, 1, sizeof( lv_ProjectOpen_Column_DateMod ) );										
lv_ProjectOpen_Column_DateMod.mask = LVCF_WIDTH | LVCF_FMT | LVCF_TEXT;
lv_ProjectOpen_Column_DateMod.fmt = LVCFMT_RIGHT,
lv_ProjectOpen_Column_DateMod.cx = 135;																		
lv_ProjectOpen_Column_DateMod.pszText = L"Date Modified";																
iColumn = ListView_InsertColumn( lv_ProjectOpen_FileSelect, 0, &lv_ProjectOpen_Column_DateMod );
	
// Name Column
memset( &lv_ProjectOpen_Column_Name, 0, sizeof( lv_ProjectOpen_Column_Name ) );										
lv_ProjectOpen_Column_Name.mask = LVCF_WIDTH | LVCF_FMT | LVCF_TEXT;
lv_ProjectOpen_Column_Name.fmt = LVCFMT_LEFT,
lv_ProjectOpen_Column_Name.cx = 180;																		
lv_ProjectOpen_Column_Name.pszText = L"Name";
iColumn = ListView_InsertColumn( lv_ProjectOpen_FileSelect, 0, &lv_ProjectOpen_Column_Name );
DWORD dwError = GetLastError();	
	
// End of Build Columns for Detail or Report View
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900