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 aobject. // // @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)