CComFileDlg.h
#pragma once
#include <string>
#include <tchar.h>
#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif
class CPathUtils
{
public:
//
// @brief: 获取当前进程完全路径
// @ret: 当前进程完全路径 如 D:\Software\HxDPortableSetup.exe
static _tstring GetCurrentModulePath();
//
// @brief: 获取当前进程所在目录
// @ret: 当前进程所在目录 如 D:\Software
static _tstring GetCurrentModuleDir();
//
// @brief: 获取当前进程名
// @ret: 当前进程名 如 HxDPortableSetup.exe
static _tstring GetCurrentModuleName(bool bHasExt = false);
//
// @brief: 获取文件所在文件夹
// @param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe
// @ret: 文件夹 如 D:\Software
static _tstring GetFileDir(const _tstring& strPath);
//
// @brief: 获取文件名
// @param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe
// @param: bHasExt 是否包含扩展名
// @ret: 文件夹 如 HxDPortableSetup
static _tstring GetFileName(const _tstring& strPath, bool bHasExt = false);
//
// @brief: 获取文件扩展名
// @param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe
// @param: bHasDot 是否包含点号
// @ret: 文件夹 如 exe
static _tstring GetFileExt(const _tstring& strPath, bool bHasDot = false);
//
// @brief: 获取短路径
// @param: strPath 输入长路径(必须存在)
// @ret: 短路径
static _tstring GetShortPath(const _tstring& strPath);
//
// @brief: 获取长路径
// @param: strPath 输入短路径(必须存在)
// @ret: 长路径
static _tstring GetLongPath(const _tstring& strPath);
//
// @brief: 获取全路径
// @param: strPath 输入路径
// @ret: 全路径
static _tstring GetFullPath(const _tstring& strPath);
//
// @brief: 检查是否为文件
// @param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe
// @ret: 是否存在 存在返回 true
static bool IsArchive(const _tstring& strPath);
//
// @brief: 检查是否为文件夹
// @param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe
// @ret: 是否存在 存在返回 true
static bool IsDirectory(const _tstring& strPath);
//
// @brief: 检查路径是否存在
// @param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe
// @ret: 是否存在 存在返回 true
static bool IsExist(const _tstring& strPath);
//
// @brief: 判断是否是完整路径
// @param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe
// @ret: 是返回 true
static bool IsFullPath(const _tstring& strPath);
//
// @brief: 如果路径存在空格, 则使用引号括起来
// @param: strPath 文件名, 如: C:\Program Files (x86)
// @ret: 添加引号 添加引号返回 true
static bool QuoteSpaces(_tstring& strPath);
//
// @brief: 删除路径开头和末尾的引号
// @param: strPath 文件名, 如: "C:\Program Files (x86)"
// @ret: 去除引号 去除引号返回 true
static bool UnquoteSpaces(_tstring& strPath);
//
// @brief: 重命名
// @param: strSrc 原始文件名
// @param: strDest 目标文件名(绝对路径或仅目标名)
// @ret: 成功返回true
static bool Rename(const _tstring& strSrc, const _tstring& strDest);
//
// @brief: 删除文件或文件夹
// @param: strPath 路径
// @ret: 成功返回true
static bool Delete(const _tstring& strPath);
//
// @brief: 删除文件
// @param: strPath 路径
// @ret: 成功返回true
static bool DeleteArchive(const _tstring& strPath);
//
// @brief: 删除目录(递归删除子目录及文件)
// @param: strPath 路径
// @ret: 成功返回true
static bool DeleteDir(const _tstring& strPath);
//
// @brief: 创建目录(递归)
// @param: strPath 路径
// @ret: 成功返回true
static bool CreateDir(const _tstring& strPath);
//
// @brief: 获取展开环境变量字符串
// @param: strPath 路径
// @ret: _tstring 展开字符串
static _tstring GetExpandEnvStrings(const _tstring& strPath);
//
// @brief: 获取环境变量字符串
// @param: strPath 路径
// @ret: _tstring 展开字符串
static _tstring GetUnExpandEnvStrings(const _tstring& strPath);
};
CComFileDlg.cpp
#include "CComFileDlg.h"
#include "CStrUtils.h"
_tstring CComFileDlg::GetCurrentModulePath()
{
TCHAR szCurPath[MAX_PATH] = { 0 };
::GetModuleFileName(NULL, szCurPath, _countof(szCurPath));
_tstring strResult = szCurPath;
return strResult;
}
_tstring CComFileDlg::GetCurrentModuleDir()
{
return GetFileDir(GetCurrentModulePath());
}
_tstring CComFileDlg::GetCurrentModuleName(bool bHasExt/* = true*/)
{
return GetFileName(GetCurrentModulePath(), bHasExt);
}
_tstring CComFileDlg::GetFileName(const _tstring& strPath, bool bHasExt/* = true*/)
{
_tstring strResult = strPath;
size_t nIndex = strResult.find_last_of(_T('\\'));
if (nIndex != _tstring::npos)
{
strResult = strResult.substr(nIndex + 1);
}
if (!bHasExt)
{
nIndex = strResult.find_last_of(_T('.'));
if (nIndex != _tstring::npos)
{
strResult.resize(nIndex);
}
}
return strResult;
}
_tstring CComFileDlg::GetFileDir(const _tstring& strPath)
{
_tstring strResult;
size_t nIndex = strPath.find_last_of(_T('\\'));
if (nIndex != _tstring::npos)
{
strResult = strPath.substr(0, nIndex);
}
return strResult;
}
bool CComFileDlg::IsExist(const _tstring& strPath)
{
return 0 == _taccess_s(strPath.c_str(), 00);
}
bool CComFileDlg::IsArchive(const _tstring& strPath)
{
WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
{
return false;
}
return attr.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE;
}
bool CComFileDlg::IsDirectory(const _tstring& strPath)
{
WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
{
return false;
}
return attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
}
bool CComFileDlg::GetSavePath(HWND hOwner, _tstring& strPath, UINT& nTypeIndex, const COMDLG_FILTERSPEC* pFilters, int filterCnt)
{
IFileSaveDialog* pSaveFileDlg = nullptr;
bool bComSuccess = false;
HRESULT hr = S_OK;
hr = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
return false;
}
bComSuccess = true;
hr = ::CoCreateInstance(
CLSID_FileSaveDialog,
nullptr,
CLSCTX_ALL,
IID_IFileSaveDialog,
(LPVOID*)&pSaveFileDlg
);
if (FAILED(hr))
{
goto L_Cleanup;
}
{
pSaveFileDlg->SetOptions(
FOS_OVERWRITEPROMPT |
FOS_STRICTFILETYPES |
FOS_DONTADDTORECENT |
FOS_NOCHANGEDIR
);
if (pFilters)
{
pSaveFileDlg->SetFileTypes(filterCnt, pFilters);
}
do
{
if (0 != nTypeIndex)
{
pSaveFileDlg->SetFileTypeIndex(nTypeIndex);
}
_tstring strFileDir = strPath;
if (strFileDir.empty())
{
strFileDir = GetCurrentModuleDir();
}
if (IsArchive(strFileDir))
{
strFileDir = GetFileDir(strFileDir);
}
if (!strFileDir.empty() && 0 == _taccess_s(strFileDir.c_str(), 00))
{
IShellItem* pItem = nullptr;
hr = ::SHCreateItemFromParsingName(CStrUtils::TStrToWStr(strFileDir).c_str(), nullptr, IID_PPV_ARGS(&pItem));
if (FAILED(hr))
{
break;
}
pSaveFileDlg->SetFolder(pItem);
pItem->Release();
}
hr = pSaveFileDlg->Show(hOwner);
if (SUCCEEDED(hr))
{
pSaveFileDlg->GetFileTypeIndex(&nTypeIndex);
IShellItem* pItemInfo = nullptr;
hr = pSaveFileDlg->GetResult(&pItemInfo);
if (pItemInfo)
{
LPWSTR resultptr = nullptr;
pItemInfo->GetDisplayName(SIGDN_FILESYSPATH, &resultptr);
pItemInfo->Release();
if (resultptr)
{
strPath = CStrUtils::WStrToTStr(resultptr);
::CoTaskMemFree(resultptr);
}
}
}
} while (FALSE);
}
L_Cleanup:
if (bComSuccess)
{
::CoUninitialize();
}
if (SUCCEEDED(hr))
{
return true;
}
return false;
}
bool CComFileDlg::GetSaveDir(HWND hOwner, _tstring& strDir)
{
IFileDialog* pFileDlg = nullptr;
bool bComSuccess = false;
HRESULT hr = S_OK;
hr = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
return false;
}
bComSuccess = true;
hr = ::CoCreateInstance(
CLSID_FileOpenDialog,
nullptr,
CLSCTX_ALL,
IID_IFileDialog,
(LPVOID*)&pFileDlg
);
if (FAILED(hr))
{
goto L_Cleanup;
}
{
pFileDlg->SetOptions(
FOS_PICKFOLDERS | FOS_NOCHANGEDIR
);
do
{
_tstring strFileDir = strDir;
if (strFileDir.empty())
{
strFileDir = GetCurrentModuleDir();
}
if (IsDirectory(strFileDir))
{
IShellItem* pItem = nullptr;
hr = ::SHCreateItemFromParsingName(CStrUtils::TStrToWStr(strFileDir).c_str(), nullptr, IID_PPV_ARGS(&pItem));
if (FAILED(hr))
{
break;
}
pFileDlg->SetFolder(pItem);
pItem->Release();
}
hr = pFileDlg->Show(hOwner);
if (SUCCEEDED(hr))
{
IShellItem* pItemInfo = nullptr;
hr = pFileDlg->GetResult(&pItemInfo);
if (pItemInfo)
{
LPWSTR resultptr = nullptr;
pItemInfo->GetDisplayName(SIGDN_FILESYSPATH, &resultptr);
pItemInfo->Release();
if (resultptr)
{
strDir = CStrUtils::WStrToTStr(resultptr);
::CoTaskMemFree(resultptr);
}
}
}
} while (FALSE);
}
L_Cleanup:
if (bComSuccess)
{
::CoUninitialize();
}
if (SUCCEEDED(hr))
{
return true;
}
return false;
}
bool CComFileDlg::GetOpenPath(HWND hOwner, _tstring& strPath, UINT& nTypeIndex, const COMDLG_FILTERSPEC* pFilters, int filterCnt)
{
IFileOpenDialog* pOpenFileDlg = nullptr;
bool bComSuccess = false;
HRESULT hr = S_OK;
hr = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
return false;
}
bComSuccess = true;
hr = ::CoCreateInstance(
CLSID_FileOpenDialog,
nullptr,
CLSCTX_ALL,
IID_IFileOpenDialog,
(LPVOID*)&pOpenFileDlg
);
if (FAILED(hr))
{
goto L_Cleanup;
}
{
pOpenFileDlg->SetOptions(
FOS_FILEMUSTEXIST |
FOS_STRICTFILETYPES |
FOS_DONTADDTORECENT |
FOS_NOCHANGEDIR
);
if (pFilters)
{
pOpenFileDlg->SetFileTypes(filterCnt, pFilters);
}
do
{
if (0 != nTypeIndex)
{
pOpenFileDlg->SetFileTypeIndex(nTypeIndex);
}
_tstring strFileDir = strPath;
if (strFileDir.empty())
{
strFileDir = GetCurrentModuleDir();
}
if (IsArchive(strFileDir))
{
strFileDir = GetFileDir(strFileDir);
}
if (IsDirectory(strFileDir))
{
IShellItem* pItem = nullptr;
hr = ::SHCreateItemFromParsingName(CStrUtils::TStrToWStr(strFileDir).c_str(), nullptr, IID_PPV_ARGS(&pItem));
if (FAILED(hr))
{
break;
}
pOpenFileDlg->SetFolder(pItem);
pItem->Release();
}
hr = pOpenFileDlg->Show(hOwner);
if (SUCCEEDED(hr))
{
pOpenFileDlg->GetFileTypeIndex(&nTypeIndex);
IShellItem* pItemInfo = nullptr;
hr = pOpenFileDlg->GetResult(&pItemInfo);
if (pItemInfo)
{
LPWSTR resultptr = nullptr;
pItemInfo->GetDisplayName(SIGDN_FILESYSPATH, &resultptr);
pItemInfo->Release();
if (resultptr)
{
strPath = CStrUtils::WStrToTStr(resultptr);
::CoTaskMemFree(resultptr);
}
}
}
} while (FALSE);
}
L_Cleanup:
if (bComSuccess)
{
::CoUninitialize();
}
if (SUCCEEDED(hr))
{
return true;
}
return false;
}
std::vector<_tstring> CComFileDlg::GetFileList(HWND hOwner, _tstring& strDir, const COMDLG_FILTERSPEC* pFilters, int filterCnt)
{
std::vector<_tstring> vFileList;
IFileOpenDialog* pOpenFileDlg = nullptr;
bool bComSuccess = false;
HRESULT hr = S_OK;
hr = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
goto L_Cleanup;
}
bComSuccess = true;
hr = ::CoCreateInstance(
CLSID_FileOpenDialog,
nullptr,
CLSCTX_ALL,
IID_IFileOpenDialog,
(LPVOID*)&pOpenFileDlg
);
if (FAILED(hr))
{
goto L_Cleanup;
}
{
pOpenFileDlg->SetOptions(
FOS_ALLOWMULTISELECT |
FOS_FILEMUSTEXIST
);
if (pFilters)
{
pOpenFileDlg->SetFileTypes(filterCnt, pFilters);
}
do
{
_tstring strFileDir = strDir;
if (strFileDir.empty())
{
strFileDir = GetCurrentModuleDir();
}
if (IsArchive(strFileDir))
{
strFileDir = GetFileDir(strFileDir);
}
if (IsDirectory(strFileDir))
{
IShellItem* pItem = nullptr;
hr = ::SHCreateItemFromParsingName(CStrUtils::TStrToWStr(strFileDir).c_str(), nullptr, IID_PPV_ARGS(&pItem));
if (FAILED(hr))
{
break;
}
pOpenFileDlg->SetFolder(pItem);
pItem->Release();
}
hr = pOpenFileDlg->Show(hOwner);
if (SUCCEEDED(hr))
{
IShellItemArray* pItemArray = nullptr;
hr = pOpenFileDlg->GetResults(&pItemArray);
DWORD dwCount = 0;
pItemArray->GetCount(&dwCount);
for (DWORD i = 0; i < dwCount; i++)
{
IShellItem* pItem = nullptr;
pItemArray->GetItemAt(i, &pItem);
if (pItem)
{
LPWSTR resultptr = nullptr;
pItem->GetDisplayName(SIGDN_FILESYSPATH, &resultptr);
//记住打开的路径
if (0 == i && nullptr != resultptr)
{
strDir = GetFileDir(CStrUtils::WStrToTStr(resultptr));
}
pItem->Release();
if (resultptr)
{
vFileList.push_back(CStrUtils::WStrToTStr(resultptr));
CoTaskMemFree(resultptr);
}
}
}
if (pItemArray)
{
pItemArray->Release();
}
}
} while (FALSE);
}
L_Cleanup:
if (bComSuccess)
{
::CoUninitialize();
}
return vFileList;
}