⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 itfindfiles.cpp

📁 完整的MP3播放器源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// @rdesc Returns a value whose meaning depends on the <p uFlags> parameter.
//
// @comm See the Win32 documentation on the <f SHGetFileInfo> function
// for a more complete description of this method and its purpose.
//
// @xref <c ITCFindFiles>
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 <mf ITCFindFiles::NextFile>. Each call to this method
// should be matched with a call to <mf ITCFindFiles::CloseSearch>.
//
// @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 <t WIN32_FIND_DATA> 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 <p strPattern> 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 <p strPattern> in the second version can only contain the pattern,
// but multiple patterns can also be specified.
// 
// When specifying the file attributes with the <p dwFindAttributes> 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 <mf ITCFindFiles::SetFindAttributes> 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 <f DragFinish> when the search
// is complete.
//
// @xref <c ITCFindFiles> <mf ITCFindFiles::NextFile>
// <mf ITCFindFiles::CloseSearch> <mf ITCFindFiles::SetFindAttributes>
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 <mf ITCFindFiles::NewSearch> before calling this
// method for the first time.
//
// @rdesc Nonzero if successful; otherwise 0. To get extended error
// information, call the Win32 function <f GetLastError>.
//
// 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 <c ITCFindFiles> <mf ITCFindFiles::NewSearch>
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
// <mf ITCFindFiles::NewSearch> to begin a new search before
// calling <mf ITCFindFiles::NextFile> again.
//
// @xref <c ITCFindFiles> <mf ITCFindFiles::NewSearch>
void ITCFindFiles::CloseSearch()
{
	ASSERT(!m_findStack.IsEmpty());
	ITCSimpleFindFiles* pFind = m_findStack.GetTail();
	pFind->Close();
	delete pFind;
	m_findStack.RemoveTail();
}

// @mfunc Appends to a <c CStringArray> the paths of files found by
// the search. This is done by calling <mf ITCFindFiles::NextFile>
// in a loop and adding the full file path of the found file to the
// list. You must call <mf ITCFindFiles::NewSearch> before calling this
// method.
//
// @parm A reference to a <c CStringArray> to append the files to.
//
// @rdesc Nonzero if successful; otherwise 0. To get extended error
// information, call the Win32 function <f GetLastError>.
// This method will return success if the last error is
// ERROR_FILE_NOT_FOUND or ERROR_NO_MORE_FILES.
//
// @xref <c ITCFindFiles> <mf ITCFindFiles::NextFile>
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 <mf ITCFindFiles::NextFile> in a loop and
// counting each file. You must call <mf ITCFindFiles::NewSearch> before
// calling this method.
//
// @parm A reference to a <t DWORD> to return number of files found.
//
// @rdesc Nonzero if successful; otherwise 0. To get extended error
// information, call the Win32 function <f GetLastError>.
// This method will return success if the last error is
// ERROR_FILE_NOT_FOUND or ERROR_NO_MORE_FILES.
//
// @xref <c ITCFindFiles> <mf ITCFindFiles::NextFile>
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 <mf ITCFindFiles::OnFindFile>.
//
// @xref <c ITCFindFiles> <f FindFileEnumProc>
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
// <mf ITCFindFiles::SetCallback> or returns nonzero if no callback is set.
//
// @rdesc Return nonzero to continue the search; otherwise 0.
//
// @xref <c ITCFindFiles> <mf ITCFindFiles::OnFilterFile>
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
// <mf ITCFindFiles::NewSearch> with the path returned by
// <mf ITCFindFiles::GetFilePath>. 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 <c ITCFindFiles>
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 <c ITCFindFiles> <mf ITCFindFiles::OnFindFile>
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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -