www.pudn.com > VC写的MP3播放器源代码.zip > ITFindFiles.cpp
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// $NoKeywords: $
//
// @doc EXTERNAL UTILITY
#include "StdAfx.h"
#include "ITFindFiles.h"
#include "ITSimpleFindFiles.h"
#include "ITAPI.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
DWORD ITCFindFiles::None = 0x0000;
DWORD ITCFindFiles::IncludeSubfolders = 0x0001;
DWORD ITCFindFiles::SearchingSubfolders = 0x0002;
DWORD ITCFindFiles::AllAttributes = ITCSimpleFindFiles::AllAttributes;
DWORD ITCFindFiles::DefaultAttributes = ITCSimpleFindFiles::DefaultAttributes;
DWORD ITCFindFiles::FilesOnly = ITCSimpleFindFiles::FilesOnly;
DWORD ITCFindFiles::FoldersOnly = ITCSimpleFindFiles::FoldersOnly;
/////////////////////////////////////////////////////////////////////////////
// ITCFindFiles helpers
static BOOL IsNonFatalError(DWORD dwError)
{
BOOL bNonFatal = FALSE; // Assume so
switch (dwError)
{
case ERROR_FILE_NOT_FOUND:
case ERROR_NO_MORE_FILES:
bNonFatal = TRUE;
break;
}
return bNonFatal;
}
/////////////////////////////////////////////////////////////////////////////
// ITCFindFiles construction
// @mfunc Constructs a object.
//
// @xref
ITCFindFiles::ITCFindFiles()
{
m_lpEnumProc = NULL;
m_lEnumParam = 0;
}
// @mfunc Destroys a object.
//
// @xref
ITCFindFiles::~ITCFindFiles()
{
while (!m_findStack.IsEmpty())
CloseSearch();
m_findStack.RemoveAll();
}
/////////////////////////////////////////////////////////////////////////////
// ITCFindFiles attributes
// @mfunc Call this method to determine if the found file is archived.
// You must call at least once before
// calling this method.
//
// @rdesc Nonzero if the file is archived; otherwise 0.
//
// @xref
BOOL ITCFindFiles::IsArchived() const
{
return HasFileAttributes(FILE_ATTRIBUTE_ARCHIVE);
}
// @mfunc Call this method to determine if the found file is compressed.
// You must call at least once before
// calling this method.
//
// @rdesc Nonzero if the file is compressed; otherwise 0.
//
// @xref
BOOL ITCFindFiles::IsCompressed() const
{
return HasFileAttributes(FILE_ATTRIBUTE_COMPRESSED);
}
// @mfunc Call this method to determine if the found file is a folder.
// You must call at least once before
// calling this method.
//
// @rdesc Nonzero if the file is a folder; otherwise 0.
//
// @xref
BOOL ITCFindFiles::IsFolder() const
{
return HasFileAttributes(FILE_ATTRIBUTE_DIRECTORY);
}
// @mfunc Call this method to determine if the found file is hidden.
// You must call at least once before
// calling this method.
//
// @rdesc Nonzero if the file is hidden; otherwise 0.
//
// @xref
BOOL ITCFindFiles::IsHidden() const
{
return HasFileAttributes(FILE_ATTRIBUTE_HIDDEN);
}
// @mfunc Call this method to determine if the found file is normal.
// You must call at least once before
// calling this method.
//
// @rdesc Nonzero if the file is normal; otherwise 0.
//
// @xref
BOOL ITCFindFiles::IsNormal() const
{
return HasFileAttributes(FILE_ATTRIBUTE_NORMAL);
}
// @mfunc Call this method to determine if the found file is offline.
// You must call at least once before
// calling this method.
//
// @rdesc Nonzero if the file is offline; otherwise 0.
//
// @xref
BOOL ITCFindFiles::IsOffline() const
{
return HasFileAttributes(FILE_ATTRIBUTE_OFFLINE);
}
// @mfunc Call this method to determine if the found file is read-only.
// You must call at least once before
// calling this method.
//
// @rdesc Nonzero if the file is read-only; otherwise 0.
//
// @xref
BOOL ITCFindFiles::IsReadOnly() const
{
return HasFileAttributes(FILE_ATTRIBUTE_READONLY);
}
// @mfunc Call this method to determine if the found file is a system file.
// You must call at least once before
// calling this method.
//
// @rdesc Nonzero if the file is a system file; otherwise 0.
//
// @xref
BOOL ITCFindFiles::IsSystem() const
{
return HasFileAttributes(FILE_ATTRIBUTE_SYSTEM);
}
// @mfunc Call this method to determine if the found file is temporary.
// You must call at least once before
// calling this method.
//
// @rdesc Nonzero if the file is a temporary file; otherwise 0.
//
// @xref
BOOL ITCFindFiles::IsTemporary() const
{
return HasFileAttributes(FILE_ATTRIBUTE_TEMPORARY);
}
// @mfunc Call this method to test the file attributes of the found file.
// You must call at least once before
// calling this method.
//
// @parm Specifies one or more file attributes, identified in the
// structure. Any combination of the attributes is
// acceptable.
//
// @rdesc Nonzero if the file has all of the specified attributes; otherwise 0.
//
// @xref
BOOL ITCFindFiles::HasFileAttributes(DWORD dwFileAttributes) const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->HasFileAttributes(dwFileAttributes);
}
// @mfunc Call this method to get the length of the found file, in bytes.
// You must call at least once before
// calling this method.
//
// This method will only return a valid length if the file is less than
// four gigabytes in size.
//
// @rdesc The length of the found file, in bytes.
//
// @xref
DWORD ITCFindFiles::GetLength() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetLength();
}
// @mfunc Returns the file attributes, identified in the
// structure, of the found file. You must call
// at least once before calling this method.
//
// @rdesc The file attributes of the found file.
//
// @xref
DWORD ITCFindFiles::GetFileAttributes() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetFileAttributes();
}
// @mfunc Call this method to get the root of the found file.
// You must call at least once before
// calling this method.
//
// @rdesc The root of the search.
//
// @comm This method returns the drive specifier and path name where
// the search began. This method will always return the complete
// path of the search origin.
//
// @xref
//
//
CString ITCFindFiles::GetRoot() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetRoot();
}
// @mfunc Call this method to get the extension of the found file. For example,
// if the name of the file is DATA.TXT,
// returns "TXT".
//
// You must call at least once before calling
// this method.
//
// @rdesc The extension of the found file.
//
// @xref
//
//
CString ITCFindFiles::GetFileExt() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetFileExt();
}
// @mfunc Call this method to get the full path of the found file. You
// must call at least once before
// calling this method.
//
// @rdesc The path of the found file.
//
// @xref
//
//
CString ITCFindFiles::GetFilePath() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetFilePath();
}
// @mfunc Call this method to get the name of the found file,
// without the extension. You must call
// at least once before calling this method.
//
// @rdesc The title of the found file.
//
// @xref
//
//
CString ITCFindFiles::GetFileTitle() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetFileTitle();
}
// @mfunc Call this method to get the name of the found file,
// including the extension. You must call
// at least once before calling this method.
//
// @rdesc The name of the found file.
//
// @xref
//
//
LPCTSTR ITCFindFiles::GetFileName() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetFileName();
}
// @mfunc Call this method to get the folder containing the found file.
// You must call at least once before calling
// this method.
//
// @rdesc The folder containing the found file.
//
// @xref
//
CString ITCFindFiles::GetFileFolder() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetFileFolder();
}
// @mfunc Returns the structure of the found file.
// You must call at least once before
// calling this method.
//
// @rdesc A pointer to the of the found file.
//
// @xref
const WIN32_FIND_DATA* ITCFindFiles::GetFindData() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetFindData();
}
// @mfunc Call this method to get the file pattern the search is based on.
// For example, the pattern would be something like *.*, *.DAT, or MY*.TXT.
//
// @rdesc The file pattern of the search.
//
// @xref
CString ITCFindFiles::GetFindPattern() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetFindPattern();
}
// @mfunc Call this method to get the complete search pattern of the search.
// This is based on the find root, determined by
// and the find pattern, determined by .
//
// @rdesc The complete search pattern the search is based on.
//
// @xref
CString ITCFindFiles::GetFindFileName() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetFindFileName();
}
// @mfunc Call this method to get the file attributes the search is based on.
// Only files that have the specified attributes will be returned in the
// search.
//
// @parm Specifies file attributes that must be set.
// @parm Specifies file attributes that must not be set.
//
// @xref
void ITCFindFiles::GetFindAttributes(DWORD& dwAttribSet, DWORD& dwAttribClear) const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
pFind->GetFindAttributes(dwAttribSet, dwAttribClear);
}
// @mfunc Sets the file attributes that are being used to filter the search.
// Only files with attributes that include all of the
// and none of the
file attributes will be returned.
//
// @parm Specifies file attributes that must be set; 0 to match all files.
// @parm Specifies file attributes that must not be set; 0 to match all files.
//
// @ex |
// // Search for compressed files.
// SetAttributeFilter(FILE_ATTRIBUTE_COMPRESSED, FILE_ATTRIBUTE_DIRECTORY);
//
// // Search for compressed folders.
// SetAttributeFilter(FILE_ATTRIBUTE_COMPRESSED|FILE_ATTRIBUTE_DIRECTORY, 0);
//
// // Search for compressed files and folders.
// SetAttributeFilter(FILE_ATTRIBUTE_COMPRESSED, 0);
//
// // Search for everything.
// SetAttributeFilter(0, 0);
//
// @xref
void ITCFindFiles::SetFindAttributes(DWORD dwAttribSet, DWORD dwAttribClear)
{
ASSERT(!m_findStack.IsEmpty());
// This method affects all the searches currently in progress.
// If you only change one of the search objects, there are
// problems when multiple search values are specified in NewSearch.
POSITION pos = m_findStack.GetHeadPosition();
while (pos)
{
ITCSimpleFindFiles* pFind = m_findStack.GetNext(pos);
pFind->SetFindAttributes(dwAttribSet, dwAttribClear);
}
}
// @mfunc Retrieve the string that describes the file's type. This is the same
// description displayed in the Type column of the Windows Explorer.
// You must call at least once before
// calling this method.
//
// @rdesc The string that describes the file's type.
//
// @xref
CString ITCFindFiles::GetTypeName() const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->GetTypeName();
}
// @mfunc Retrieves shell information about the found file using the
// Win32 function. You must call
// at least once before calling this method.
//
// @parm Combination of one or more file attribute flags.
// @parm Address of a structure to receive the file information.
// @parm Flags that specify the file information to retrieve.
//
// @rdesc Returns a value whose meaning depends on the parameter.
//
// @comm See the Win32 documentation on the function
// for a more complete description of this method and its purpose.
//
// @xref
DWORD ITCFindFiles::SHGetFileInfo(DWORD dwFileAttributes,
SHFILEINFO FAR *psfi, UINT uFlags) const
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return pFind->SHGetFileInfo(dwFileAttributes, psfi, uFlags);
}
/////////////////////////////////////////////////////////////////////////////
// ITCFindFiles operations
// @mfunc Call this method to begin a search. You must call this method
// before calling . Each call to this method
// should be matched with a call to .
//
// @syntax void NewSearch(CString strPattern,
// DWORD dwFindAttributes, DWORD dwFindFlags);
// @syntax void NewSearch(CString strFolder, CString strPattern,
// DWORD dwFindAttributes, DWORD dwFindFlags)
// @syntax void NewSearch(HDROP hDropInfo,
// DWORD dwFindAttributes, DWORD dwFindFlags)
//
// @parm CString | strFolder | The folder to search; can be the empty string.
// @parm CString | strPattern | The name of the file(s) to find. The name
// can contain wildcard characters (* and ?); if empty, the pattern *.* is used.
// @parm DWORD | dwFindAttributes | The file attributes of the file(s) to
// find. See the Win32 documentation on the structure
// for a description of valid file attributes. You can also specify one of
// the following special values.
// @flag ITCFindFiles::AllAttributes | Finds everything.
// @flag ITCFindFiles::DefaultAttributes | Find all non-system files and folders.
// @flag ITCFindFiles::FilesOnly | Find all non-system files.
// @flag ITCFindFiles::FoldersOnly | Find all non-system folders.
// @parm DWORD | dwFindFlags | Can be a combination of the following values:
// @flag ITCFindFiles::None | No flags are set.
// @flag ITCFindFiles::IncludeSubfolders | Specifies that subfolders should be searched.
//
// @comm The in the first version of this method can
// contain the folder and pattern to search, for example C:\*.*. Multiple
// searches can be performed by separating them with semicolons.
// The
in the second version can only contain the pattern,
// but multiple patterns can also be specified.
//
// When specifying the file attributes with the
parameter,
// only files that have all the specified file attributes will be returned
// in the search. If you do not specify one of the special values, you should
// use the method to gain more
// control over attribute based searches.
//
// The third version of this method can be used to iterate through a set
// of files in a drag and drop operation. Usually you would use the
// ITCFindFiles::FilesOnly find attribute and the ITCFindFiles::IncludeSubfolders
// find flag. You are responsible for calling when the search
// is complete.
//
// @xref
//
void ITCFindFiles::NewSearch(CString strPattern,
DWORD dwFindAttributes, DWORD dwFindFlags)
{
CStringArray aMultiSearch;
ITCLIB::StringToStringArray(strPattern, ";", aMultiSearch);
// Add the searches in reverse order so they appear in the
// file list as they appear in the pattern specification.
for (int i=aMultiSearch.GetUpperBound(); i >= 0; i--)
{
ITCSimpleFindFiles* pFind = new ITCSimpleFindFiles;
pFind->NewSearch(aMultiSearch[i], dwFindAttributes);
pFind->SetUserData(dwFindFlags);
m_findStack.AddTail(pFind);
}
}
void ITCFindFiles::NewSearch(CString strFolder, CString strPattern,
DWORD dwFindAttributes, DWORD dwFindFlags)
{
CStringArray aMultiSearch;
ITCLIB::StringToStringArray(strPattern, ";", aMultiSearch);
// Add the searches in reverse order so they appear in the
// file list as they appear in the pattern specification.
for (int i=aMultiSearch.GetUpperBound(); i >= 0; i--)
{
ITCSimpleFindFiles* pFind = new ITCSimpleFindFiles;
pFind->NewSearch(strFolder, aMultiSearch[i], dwFindAttributes);
pFind->SetUserData(dwFindFlags);
m_findStack.AddTail(pFind);
}
}
void ITCFindFiles::NewSearch(HDROP hDropInfo,
DWORD dwFindAttributes, DWORD dwFindFlags)
{
ITCSimpleFindFiles* pFind = new ITCSimpleFindFiles;
pFind->NewSearch(hDropInfo, dwFindAttributes);
pFind->SetUserData(dwFindFlags);
m_findStack.AddTail(pFind);
}
// @mfunc Call this method to start or continue the file search.
// You must call before calling this
// method for the first time.
//
// @rdesc Nonzero if successful; otherwise 0. To get extended error
// information, call the Win32 function .
//
// The most common return values will be ERROR_FILE_NOT_FOUND if the
// search cannot be started and ERROR_NO_MORE_FILES if there are
// no more files in the search.
//
// @xref
BOOL ITCFindFiles::NextFile()
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
return (pFind->IsDroppedFiles()) ? NextDropFile() : NextFindFile();
}
// @mfunc Call this method to end the search. You must call
// to begin a new search before
// calling again.
//
// @xref
void ITCFindFiles::CloseSearch()
{
ASSERT(!m_findStack.IsEmpty());
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
pFind->Close();
delete pFind;
m_findStack.RemoveTail();
}
// @mfunc Appends to a the paths of files found by
// the search. This is done by calling
// in a loop and adding the full file path of the found file to the
// list. You must call before calling this
// method.
//
// @parm A reference to a to append the files to.
//
// @rdesc Nonzero if successful; otherwise 0. To get extended error
// information, call the Win32 function .
// This method will return success if the last error is
// ERROR_FILE_NOT_FOUND or ERROR_NO_MORE_FILES.
//
// @xref
BOOL ITCFindFiles::BuildFileList(CStringArray& rFileList)
{
ASSERT(!m_findStack.IsEmpty());
while (NextFile())
rFileList.Add(GetFilePath());
return IsNonFatalError(::GetLastError());
}
// @mfunc This method returns the number of the files found by the search.
// This is done by calling in a loop and
// counting each file. You must call before
// calling this method.
//
// @parm A reference to a to return number of files found.
//
// @rdesc Nonzero if successful; otherwise 0. To get extended error
// information, call the Win32 function .
// This method will return success if the last error is
// ERROR_FILE_NOT_FOUND or ERROR_NO_MORE_FILES.
//
// @xref
BOOL ITCFindFiles::GetFileCount(DWORD& dwCount)
{
ASSERT(!m_findStack.IsEmpty());
dwCount = 0;
while (NextFile())
dwCount++;
return IsNonFatalError(::GetLastError());
}
// @mfunc Sets the function to be called for each file found in the search.
//
// @parm A pointer to the callback function.
// @parm Specifies the application-defined parameter to be passed to
// the callback function.
//
// @rdesc The previous callback function or NULL if no callback was defined.
//
// @comm The callback function is called by .
//
// @xref
ITCFINDFILESENUMPROC ITCFindFiles::SetCallback(ITCFINDFILESENUMPROC lpEnumProc, LONG lParam)
{
ITCFINDFILESENUMPROC lpOldEnumProc = m_lpEnumProc;
m_lpEnumProc = lpEnumProc;
m_lEnumParam = lParam;
return lpOldEnumProc;
}
/////////////////////////////////////////////////////////////////////////////
// ITCFindFiles overridables
// @mfunc This method is called for each file found in the search.
// You can use this method to stop the search when a file is found.
// The default implementation calls the callback function set by
// or returns nonzero if no callback is set.
//
// @rdesc Return nonzero to continue the search; otherwise 0.
//
// @xref
BOOL ITCFindFiles::OnFindFile()
{
if (m_lpEnumProc)
return (m_lpEnumProc)(this, m_lEnumParam);
return TRUE; // Continue the search
}
// @mfunc If the search includes subfolders, this method is called
// for each subfolder to search. The default implementation begins
// a new search for the files in the subfolder by calling
// with the path returned by
// . The files in the new search will
// be enumerated before the current search continues.
//
// @comm This method is not called for the folder where the search
// begins. This method is only called when subfolders need to be
// searched.
//
// @xref
void ITCFindFiles::OnSearchSubfolder()
{
ASSERT(m_findStack.GetCount() >= 2);
if (m_findStack.GetCount() >= 2)
{
POSITION pos = m_findStack.GetTailPosition();
ITCSimpleFindFiles* pPrev = NULL;
// The last search is the search for each subfolder.
// The search before that contains the attributes and
// filter of the files we want to search for.
pPrev = m_findStack.GetPrev(pos);
pPrev = m_findStack.GetPrev(pos);
DWORD dwAttribSet = 0;
DWORD dwAttribClear = 0;
pPrev->GetFindAttributes(dwAttribSet, dwAttribClear);
if (HasFileAttributes(FILE_ATTRIBUTE_SYSTEM) && !(dwAttribSet & FILE_ATTRIBUTE_SYSTEM))
{
// This is a System folder and if the user didn't want
// to see System files, we shouldn't show them files
// in system folders.
}
else
{
CString strPattern = pPrev->GetFindPattern();
ITCSimpleFindFiles* pSearchSubfolder = new ITCSimpleFindFiles;
pSearchSubfolder->NewSearch(GetFilePath(), strPattern, 0);
pSearchSubfolder->SetUserData(IncludeSubfolders);
pSearchSubfolder->SetFindAttributes(dwAttribSet, dwAttribClear);
m_findStack.AddTail(pSearchSubfolder);
}
}
}
// @mfunc This method is called to determine if a file should be
// part of the search. You can override this method to perform
// custom filtering of files. The default implementation always
// returns nonzero.
//
// @rdesc Return nonzero if the file should be returned as part of
// the search; otherwise 0.
//
// @xref
BOOL ITCFindFiles::OnFilterFile() const
{
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// ITCFindFiles implementation
BOOL ITCFindFiles::NextFindFile()
{
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
DWORD dwUserData = pFind->GetUserData();
if (dwUserData & SearchingSubfolders)
{
// We are trying to find subfolders. For each subfolder
// we find, create a new search for each of the files in
// that folder. If there are no more subfolders, close the
// search and continue with the search that got us here.
DWORD dwLastError = ::GetLastError();
if (pFind->NextFile())
{
ASSERT(IsFolder());
OnSearchSubfolder();
dwLastError = ::GetLastError();
}
else if (::GetLastError() == ERROR_FILE_NOT_FOUND)
{
dwLastError = ERROR_NO_MORE_FILES;
CloseSearch();
}
else
{
dwLastError = ::GetLastError();
CloseSearch();
}
::SetLastError(dwLastError);
return NextFile();
}
if (pFind->NextFile())
{
// We found a matching file or folder!
if (!OnFilterFile())
return NextFile();
return OnFindFile();
}
if (dwUserData & IncludeSubfolders)
{
// We have been through all the matching files and folders,
// so now we want to search the subfolders. We create a new
// search to find each subfolder, and if there are any,
// each of them will be searched. Make sure we don't search
// this folder for subfolders again.
dwUserData &= ~IncludeSubfolders;
pFind->SetUserData(dwUserData);
ITCSimpleFindFiles* pFindSubfolders = new ITCSimpleFindFiles;
pFindSubfolders->NewSearch(GetRoot(), "*.*", FILE_ATTRIBUTE_DIRECTORY);
pFindSubfolders->SetUserData(SearchingSubfolders|IncludeSubfolders);
m_findStack.AddTail(pFindSubfolders);
return NextFile();
}
if (m_findStack.GetCount() > 1)
{
// There are no more matching files or folders so continue
// with the search that got us here.
CloseSearch();
return NextFile();
}
return FALSE;
}
BOOL ITCFindFiles::NextDropFile()
{
ITCSimpleFindFiles* pFind = m_findStack.GetTail();
DWORD dwUserData = pFind->GetUserData();
if (dwUserData & SearchingSubfolders)
{
// We are trying to find subfolders. For each subfolder
// we find, create a new search for each of the files in
// that folder. If there are no more subfolders, close the
// search and continue with the search that got us here.
if (pFind->NextFile())
{
ASSERT(IsFolder());
OnSearchSubfolder();
return NextFile();
}
return FALSE;
}
if (pFind->NextFile())
{
// We found a matching file or folder!
if (!OnFilterFile())
return NextFile();
return OnFindFile();
}
if (dwUserData & IncludeSubfolders)
{
// We have been through all the matching files and folders,
// so now we want to search the subfolders. We reset the
// search to find each subfolder, and if there are any,
// each of them will be searched. Make sure we don't search
// for subfolders again.
dwUserData &= ~IncludeSubfolders;
pFind->SetUserData(dwUserData);
ITCSimpleFindFiles* pFindSubfolders = new ITCSimpleFindFiles;
pFindSubfolders->NewSearch(*pFind);
pFindSubfolders->SetFindAttributes(FILE_ATTRIBUTE_DIRECTORY, 0);
pFindSubfolders->SetUserData(SearchingSubfolders|IncludeSubfolders);
m_findStack.AddTail(pFindSubfolders);
return NextFile();
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// ITCFindFiles diagnostics
#ifdef _DEBUG
void ITCFindFiles::AssertValid() const
{
CObject::AssertValid();
ASSERT_VALID(&m_findStack);
}
void ITCFindFiles::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(ITCFindFiles, CObject)