📄 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 <c ITCSimpleFindFiles> object.
//
// @xref <c ITCSimpleFindFiles>
ITCSimpleFindFiles::ITCSimpleFindFiles()
{
CommonConstruct();
}
// @mfunc Destroys a <c ITCSimpleFindFiles> object.
//
// @xref <c ITCSimpleFindFiles>
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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -