打开保存文件对话框(Win32, C++)

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;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值