www.pudn.com > VC写的MP3播放器源代码.zip > ITSimpleFindFiles.cpp


///////////////////////////////////////////////////////////////////////////// 
 
///////////////////////////////////////////////////////////////////////////// 
// 
// $NoKeywords: $ 
// 
// @doc INTERNAL UTILITY 
 
#include "StdAfx.h" 
 
#include "ITSimpleFindFiles.h" 
#include "ITAPI.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
// Note: These special values assume that there are no FILE_ATTRIBUTE_ 
// values with the high bits set. 
// FILE_ATTRIBUTE_SYSTEM 
// FILE_ATTRIBUTE_READONLY 
// FILE_ATTRIBUTE_HIDDEN 
// FILE_ATTRIBUTE_DIRECTORY 
// FILE_ATTRIBUTE_ARCHIVE 
// FILE_ATTRIBUTE_NORMAL 
// FILE_ATTRIBUTE_TEMPORARY 
// FILE_ATTRIBUTE_COMPRESSED 
// FILE_ATTRIBUTE_OFFLINE; 
 
DWORD ITCSimpleFindFiles::AllAttributes = 0x01000000; 
static DWORD AllAttributesSet = 0; 
static DWORD AllAttributesClear = 0; 
 
// Find all non-system files and folders. 
// Includes all attributes except FILE_ATTRIBUTE_SYSTEM so 
// the user doesn't search folders such as the Recycle Bin. 
DWORD ITCSimpleFindFiles::DefaultAttributes = 0x02000000; 
static DWORD DefaultAttributesSet = 0; 
static DWORD DefaultAttributesClear = FILE_ATTRIBUTE_SYSTEM; 
 
// Find all non-system files. 
// Files don't have the FILE_ATTRIBUTE_DIRECTORY set. 
DWORD ITCSimpleFindFiles::FilesOnly = 0x03000000; 
static DWORD FilesOnlyAttribSet = 0; 
static DWORD FilesOnlyAttribClear = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_SYSTEM; 
 
// Find all non-system folders. 
// Folders must have the FILE_ATTRIBUTE_DIRECTORY set. 
DWORD ITCSimpleFindFiles::FoldersOnly = 0x04000000; 
static DWORD FoldersOnlyAttribSet = FILE_ATTRIBUTE_DIRECTORY; 
static DWORD FoldersOnlyAttribClear = FILE_ATTRIBUTE_SYSTEM; 
 
static HDROP INVALID_DROP_HANDLE = (HDROP)INVALID_HANDLE_VALUE; 
 
///////////////////////////////////////////////////////////////////////////// 
// ITCSimpleFindFiles construction 
 
// @mfunc Constructs a  object. 
// 
// @xref  
ITCSimpleFindFiles::ITCSimpleFindFiles() 
{ 
	CommonConstruct(); 
} 
 
// @mfunc Destroys a  object. 
// 
// @xref  
ITCSimpleFindFiles::~ITCSimpleFindFiles() 
{ 
	Close(); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// ITCSimpleFindFiles attributes 
 
BOOL ITCSimpleFindFiles::HasFileAttributes(DWORD dwFileAttributes) const 
{ 
	return ((m_findData.dwFileAttributes & dwFileAttributes) == dwFileAttributes); 
} 
 
DWORD ITCSimpleFindFiles::GetLength() const 
{ 
	return m_findData.nFileSizeLow; 
} 
 
DWORD ITCSimpleFindFiles::GetFileAttributes() const 
{ 
	return m_findData.dwFileAttributes; 
} 
 
BOOL ITCSimpleFindFiles::IsSpecialFolder() const 
{ 
	LPCTSTR lpszFileName = GetFileName(); 
 
	if (HasFileAttributes(FILE_ATTRIBUTE_DIRECTORY) && (lpszFileName[0] == '.')) 
	{ 
		if (strcmp(lpszFileName, ".") == 0) 
			return TRUE; 
		else if (strcmp(lpszFileName, "..") == 0) 
			return TRUE; 
	} 
 
	return FALSE; 
} 
 
CString ITCSimpleFindFiles::GetRoot() const 
{ 
	return m_strFindRoot; 
} 
 
CString ITCSimpleFindFiles::GetFilePath() const 
{ 
	CString strFilePath; 
 
	// If the files we are returning are from a drag and 
	// drop operation, the file paths are already fully 
	// qualified. If we are getting files from the file 
	// system, the file paths must be created based on 
	// the search folder and the name of the current file. 
 
	if (!IsDroppedFiles()) 
	{ 
		strFilePath = GetRoot(); 
		 
		if (!strFilePath.IsEmpty()) 
		{ 
			ASSERT(strFilePath[strFilePath.GetLength()-1] != '\\'); 
			strFilePath += '\\'; 
		} 
		 
		strFilePath += GetFileName(); 
	} 
	else 
	{ 
		strFilePath = m_strDropFilePath; 
	} 
 
	return strFilePath; 
} 
 
CString ITCSimpleFindFiles::GetFileExt() const 
{ 
	TCHAR szExtention[_MAX_EXT]; 
	_tsplitpath(GetFileName(), NULL, NULL, NULL, szExtention); 
	return (szExtention[0] != '.') ? szExtention : &(szExtention[1]); 
} 
 
CString ITCSimpleFindFiles::GetFileTitle() const 
{ 
	CString strFileTitle; 
	_tsplitpath(GetFileName(), NULL, NULL, strFileTitle.GetBuffer(_MAX_PATH), NULL); 
	strFileTitle.ReleaseBuffer(); 
	return strFileTitle; 
} 
 
LPCTSTR ITCSimpleFindFiles::GetFileName() const 
{ 
	return m_findData.cFileName; 
} 
 
CString ITCSimpleFindFiles::GetFileFolder() const 
{ 
	CString strFileFolder = GetFilePath(); 
	LPSTR lpsz = strrchr(strFileFolder.GetBuffer(0), '\\'); 
	if (lpsz) *lpsz = '\0'; 
	strFileFolder.ReleaseBuffer(); 
	return strFileFolder; 
} 
 
const WIN32_FIND_DATA* ITCSimpleFindFiles::GetFindData() const 
{ 
	return &m_findData; 
} 
 
CString ITCSimpleFindFiles::GetFindPattern() const 
{ 
	return m_strFindPattern; 
} 
 
CString ITCSimpleFindFiles::GetFindFileName() const 
{ 
	CString strFileName = GetRoot(); 
	if (!strFileName.IsEmpty()) 
		strFileName += "\\"; 
	strFileName += GetFindPattern(); 
	return strFileName; 
} 
 
DWORD ITCSimpleFindFiles::GetUserData() const 
{ 
	return m_dwUserData; 
} 
 
void ITCSimpleFindFiles::SetUserData(DWORD dwUserData) 
{ 
	m_dwUserData = dwUserData; 
} 
 
void ITCSimpleFindFiles::GetFindAttributes(DWORD& dwAttribSet, DWORD& dwAttribClear) const 
{ 
	dwAttribSet = m_dwFindAttribSet; 
	dwAttribClear = m_dwFindAttribClear; 
} 
 
void ITCSimpleFindFiles::SetFindAttributes(DWORD dwAttribSet, DWORD dwAttribClear) 
{ 
	if (dwAttribSet == ITCSimpleFindFiles::AllAttributes) 
	{ 
		m_dwFindAttribSet = AllAttributesSet; 
		m_dwFindAttribClear = AllAttributesClear; 
	} 
	else if (dwAttribSet == ITCSimpleFindFiles::DefaultAttributes) 
	{ 
		m_dwFindAttribSet = DefaultAttributesSet; 
		m_dwFindAttribClear = DefaultAttributesClear; 
	} 
	else if (dwAttribSet == ITCSimpleFindFiles::FilesOnly) 
	{ 
		m_dwFindAttribSet = FilesOnlyAttribSet; 
		m_dwFindAttribClear = FilesOnlyAttribClear; 
	} 
	else if (dwAttribSet == ITCSimpleFindFiles::FoldersOnly) 
	{ 
		m_dwFindAttribSet = FoldersOnlyAttribSet; 
		m_dwFindAttribClear = FoldersOnlyAttribClear; 
	} 
	else 
	{ 
		m_dwFindAttribSet = dwAttribSet; 
		m_dwFindAttribClear = dwAttribClear; 
	} 
} 
 
BOOL ITCSimpleFindFiles::IsDroppedFiles() const 
{ 
	return (m_hDropInfo != INVALID_DROP_HANDLE); 
} 
 
CString ITCSimpleFindFiles::GetTypeName() const 
{ 
	CString strTypeName; 
 
	SHFILEINFO sfi; 
	if (SHGetFileInfo(0, &sfi, SHGFI_TYPENAME)) 
	{ 
		strTypeName = sfi.szTypeName; 
	} 
 
	// szTypeName may be an empty string. If so, we build the 
	// type based on the file extension (i.e. 'DAT File'). If 
	// there is no file extension, just use the word 'File'. 
 
	if (strTypeName.IsEmpty()) 
	{ 
		strTypeName = GetFileExt(); 
		strTypeName.MakeUpper(); // Extension is shown in uppercase 
		strTypeName += (strTypeName.IsEmpty()) ? "File" : " File"; 
	} 
 
	return strTypeName; 
} 
 
DWORD ITCSimpleFindFiles::SHGetFileInfo(DWORD dwFileAttributes, 
	SHFILEINFO FAR *psfi, UINT uFlags) const 
{ 
	return ::SHGetFileInfo(GetFilePath(), dwFileAttributes,  
		psfi, sizeof(SHFILEINFO), uFlags); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// ITCSimpleFindFiles operations 
 
void ITCSimpleFindFiles::NewSearch(CString strPattern, 
	DWORD dwFindAttributes) 
{ 
	ITCLIB::TrimString(strPattern); 
 
	if (strPattern.IsEmpty()) 
		strPattern = "*.*"; 
 
	CString strFindRoot; 
	CString strFindPattern; 
 
	const int chPattern = strPattern.ReverseFind('\\'); 
	if (chPattern >= 0) 
	{ 
		strFindRoot = strPattern.Left(chPattern); 
		const int nLength = strPattern.GetLength() - chPattern - 1; 
		strFindPattern = strPattern.Right(nLength); 
	} 
	else 
	{ 
		strFindRoot.Empty(); 
		strFindPattern = strPattern; 
	} 
 
	NewSearch(strFindRoot, strFindPattern, dwFindAttributes); 
} 
 
void ITCSimpleFindFiles::NewSearch(CString strFolder, 
	CString strPattern, DWORD dwFindAttributes) 
{ 
	ASSERT(m_hFindFile == INVALID_HANDLE_VALUE); 
 
	CommonConstruct(); 
 
	ITCLIB::TrimString(strFolder); 
	ITCLIB::TrimString(strPattern); 
 
	if (strPattern.IsEmpty()) 
		strPattern = "*.*"; 
 
	m_strFindPattern = strPattern; 
	 
	SetFindAttributes(dwFindAttributes, 0); 
 
	// If the folder is a drive specification such as "C:" 
	// we can't call fullpath() because it will convert it 
	// to the current directory for that drive and they 
	// really want to search the entire drive. 
	BOOL bSearchDrive = FALSE; 
	if (!strFolder.IsEmpty()) 
		bSearchDrive = (strFolder[strFolder.GetLength()-1] == ':'); 
 
	if (!bSearchDrive) 
	{ 
		LPTSTR lpszRoot = m_strFindRoot.GetBufferSetLength(_MAX_PATH); 
		_tfullpath(lpszRoot, strFolder, _MAX_PATH); 
		if (lpszRoot[lstrlen(lpszRoot)-1] == '\\') 
			lpszRoot[lstrlen(lpszRoot)-1] = '\0'; 
		m_strFindRoot.ReleaseBuffer(); 
	} 
	else 
	{ 
		m_strFindRoot = strFolder; 
	} 
} 
 
void ITCSimpleFindFiles::NewSearch(HDROP hDropInfo, 
	DWORD dwFindAttributes) 
{ 
	ASSERT(hDropInfo != NULL); 
	ASSERT(m_hFindFile == INVALID_HANDLE_VALUE); 
 
	CommonConstruct(); 
 
	m_hDropInfo = hDropInfo; 
	m_uDropIndex = 0; 
	m_uMaxDropIndex = ::DragQueryFile(m_hDropInfo, (UINT)-1, NULL, 0); 
 
	SetFindAttributes(dwFindAttributes, 0); 
} 
 
void ITCSimpleFindFiles::NewSearch(const ITCSimpleFindFiles& rhs) 
{ 
	ASSERT(m_hDropInfo == INVALID_DROP_HANDLE); 
	ASSERT(m_hFindFile == INVALID_HANDLE_VALUE); 
 
	CommonConstruct(); 
 
	m_uDropIndex = 0; 
	m_uMaxDropIndex = rhs.m_uMaxDropIndex; 
	m_dwUserData = rhs.m_dwUserData; 
	m_dwFindAttribSet = rhs.m_dwFindAttribSet; 
	m_dwFindAttribClear = rhs.m_dwFindAttribClear; 
	m_hDropInfo = rhs.m_hDropInfo; 
	m_hFindFile = rhs.m_hFindFile; 
	m_strFindRoot = rhs.m_strFindRoot; 
	m_strFindPattern = rhs.m_strFindPattern; 
	m_strDropFilePath = rhs.m_strDropFilePath; 
 
	CopyMemory(&m_findData, &(rhs.m_findData), sizeof(WIN32_FIND_DATA)); 
} 
 
BOOL ITCSimpleFindFiles::NextFile() 
{ 
	return (IsDroppedFiles()) ? NextDropFile() : NextFindFile(); 
} 
 
void ITCSimpleFindFiles::Close() 
{ 
	if (m_hFindFile != INVALID_HANDLE_VALUE) 
	{ 
		VERIFY(::FindClose(m_hFindFile)); 
		m_hFindFile = INVALID_HANDLE_VALUE; 
	} 
 
	if (m_hDropInfo != INVALID_DROP_HANDLE) 
	{ 
		m_uDropIndex = 0; 
		m_uMaxDropIndex = 0; 
		m_hDropInfo = INVALID_DROP_HANDLE; 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// ITCSimpleFindFiles overridables 
 
BOOL ITCSimpleFindFiles::OnFilterFile() const 
{ 
	// Skip the special folders "." and ".." and any files 
	// that have or don't have the attributes we are looking for. 
 
	BOOL bMatch = TRUE; 
 
	bMatch &= (!IsSpecialFolder()); 
	bMatch &= ((m_findData.dwFileAttributes & m_dwFindAttribSet) == m_dwFindAttribSet); 
	bMatch &= ((m_findData.dwFileAttributes & m_dwFindAttribClear) == 0); 
 
	return bMatch; 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// ITCSimpleFindFiles implementation 
 
void ITCSimpleFindFiles::CommonConstruct() 
{ 
	m_hFindFile = INVALID_HANDLE_VALUE; 
	m_hDropInfo = INVALID_DROP_HANDLE; 
	m_uDropIndex = 0; 
	m_dwUserData = 0; 
	m_uMaxDropIndex = 0; 
	m_dwFindAttribSet = 0; // Match all files 
	m_dwFindAttribClear = 0; // Match all files 
 
	m_strFindRoot.Empty(); 
	m_strFindPattern = "*.*"; 
	m_strDropFilePath.Empty(); 
 
	::ZeroMemory(&m_findData, sizeof(WIN32_FIND_DATA)); 
} 
 
BOOL ITCSimpleFindFiles::NextFindFile() 
{ 
	::ZeroMemory(&m_findData, sizeof(WIN32_FIND_DATA)); 
 
	if (m_hFindFile == INVALID_HANDLE_VALUE) 
	{ 
		// The first time we are called, attempt to open the 
		// find and see if the first file is valid. 
 
		m_hFindFile = ::FindFirstFile(GetFindFileName(), &m_findData); 
		if (m_hFindFile != INVALID_HANDLE_VALUE) 
			if (OnFilterFile()) 
				return TRUE; 
	} 
 
	if (m_hFindFile != INVALID_HANDLE_VALUE) 
	{ 
		// If the first file is not valid, or when we are called 
		// again, search until we find the next valid file. 
 
		do 
		{ 
			if (!::FindNextFile(m_hFindFile, &m_findData)) 
				return FALSE; 
 
		} while (!OnFilterFile()); 
	} 
 
	return (m_hFindFile != INVALID_HANDLE_VALUE); 
} 
 
BOOL ITCSimpleFindFiles::NextDropFile() 
{ 
	if (m_hDropInfo != INVALID_DROP_HANDLE) 
	{ 
		do 
		{ 
			if (!DragQueryFile()) 
				return FALSE; 
 
		} while (!OnFilterFile()); 
	} 
 
	return (m_hDropInfo != INVALID_DROP_HANDLE); 
} 
 
BOOL ITCSimpleFindFiles::DragQueryFile() 
{ 
	ASSERT(m_hDropInfo != INVALID_DROP_HANDLE); 
 
	BOOL bValidFile = FALSE; // Assume failure 
 
	::ZeroMemory(&m_findData, sizeof(WIN32_FIND_DATA)); 
 
	if (m_uDropIndex < m_uMaxDropIndex) 
	{ 
		LPSTR lpszFile = m_strDropFilePath.GetBufferSetLength(_MAX_PATH); 
 
		VERIFY(::DragQueryFile(m_hDropInfo, m_uDropIndex++, 
			lpszFile, _MAX_PATH) < _MAX_PATH); 
 
		m_strDropFilePath.ReleaseBuffer(); 
 
		bValidFile = (::FindFirstFile(m_strDropFilePath, 
			&m_findData) != INVALID_HANDLE_VALUE); 
	} 
	else 
	{ 
		::SetLastError(ERROR_NO_MORE_FILES); 
	} 
 
	if (!bValidFile) 
		m_strDropFilePath.Empty(); 
 
	return bValidFile; 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// ITCSimpleFindFiles diagnostics 
 
#ifdef _DEBUG 
void ITCSimpleFindFiles::AssertValid() const 
{ 
	CObject::AssertValid(); 
 
	if (m_hFindFile != INVALID_HANDLE_VALUE) 
	{ 
		ASSERT(m_hDropInfo == INVALID_DROP_HANDLE); 
	} 
 
	if (m_hDropInfo != INVALID_DROP_HANDLE) 
	{ 
		ASSERT(m_hFindFile == INVALID_HANDLE_VALUE); 
	} 
} 
 
void ITCSimpleFindFiles::Dump(CDumpContext& dc) const 
{ 
	CObject::Dump(dc); 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
 
IMPLEMENT_DYNAMIC(ITCSimpleFindFiles, CObject)