This is an EnumFiles function I created some time ago. It's a non-recursive function. If you look hard enough at the code, you can figure out the rest of the problem: how to add the files to the treeview.
Code:
// filename.h
#include <windows.h>
typedef BOOL (CALLBACK *ENUMFILEPROC)(LPCTSTR,LPTSTR,DWORD,LPARAM);
#define PATHSEP '\\'
#define EXTSEP '.'
#define EF_RECURSE 0x0001
#define EF_NOGETDIR 0x0002
#define EF_NOGETFILE 0x0004
#define EF_GETDIRLAST 0x0008
BOOL ParsePath(LPCTSTR filespec,LPTSTR path,LPTSTR *name,LPTSTR *ext);
BOOL EnumFiles(LPCTSTR filespec, UINT uFlags, ENUMFILEPROC efp, LPARAM lParam);
#define SetFileNameExt(out,dir,name,ext) \
wsprintf(out,"%s%c%s%c%s",(dir)?dir:"",PATHSEP,(name)?name:"",EXTSEP,(ext)?ext:"")
#define SetFileName(out,dir,name) \
wsprintf(out,"%s%c%s",(dir)?dir:"",PATHSEP,(name)?name:"")
Code:
// filename.c
#include "filename.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
BOOL ParsePath(LPCTSTR filespec,
LPTSTR path,
LPTSTR *name,
LPTSTR *ext){
if(name)*name=NULL;
if(ext)*ext=NULL;
if (lstrlen(filespec) >= _MAX_PATH)
return FALSE;
if (lstrcmp(filespec,_T("."))==0 || lstrcmp(filespec,_T(".."))==0) {
if(path)GetCurrentDirectory(MAX_PATH,path);
return TRUE;
} else {
// Parse extension
int i;
TCHAR c;
int len = lstrlen(filespec);
for (i = len-1; i>=0; i--) {
c = filespec[i];
if (c==PATHSEP) {
break;
} else if (c==EXTSEP) {
if(ext)*ext = &filespec[i+1];
i--; // skip dot
break;
}
}
// Parse name
for ( ; i>=0; i--) {
c = filespec[i];
if (c==PATHSEP) {
if(name)*name = &filespec[i+1];
if(path)lstrcpyn(path,filespec,i+1);
break;
} else if (i==0) {
if(name)*name=filespec;
if(path)GetCurrentDirectory(MAX_PATH,path);
break;
}
}
}
return TRUE;
}
static int charicmp ( char char1, char char2 ){
char Char1 = ( 'a' <= char1 ) && ( char1 <= 'z' ) ? char1 - 'a' + 'A' : char1;
char Char2 = ( 'a' <= char2 ) && ( char2 <= 'z' ) ? char2 - 'a' + 'A' : char2;
return ( Char2 - Char1 );
}
static int _mfs_regexp(LPSTR lpFileName,LPSTR lpFilter){
LPSTR lpTempFileName = lpFileName;
LPSTR lpTempFilter = lpFilter;
char TempToken [ 2 ];
BOOL Matched = FALSE;
if((! lpFileName) ||(! *lpFileName) ||
(! lpFilter) ||(! *lpFilter))
return(FALSE);
while((lpTempFilter) &&(*lpTempFilter) &&(! Matched)){
memset(TempToken, 0, sizeof(TempToken));
switch(*lpTempFilter){
default:
if(charicmp(*lpTempFileName, *lpTempFilter)){
lpTempFileName = lpFileName;
if ((lpTempFilter = strpbrk(lpTempFilter, " ,;")))
lpTempFilter++;
} else {
lpTempFilter++;
lpTempFileName++;
switch(*lpTempFilter){
default:
break;
case '\0':case ' ':case ',':case ';':
if(! *lpTempFileName)
Matched = TRUE;
break;
}
}
break;
case '?':
lpTempFilter++;
lpTempFileName++;
break;
case '*':
if(!(TempToken [ 0 ] = *(++lpTempFilter)))
Matched = TRUE;
else
{
lpTempFilter++;
while((lpTempFileName = strpbrk(lpTempFileName, TempToken)) &&
(! Matched))
Matched = _mfs_regexp(++lpTempFileName, lpTempFilter);
if((! lpTempFileName) &&(! Matched))
{
lpTempFileName = lpFileName;
if ((lpTempFilter = strpbrk(lpTempFilter, " ,;")))
lpTempFilter++;
}
}
break;
case '\0':case ' ':case ',':case ';':
Matched = TRUE;
break;
}
}
return(Matched);
}
BOOL EnumFiles(LPCTSTR filespec, UINT uFlags, ENUMFILEPROC efp, LPARAM lParam){
HANDLE hf=INVALID_HANDLE_VALUE;
WIN32_FIND_DATA fd;
TCHAR fullname[MAX_PATH];
TCHAR fullpath[MAX_PATH];
TCHAR findspec[MAX_PATH];
HANDLE *pStack=NULL; // handle stack to improve efficiency
int stacksize=0;
LPTSTR name,ext;
BOOL bexit=FALSE;
BOOL ngf=(uFlags&EF_NOGETFILE);
BOOL ngd=(uFlags&EF_NOGETDIR);
BOOL rcu=(uFlags&EF_RECURSE);
BOOL rcf=FALSE;
int i;
if(ngf&&ngd)
return TRUE;
ParsePath(filespec,fullname,&name,&ext);
if(uFlags&EF_RECURSE){
pStack=malloc(sizeof(HANDLE)*MAX_PATH);
if(!pStack)return FALSE;
SetFileName(findspec,fullname,"*.*");
rcf=TRUE;
} else {
lstrcpy(findspec,filespec);
}
while(1){
BOOL leavenow=FALSE;
if(hf==INVALID_HANDLE_VALUE)
hf=FindFirstFile(findspec,&fd);
if(pStack)pStack[stacksize++]=hf;
if(hf!=INVALID_HANDLE_VALUE){
// push onto stack
while(1){
BOOL isdir=(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY);
if(lstrcmp(fd.cFileName,".")&&lstrcmp(fd.cFileName,"..")){
// DebugOut("%s | %s",fd.cFileName,name);
#define CHKAGAINST (!rcu||(rcu&&(isdir||(!isdir&&_mfs_regexp(fd.cFileName,name)))))
if(((!ngf&&!ngd)||(ngf&&isdir)||(ngd&&!isdir))
&&CHKAGAINST){
SetFileName(fullpath,fullname,fd.cFileName);
if(!efp(fullpath,
fd.cFileName,
fd.dwFileAttributes,
lParam)){
FindClose(hf);
if(pStack)free(pStack);
return TRUE;
}
}
if((uFlags&EF_RECURSE)&&isdir){
BOOL ret;
TCHAR fullpath2[MAX_PATH];
SetFileName(fullpath,fullname,fd.cFileName);
SetFileName(fullpath2,fullpath,name);
SetFileName(findspec,fullpath2,"*.*");
leavenow=TRUE;
break;
}
}
if(!FindNextFile(hf,&fd))
break;
}
if(leavenow){
hf=INVALID_HANDLE_VALUE;
continue;
}
FindClose(hf);
}
// pop from stack
if(pStack&&stacksize>0)hf=pStack[--stacksize];
if(uFlags&EF_RECURSE){
if(stacksize==0)break;
} else break;
for(i=lstrlen(findspec)-1;i<=0;i--)
if(findspec[i]==PATHSEP){findspec[i]='\0';break;}
}
if(pStack)free(pStack);
return TRUE;
}
// sample callback functions
BOOL EnumFiles_CalcTotalFileSize(LPCTSTR filename, LPTSTR filepart, DWORD dwAttr, LPARAM lParam){
PDWORD64 pdwlSize=(void*)lParam;
if(!(dwAttr&FILE_ATTRIBUTE_DIRECTORY)){
DWORD dwLow,dwHigh;
HANDLE hf=OpenFileForReading(filename);
dwLow=GetFileSize(hf,&dwHigh);
if(dwHigh==0)
*pdwlSize+=(DWORD64)dwLow;
else
*pdwlSize+=((DWORD64)dwHigh<<32)|dwLow;
CloseHandle(hf);
}
return TRUE;
}
BOOL EnumFiles_NumberOfFiles(LPCTSTR filename, LPTSTR filepart, DWORD dwAttr, LPARAM lParam){
PDWORD pdwNum=(void*)lParam;
*pdwNum+=1;
return TRUE;
}