zoukankan      html  css  js  c++  java
  • Common Item Dialog, 打开文件对话框

    最近写音乐播放器练手。音乐需要一个添加音乐文件的对话框,便在msdn上找到了一个新姿势,就是Common Item Dialog.

    MSDN链接:http://msdn.microsoft.com/en-us/library/windows/desktop/bb776913(v=vs.85).aspx

    按照msdn的说法,Common Item Dialog用来代替以前Common File Dialog去打开或保存文件。Common Item Dialog需要win vista以上操作系统, 拥有Open dialog 和 Save dialog.

    先给出一个简单的例子,这个例子是我用来打开音乐文件的:

        //打开文件窗口
        std::vector<std::wstring> showOpenFile()
        {
            HRESULT hr = S_OK;
            std::vector<std::wstring> filePaths;
    
            IFileOpenDialog *fileDlg = NULL;
            hr = CoCreateInstance(CLSID_FileOpenDialog,
                NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&fileDlg));
            if (FAILED(hr)) return filePaths;
            ON_SCOPE_EXIT([&] { fileDlg->Release(); });
    
            IKnownFolderManager *pkfm = NULL;
            hr = CoCreateInstance(CLSID_KnownFolderManager,
                NULL,
                CLSCTX_INPROC_SERVER,
                IID_PPV_ARGS(&pkfm));
            if (FAILED(hr)) return filePaths;
            ON_SCOPE_EXIT([&] { pkfm->Release(); });
    
            IKnownFolder *pKnownFolder = NULL;
            hr = pkfm->GetFolder(FOLDERID_PublicMusic, &pKnownFolder);
            if (FAILED(hr)) return filePaths;
            ON_SCOPE_EXIT([&] { pKnownFolder->Release(); });
    
            IShellItem *psi = NULL;
            hr = pKnownFolder->GetShellItem(0, IID_PPV_ARGS(&psi));
            if (FAILED(hr)) return filePaths;
            ON_SCOPE_EXIT([&] { psi->Release(); });
    
            hr = fileDlg->AddPlace(psi, FDAP_BOTTOM);
            COMDLG_FILTERSPEC rgSpec[] = {
                { L"音乐文件", L"*.mp3;*.wav;" }
            };
            fileDlg->SetFileTypes(1, rgSpec);
    
            DWORD dwOptions;
            fileDlg->GetOptions(&dwOptions);
            fileDlg->SetOptions(dwOptions | FOS_ALLOWMULTISELECT);
            hr = fileDlg->Show(NULL);
            if (SUCCEEDED(hr)) {
                IShellItemArray *pRets;
                hr = fileDlg->GetResults(&pRets);
                if (SUCCEEDED(hr)) {
                    DWORD count;
                    pRets->GetCount(&count);
                    for (DWORD i = 0; i < count; i++) {
                        IShellItem *pRet;
                        LPWSTR nameBuffer;
                        pRets->GetItemAt(i, &pRet);
                        pRet->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &nameBuffer);
                        filePaths.push_back(std::wstring(nameBuffer));
                        pRet->Release();
                        CoTaskMemFree(nameBuffer);
                    }
                    pRets->Release();
                }
            }
            return filePaths;
        }
    View Code

    ps:我使用了头文件如下:

    #include <Shlobj.h>
    #include <Shobjidl.h>
    #include <iostream>
    #include <vector>

    该函数返回一个文件列表的容器,储存的文件的绝对路径。

    其中ON_SCOPE_EXIT宏是引用http://www.cnblogs.com/fuzhe1989/p/3524249.html 中的资源管理。

    大致说明如下:

    • 创建一个IFileOpenDialog接口指针的实例 fileDlg。
    • IKnownFolderManager *pkfm, IKnownFolder *pKnownFolder 两个接口是用来设置默认的路径的,此例把默认路径设置为用户目录下的音乐文件夹。
    • 设置文件类型。这里用到了IFileOpenDialog接口的SetFileTypes方法,该方法参数如下:
    HRESULT SetFileTypes(
      [in]  UINT cFileTypes,
      [in]  const COMDLG_FILTERSPEC *rgFilterSpec
    );

        第一个参数 cFileTypes是第二个参数数组元素的个数。

        参数 rgFilterSpec 用来设置文件类型,例如:

    COMDLG_FILTERSPEC rgSpec[] =
    { 
        { szJPG, L"*.jpg;*.jpeg" },
        { szBMP, L"*.bmp" },
        { szAll, L"*.*" },
    };
    • 因为本例添加音乐文件需要支持添加多个文件,因此设置允许选择多个文件。方法如下:
            DWORD dwOptions;
            fileDlg->GetOptions(&dwOptions);
            fileDlg->SetOptions(dwOptions | FOS_ALLOWMULTISELECT);
    • 接下来就可以调用IFileOpenDialog接口的Show()方法了。用户选择后,如果是单个文件,调用GetResult([out]  IShellItem **ppsi)方法获得选中的文件,如果是选择了多个文件,调用GetResults([out]  IShellItemArray **ppenum)方法。区别在于前者获取IShellItem接口,后者获取IShellItemArray接口。

    IShellItemArray基本上就是IShellItem接口数组,根据其方法名字就很容易使用。因此说下IShellItem.

    IShellItem可以看成将文件路径封装起来的接口,可以通过调用其GetDisplayName([in] SIGDN sigdnName, [out] LPWSTR *ppszName方法。第一个参数sigdnName决定了返回文件字符串的格式,此处我们使用SIGDN_DESKTOPABSOLUTEPARSING参数,返回文件的绝对路径。 不过要记得释放返回的字符串,释放方法为使用CoTaskMemFree()函数。

    基本上到此就完成了我们的目的...不过确实..使用起来有点那么麻烦..所以我是自己封装成函数了..

  • 相关阅读:
    Hihocoder-小Hi的烦恼
    Python包下载与离线安装
    Shell输出颜色设置
    MySQL主从配置
    MySQL初始化与用户配置
    [转]常用 GDB 命令中文速览
    搭建github静态博客
    树莓派上手
    vim安装与配置
    数组,看了你就懂了!
  • 原文地址:https://www.cnblogs.com/zihuyishi/p/3529294.html
Copyright © 2011-2022 走看看