作者:朱金灿

来源:http://blog.csdn.net/clever101

在xp系统上进行文件多选,实际上其文件字符串数组的缓冲区是有限,并不能支持选择任意多个文件,为此以前我还写过一篇文章:使用CFileDialog的钩子函数解决对话框的多选问题。实际上这种做法在vista系统及win7系统上并不支持。那么如何在vista系统及win7系统支持打开文件对话框任意多选文件呢?我想到windows是一个基于com的系统,没准使用com接口能做到。事实上是这样的,需要使用一个叫IFileOpenDialog的接口类。下面是示例代码:

// Return the file system path for a given IShellItem.
static bool PathFromShellItem ( IShellItem* pItem, CString& sPath )
{HRESULT hr;LPOLESTR pwsz = NULL;hr = pItem->GetDisplayName ( SIGDN_FILESYSPATH, &pwsz );if ( FAILED(hr) )return false;sPath = pwsz;CoTaskMemFree ( pwsz );return true;
}// Convert a pipe-separated list of filter strings into a vector of
// COMDLG_FILTERSPEC. The vector<CString> is needed to actually hold the strings
// that the COMDLG_FILTERSPEC structs will point to.
static bool BuildFilterSpecList (_U_STRINGorID szFilterList,COMDLG_FILTERSPEC*& pVecFilter,int& nFilterNum )
{std::vector<CString> vecsFilterParts;CString sFilterList = szFilterList.m_lpstr;CString sToken;int nIdx = 0;// Split the passed-in filter list on pipe characters (MFC-style)for(;;){sToken = sFilterList.Tokenize(_T("|"), nIdx );if ( sToken.IsEmpty() )break;vecsFilterParts.push_back ( sToken );}// There should be an even number of tokens in the stringif ( vecsFilterParts.size() & 1 ){ATLASSERT(0);vecsFilterParts.pop_back();}if(vecsFilterParts.empty())return false;nFilterNum = vecsFilterParts.size()/2.0;pVecFilter = new COMDLG_FILTERSPEC[nFilterNum];// Use each pair of tokens for a COMDLG_FILTERSPEC struct./*for (std::vector<CString>::size_type i = 0; i < vecsFilterParts.size(); i += 2 )*/for (std::vector<CString>::size_type i = 0; i <nFilterNum; i++){USES_CONVERSION;int j = i*2;std::wstring strName = A2W(vecsFilterParts[j]);pVecFilter[i].pszName = new WCHAR[strName.length()+1];memset((void*)pVecFilter[i].pszName,'\0',(strName.length()+1)*sizeof(WCHAR));wcsncpy((wchar_t*)pVecFilter[i].pszName,strName.c_str(),strName.length());j = j+1;std::wstring strSpec = A2W(vecsFilterParts[j]);pVecFilter[i].pszSpec = new WCHAR[strSpec.length()+1];memset((void*)pVecFilter[i].pszSpec,'\0',(strSpec.length()+1)*sizeof(WCHAR));wcsncpy((wchar_t*)pVecFilter[i].pszSpec,strSpec.c_str(),strSpec.length());}
//  return !vecFilters.empty();return true;
}void CMultiSelectDlg::OnBnClickedBtnVista()
{// TODO: 在此添加控件通知处理程序代码HRESULT hr;CComPtr<IFileOpenDialog> pDlg;
//  std::vector<CString> vecsFilterParts;
//  std::vector<COMDLG_FILTERSPEC> vecFilters;COMDLG_FILTERSPEC* pVecFilter = NULL;;int nFilterNum = 0;//   std::vector<std::wstring> vecFilters;CString sDlgTitle = _T("Multi-selection File Open Dialog");CString sOKButtonLabel = _T("确定");CString sFilenameLabel = _T("文件名(N):");DWORD dwFlags = 0;// Create the file-open dialog COM object.hr = pDlg.CoCreateInstance( __uuidof(FileOpenDialog) );if ( FAILED(hr) )return;// Tell the dlg to load the state data associated with this GUID:// {7D5FE367-E148-4a96-B326-42EF237A3662}// This is not strictly necessary for our app (normally you'd wand loads// and saves to share the same state data) but I'm putting this in for the demo.static const GUID guidFileOpen = { 0x7D5FE367, 0xE148, 0x4A96, { 0xB3, 0x26, 0x42, 0xEF, 0x23, 0x7A, 0x36, 0x62 } };hr = pDlg->SetClientGuid ( guidFileOpen );// Call this helper function to convert a pipe-separated file spec list // (like MFC uses) to a vector of COMDLG_FILTERSPEC.if ( BuildFilterSpecList(_T("Text files (*.txt)|*.txt|Executable files (*.exe;*.dll)|*.exe;*.dll|All files (*.*)|*.*|"),pVecFilter,nFilterNum))hr = pDlg->SetFileTypes(nFilterNum,pVecFilter);// Set some other properties of the dialog. It's not the end of the world if// any of these calls fail.USES_CONVERSION; hr = pDlg->SetTitle (A2W(sDlgTitle));hr = pDlg->SetOkButtonLabel(A2W(sOKButtonLabel));hr = pDlg->SetFileNameLabel(A2W(sFilenameLabel));// Set the multi-select option flag.hr = pDlg->GetOptions ( &dwFlags );hr = pDlg->SetOptions ( dwFlags | FOS_ALLOWMULTISELECT );// Set up our event listener.
//  CComObjectStackEx<CDlgEventHandler> cbk;// Show the dialog!hr = pDlg->Show ( m_hWnd );//if ( bAdvised )// pDlg->Unadvise ( dwCookie );// Get the list of selected items and add each filename to the list ctrl.if ( SUCCEEDED(hr) ){CComPtr<IShellItemArray> pItemArray;hr = pDlg->GetResults ( &pItemArray );if ( SUCCEEDED(hr) ){DWORD cSelItems;hr = pItemArray->GetCount ( &cSelItems );if ( SUCCEEDED(hr) ){int nCount = 0;for ( DWORD j = 0; j < cSelItems; j++ ){CComPtr<IShellItem> pItem;hr = pItemArray->GetItemAt ( j, &pItem );if ( SUCCEEDED(hr) ){CString sPath;if ( PathFromShellItem ( pItem, sPath ) ){m_listbox.AddString(sPath);nCount++;}}}CString str;str.Format(_T("%u files selected"), nCount);m_static.SetWindowText(str);}}}for (int i  = 0;i<nFilterNum;i++){delete []pVecFilter[i].pszName;delete []pVecFilter[i].pszSpec;}delete []pVecFilter;
}

值得注意的是这个做法并不兼容xp系统,因此在使用哪种做法时需要你先对操作系统的版本进行判断。我专门写了一个例程供大家参考:VC文件多选对话框

参考文献:

1. WindowsVista for Developers——第六部分:新的文件对话框

2. IFileDialog使用指南

转载于:https://www.cnblogs.com/lanzhi/p/6470137.html

打开文件对话框在xp和win7上的实现文件任意多选相关推荐

  1. 对于win7上共享的文件在工作组的其他电脑上无权限访问的问题解决,以及工作组电脑无需密码登入访问设置

    1.工作组(家庭组)电脑无需密码设置 a.将本机的guest账户解除禁用:计算机--(右键)管理--本地用户和组--用户--Guest--(右键)属性--(取消)账户已禁用: b.控制面板--管理工具 ...

  2. pdf上传及预览;file上传pdf文件及预览;vue上传pdf文件及预览;vue-pdf预览pdf文件

    需求:上传pdf文件,并点击可以打开预览.使用input的file功能即可完成,预览只需要跳转到pdf的url地址即可.还可以配合vue-pdf直接预览,点击看这篇. 以下代码可直接复制使用!!!有效 ...

  3. 服务器上传excel文件并读取数据,asp.net上传Excel文件并读取数据的实现方法

    前言 本文主要给大家介绍了关于asp.net上传Excel文件并读取数据的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 实现如下: 前台代码:使用服务端控件实现上传 服务端 ...

  4. 启用tim无法访问文件夹_如何在三星手机上启用安全文件夹

    启用tim无法访问文件夹 The Secure Folder is a useful feature on Samsung devices that allows you to keep apps a ...

  5. java scp 文件夹_利用scp 远程上传下载文件/文件夹

    scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器 ...

  6. html5 上传超大文件,HTML5教程 如何拖拽上传大文件

    本篇教程探讨了HTML5教程 如何拖拽上传大文件,希望阅读本篇文章以后大家有所收获,帮助大家HTML5+CSS3从入门到精通 . < 前言: 大文件传输一直是技术上的一大难点.文件过大时,一些性 ...

  7. php上传压缩文件,8行代码实现PHP上传RAR文件并解压

    今天闲的没事,写了一个这样的小演示: $dir=getcwd();//获取绝对路径 if ($_POST["sub"]){ ?$tname=$_FILES["upload ...

  8. ajax上传本地音频文件,使用ajax将音频blob上传到文件夹中

    我正在构建一个录音项目,我想通过blob将音频上传到文件夹(上传). 这是我迄今取得的成就: var url = URL.createObjectURL(blob); var li = documen ...

  9. linux上下载文件夹命令,linux命令(上传下载文件)

    1.从服务器上下载文件 scp username@servername:/path/filename /var/www/local_dir(本地目录) 例如scp root@192.168.0.101 ...

  10. linux ftp去不了文件损坏,Linux下使用ftp上传压缩文件,windows下载打开损坏问题

    由于业务部门提出新的需求,需要在业务系统上进行修改,于是准备把生产环境上的系统下载到本地进行相应的修改(系统是第三方做的),服务器用的是CentOS6.3,由于安全问题,服务器的登录需要经过堡垒机,不 ...

最新文章

  1. HTML小知识点积累
  2. 关于 SAP Commerce Cloud 启动时报 Address already in use - bind 的错误消息
  3. Windows下搭建Android开发环境
  4. 穿山甲插屏广告居中_穿山甲跻身广告联盟头部阵营 如何实现增量创新?
  5. Java笔记(十七) 异步任务执行服务
  6. 2012第50周星期日
  7. Atitit table的读取与遍历 jquery jsoup 目录 1. atitit.gui控件的定位与选择器 1 2. 读取表格流程 遍历表格table 1 3. W3cdom标准化 1
  8. .NetCore获取拼多多平台优惠券
  9. 播放超1200w,仅21w粉的B站UP主靠带货也能引爆B站
  10. 基于饥饿博弈搜索算法的函数寻优算法
  11. 人脑能用计算机算法吗,电脑到人脑,计算机必不可少的4大思维
  12. bzoj 4430: [Nwerc2015]Guessing Camels赌骆驼
  13. 不是所有物联网平台都适合系统集成
  14. RK3568平台开发系列讲解(安卓适配篇)Android11 预安装应用功能
  15. XFTP连接服务器成功,传输文件失败解决方案
  16. sparkRDD算子数据处理实践
  17. 14、函数的嵌套调用
  18. BUU XSS COURSE 1 wp XSS平台在线注册
  19. 王者荣耀交流协会PSP Daily项目Postmortem结果
  20. flutter获取验证码输入框组件

热门文章

  1. 在.net开发过程中遇到的问题种种
  2. this.$router.push相关的vue-router的导航方法
  3. Python数据结构之字节,字节数组
  4. 理解OpenCL数据类型
  5. IOS TableView详解
  6. axis2远程调用webservice例子(返回xml用dom4j解析)
  7. (转)git clone: error: RPC failed; result=18, HTTP code = 200 解决办法
  8. 空值的日期类型和update 中的null
  9. C#的yield return是怎么被调用到的?
  10. TELERIK Reporting 实践