////////////////////////////////////////////////////////////////////// // // Path.cpp: implementation of the myPath class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "mypath.h" #include "Shlwapi.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// myPath::myPath() { m_bIsRelative = FALSE; } myPath::myPath(LPCTSTR szPath, BOOL bIsFolderPath, BOOL bHasArguments) { SetPath(szPath, bIsFolderPath, bHasArguments); } myPath::myPath(DWORD dwSpecial) { SetPath(dwSpecial); } myPath::~myPath() { } void myPath::SetPath(DWORD dwSpecial) { switch (dwSpecial) { case PATH_CMDLINE: SetPath(GetCommandLine(), FALSE, TRUE); break; case PATH_MODULE: { char szPath[_MAX_PATH]; GetModuleFileName(NULL, szPath, _MAX_PATH); //获取当前应用程序的路径 SetPath(szPath); } break; } } void myPath::SetPath(LPCTSTR szPath, BOOL bIsFolderPath, BOOL bHasArguments) { char szParamPath[_MAX_PATH]; char szDrive[_MAX_DRIVE], szDir[_MAX_DIR]; char szName[_MAX_FNAME], szExt[_MAX_EXT]; // Reset m_sOriginalPath.Empty(); m_sDriveLabel.Empty(); m_bIsRelative = FALSE; m_aDir.RemoveAll(); m_sExtName.Empty(); m_aArgs.RemoveAll(); // Original path m_sOriginalPath = szPath; // Get args and remove them from path szParamPath[0] = 0x0; strcpy(szParamPath, szPath); if (bHasArguments) { /*PathGetArgs功能:从路径中分析参数 例如:LPTSTR pszParam = PathGetArgs( “notepad.exe c:\\temp.txt” ) pszParam 返回 “c:\\temp.txt”*/ m_sArgs = PathGetArgs(szParamPath); PathRemoveArgs(szParamPath); //删除路径中所得带的参数 } PathUnquoteSpaces(szParamPath); //从带引号的路径中取出路径 if (szParamPath[0] == 0x0) return; _splitpath(szParamPath, szDrive, szDir, szName, szExt);//将一个文件名或 URL (统一资源定位符)分解成它的名称、目录、扩展名和驱动器。 // Drive m_sDrive = szDrive; // Directory m_sDir = szDir; m_sDir.Replace('/', '\\'); if (!m_sDir.IsEmpty()) m_bIsRelative = (m_sDir[0] != '\\'); // FileTitle if (bIsFolderPath) { m_sDir = myPath::AddBackSlash(m_sDir); m_sDir += szName; m_sDir = myPath::AddBackSlash(m_sDir); } else { m_sFileTitle = szName; } // Get extension name (e.g.: "txt") if (IsFilePath()) { m_sExtName = szExt; m_sExtName.Remove('.'); } } BOOL myPath::IsLocalPath() { return !m_sDrive.IsEmpty() && !m_bIsRelative; } BOOL myPath::IsRelativePath() { return m_bIsRelative; } BOOL myPath::IsFilePath() { return !m_sFileTitle.IsEmpty(); } BOOL myPath::ExistFile() { if (!IsFilePath()) return FALSE; return PathFileExists(GetPath()); } BOOL myPath::ExistLocation() { return PathFileExists(GetLocation()); } CString myPath::GetAbsolutePath(LPCTSTR szBaseFolder) { if (!IsRelativePath()) return sCEmptyString; char szAbsolutePath[_MAX_PATH]; CString sFullPath(szBaseFolder); if (sFullPath.IsEmpty()) return sCEmptyString; sFullPath = myPath::AddBackSlash(sFullPath); sFullPath += GetPath(); if (!PathCanonicalize(szAbsolutePath, sFullPath)) return sCEmptyString; return szAbsolutePath; } CString myPath::GetRelativePath(LPCTSTR szBaseFolder) { if (IsRelativePath()) return sCEmptyString; char szRelativePath[_MAX_PATH]; CString sRelPath; PathRelativePathTo(szRelativePath, szBaseFolder, FILE_ATTRIBUTE_DIRECTORY, GetPath(), IsFilePath() ? 0 : FILE_ATTRIBUTE_DIRECTORY); sRelPath = szRelativePath; if (sRelPath.GetLength() > 1) { // Remove ".\" from the beginning if ((sRelPath[0] == '.') && (sRelPath[1] == '\\')) sRelPath.Right(sRelPath.GetLength() - 2); } return sRelPath; } CString myPath::GetPath(BOOL bAppendArgs, BOOL bOriginal) { CString sPath; if (bOriginal) sPath = m_sOriginalPath; else sPath = GetLocation() + GetFileName(); if (bAppendArgs) sPath += GetArgument(); return sPath; } CString myPath::GetShortPath() { char szShortPath[_MAX_PATH]; szShortPath[0] = 0x0; GetShortPathName(GetPath(), szShortPath, _MAX_PATH); return szShortPath; } CString myPath::GetLongPath() { char szLongPath[_MAX_PATH]; szLongPath[0] = 0x0; GetLongPathName(GetPath(), szLongPath, _MAX_PATH); return szLongPath; } CString myPath::GetDrive() { return m_sDrive; } CString myPath::GetDriveLabel(BOOL bPCNameIfNetwork) { if (m_sDriveLabel.IsEmpty() && !IsRelativePath()) { if ((bPCNameIfNetwork) && (!IsLocalPath())) m_sDriveLabel = GetDir(0); else { CString sRoot; char szVolumeName[256]; szVolumeName[0] = '\0'; if (IsLocalPath()) { sRoot = m_sDrive + CString("\\"); } else if (GetDirCount() > 1) { sRoot.Format("\\\\%s\\%s\\", GetDir(0), GetDir(1)); } GetVolumeInformation(sRoot, szVolumeName, 255, NULL, NULL, NULL, NULL, 0); m_sDriveLabel = szVolumeName; } } return m_sDriveLabel; } int myPath::GetDirCount() { FillDirArray(); return m_aDir.GetSize(); } CString myPath::GetDir(int nIndex) { if (nIndex < 0) return m_sDir; else if (nIndex < GetDirCount()) { FillDirArray(); return m_aDir[nIndex]; } return sCEmptyString; } CString myPath::GetLocation() { return m_sDrive + GetDir(); } CString myPath::GetFileTitle() { return m_sFileTitle; } CString myPath::GetFileName() { return m_sFileTitle + GetExtension(); } CString myPath::GetExtension() { if (m_sExtName.IsEmpty()) return sCEmptyString; return CString(".") + m_sExtName; } CString myPath::GetExtName() { return m_sExtName; } int myPath::GetArgCount() { FillArgArray(); return m_aArgs.GetSize(); } CString myPath::GetArgument(int nIndex, BOOL bGetFlag) { if (nIndex < 0) { if (m_sArgs.IsEmpty()) { for (int nItem = 0; nItem < m_aArgs.GetSize(); nItem++) m_sArgs += m_aArgs[nItem].GetString(); m_sArgs.TrimLeft(); } return m_sArgs; } else if (nIndex < GetArgCount()) { FillArgArray(); if (bGetFlag) return m_aArgs[nIndex].sFlag; else return m_aArgs[nIndex].sValue; } return sCEmptyString; } void myPath::SetArguments(LPCTSTR szArgs) { m_aArgs.RemoveAll(); m_sArgs = szArgs; } void myPath::AddSetArgument(LPCTSTR szFlag, LPCTSTR szArgument) { int nIndex; nIndex = FindArgument(szFlag); if (nIndex != -1) { // An argument with the same flag already exists. Update it! m_aArgs[nIndex].sValue = szArgument; } else { CArgument arg; arg.sValue = szArgument; arg.SetFlag(szFlag); m_aArgs.Add(arg); m_sArgs.Empty(); } } void myPath::RemoveArgument(int nIndex) { if ((nIndex >= 0) && (nIndex < m_aArgs.GetSize())) { m_aArgs.RemoveAt(nIndex); m_sArgs.Empty(); } } int myPath::FindArgument(LPCTSTR szFlag) { bool bFound = false; int nIndex; CArgument arg; FillArgArray(); arg.SetFlag(szFlag); if (!arg.sFlag.IsEmpty()) { for (nIndex = 0; nIndex < m_aArgs.GetSize(); nIndex++) { bFound = (m_aArgs[nIndex].sFlag.CompareNoCase(arg.sFlag) == 0); if (bFound) break; } } return (bFound ? nIndex : -1); } BOOL myPath::GetFileSize(__int64 &nSize) { BOOL bResult; bResult = FillFileInfoStruct(); nSize = ((__int64)m_fis.nFileSizeHigh * (__int64)MAXDWORD) + (__int64)m_fis.nFileSizeLow; return bResult; } BOOL myPath::GetFileTime(CTime &time, DWORD dwType) { BOOL bResult; FILETIME *pTime = NULL; bResult = FillFileInfoStruct(); switch (dwType) { case FILE_CREATION: pTime = &m_fis.ftCreationTime; break; case FILE_WRITE: pTime = &m_fis.ftLastWriteTime; break; case FILE_ACCESS: default: pTime = &m_fis.ftLastAccessTime; break; } if (pTime != NULL) time = CTime(*pTime); return bResult; } ///////////////////////////////////////////////////////////////////////////////////////////// // Private methods // This function must be called whenever m_aDir array is needed, since this // method is the one which parses m_sDir and fill m_aDir void myPath::FillDirArray() { if (m_sDir.IsEmpty() || (m_aDir.GetSize() > 0)) return; int nFrom, nTo; // nFrom: 0 - relative / 1 - local / 2 - network nFrom = IsLocalPath() ? 1 : (IsRelativePath() ? 0 : 2); while ((nTo = m_sDir.Find('\\', nFrom)) != -1) { m_aDir.Add(m_sDir.Mid(nFrom, nTo - nFrom)); nFrom = nTo + 1; } } // This function must be called whenever m_aArgs array is needed, since this // method is the one which parses m_sArgs and fill m_aArgs void myPath::FillArgArray() { if (m_sArgs.IsEmpty() || (m_aArgs.GetSize() > 0)) return; CString sArgs(m_sArgs); int nFrom, nTo; bool bQuotedArg = false; CArgument arg; sArgs.TrimLeft(); sArgs.TrimRight(); // add a blank space at the end of the string to include the last argument sArgs += " "; while ((nTo = sArgs.FindOneOf(" \"")) != -1) { bQuotedArg = (sArgs[nTo] == '\"'); if (bQuotedArg) { nFrom = nTo + 1; if ((nTo = sArgs.Find('\"', nFrom)) == -1) break; arg.sValue = sArgs.Mid(nFrom, nTo - nFrom); } else { CString *pStr; if ((sArgs[0] == '/') || (sArgs[0] == '-')) { if (!arg.sFlag.IsEmpty()) { arg.SetFlag(arg.sFlag); m_aArgs.Add(arg); arg.sFlag.Empty(); arg.sValue.Empty(); } pStr = &arg.sFlag; } else pStr = &arg.sValue; *pStr = sArgs.Left(nTo); } if (!arg.sValue.IsEmpty()) { arg.SetFlag(arg.sFlag); m_aArgs.Add(arg); arg.sFlag.Empty(); arg.sValue.Empty(); } sArgs = sArgs.Right(sArgs.GetLength() - nTo - 1); sArgs.TrimLeft(); } // if the last argument is only a flag it hasn't been added yet if (!arg.sFlag.IsEmpty()) { arg.SetFlag(arg.sFlag); m_aArgs.Add(arg); } } BOOL myPath::FillFileInfoStruct() { HANDLE hFile; BOOL bResult; ::memset(&m_fis, 0, sizeof(m_fis)); hFile = CreateFile(GetPath(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; bResult = GetFileInformationByHandle(hFile, &m_fis); CloseHandle(hFile); return bResult; } CString myPath::AddBackSlash(LPCTSTR szFolderPath, BOOL bInverted) { CString sResult(szFolderPath); int nLastChar = sResult.GetLength() - 1; if (nLastChar >= 0) { if ((sResult[nLastChar] != '\\') && (sResult[nLastChar] != '/')) sResult += bInverted ? '/' : '\\'; } return sResult; } CString myPath::RemoveBackSlash(LPCTSTR szFolderPath) { CString sResult(szFolderPath); int nLastChar = sResult.GetLength() - 1; if (nLastChar >= 0) { if ((sResult[nLastChar] == '\\') || (sResult[nLastChar] == '/')) sResult = sResult.Left(nLastChar); } return sResult; } myPath::operator LPCTSTR () { m_sLPCTSTRPath = GetPath(); return m_sLPCTSTRPath; } const myPath& myPath::operator = (LPCTSTR szPath) { SetPath(szPath); return *this; } const myPath& myPath::operator = (myPath &ref) { m_aArgs.RemoveAll(); m_aArgs.Copy(ref.m_aArgs); m_aDir.RemoveAll(); m_aDir.Copy(ref.m_aDir); m_bIsRelative = ref.m_bIsRelative; m_fis = ref.m_fis; m_sArgs = ref.m_sArgs; m_sDir = ref.m_sDir; m_sDrive = ref.m_sDrive; m_sDriveLabel = ref.m_sDriveLabel; m_sExtName = ref.m_sExtName; m_sFileTitle = ref.m_sFileTitle; m_sOriginalPath = ref.m_sOriginalPath; return *this; }