打开文件对话框在xp和win7上的实现文件任意多选
作者:朱金灿
来源: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 string
if ( 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——第六部分:新的文件对话框
打开文件对话框在xp和win7上的实现文件任意多选的更多相关文章
- git中 .ignore文件的配置 忽略不想上传的文件
1.配置语法: 以斜杠“/”开头表示目录: 以星号“*”通配多个字符: 以问号“?”通配单个字符 以方括号“[]”包含单个字符的匹配列表: 以叹号“!”表示不忽略(跟踪)匹配到的文件或目录: 此外,g ...
- input file实现多次上传文件(不会覆盖上次上传的文件)
html原生的file多选控件:<input class="className" type="file" name="name" ac ...
- react native android 上传文件,Nodejs服务端获取上传的文件
React Native端 使用react-native-image-picker 做出选择图片的操作,选择完成后,直接将图片Post至服务器,保存在服务器的某个地方(保存图片的路径需要公开显示),并 ...
- Reg2Bat_By Slore(生成同名bat文件,支持XP WIN7 WIN7X64).vbs
原文http://slore.blogbus.com/logs/52627038.htmlSlore编写的这个reg文件转换为bat文件,是逐句转换的,不是通过批处理生成临时reg文件然后导入的方法, ...
- MFC 文件对话框
文件对话框的分类 文件对话框分为打开文件对话框和保存文件对话框,相信大家在Windows系统中经常见到这两种文件对话框.例如,很多编辑软件像记事本等都有"打开"选项,选择" ...
- MFC编程入门之十七(对话框:文件对话框)
上一讲介绍的是消息对话框,本节讲解文件对话框.文件对话框也是很常用的一类对话框. 文件对话框的分类 文件对话框分为打开文件对话框和保存文件对话框,相信大家在Windows系统中经常见到这两种文件对话框 ...
- 配置Synergy(Server : XP, client: Win7)
此文只是为了Mark一下配置方法,以防以后重装系统的时候,忘记. 首先,因为我的Server机器是XP,所以要求两台机器,都是安装的x86的版本,而不能是x64的版本. 我用的版本是1.4.11, ...
- 工作总结:文件对话框的分类(C++)
原文地址:http://www.jizhuomi.com/software/173.html 文件对话框分为打开文件对话框和保存文件对话框,相信大家在Windows系统中经常见到这两种文件对话框.例如 ...
- VS2010/MFC对话框:文件对话框
文件对话框 上一讲介绍的是消息对话框,本节讲解文件对话框.文件对话框也是很常用的一类对话框. 文件对话框的分类 文件对话框分为打开文件对话框和保存文件对话框,相信大家在Windows系统中 ...
随机推荐
- py_One
1.Python 标识符 在 Python 里,标识符由字母.数字.下划线组成. 在 Python 中,所有标识符可以包括英文.数字以及下划线(_),但不能以数字开头. Python 中的标识符是区分 ...
- WPF 一个空的 WPF 程序有多少个窗口
原文:WPF 一个空的 WPF 程序有多少个窗口 好多小伙伴说 WPF 的程序有五个窗口,但是我尝试使用了 EnumThreadWindows 去获取的时候居然拿到了 10 多个窗口 在 WPF 内部 ...
- 【BZOJ 1293】[SCOI2009]生日礼物
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 显然的滑动窗口题. (尺取法 如果l..i这一段已经有k种珍珠了. 那么就尝试把l++; (即把l这个影响尝试去掉一下 如果不足k种 ...
- Java基础学习总结(43)——Java8 Lambda揭秘
再了解了Java 8 Lambda的一些基本概念和应用后, 我们会有这样的一个问题: Lambda表达式被编译成了什么?. 这是一个有趣的问题,涉及到JDK的具体的实现. 本文将介绍OpenJDK对L ...
- linux 下同步异步,堵塞非堵塞的一些想法
补充: 发现一个更好的解释样例:同步是一件事我们从头到尾尾随着完毕.异步是别人完毕我们仅仅看结果. 堵塞是完毕一件事的过程中可能会遇到一些情况让我们等待(挂起).非堵塞就是发生这些情况时我们跨过. 比 ...
- BZOJ1830: [AHOI2008]Y型项链 & BZOJ1789: [Ahoi2008]Necklace Y型项链
[传送门:BZOJ1830&BZOJ1789] 简要题意: 给你3个字符串,你每一次可以在一个字符串的末端删除一个字符或添加一个字符,你需要用尽量少的操作次数使得这3个字符串变成一样的. 题解 ...
- invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
Column 'dbo.tbm_vie_View.ViewID' is invalid in the select list because it is not contained in either ...
- spring boot自动配置之jdbc
1.DataSource配置 1.1 默认配置application.xml spring.datasource.url=jdbc:mysql://localhost/test spring.data ...
- java9新特性-9-语法改进:try语句
1. 使用举例 在java8 之前,我们习惯于这样处理资源的关闭: java 8 中,可以实现资源的自动关闭,但是要求执行后必须关闭的所有资源必须在try子句中初始化,否则编译不通过.如下例所 ...
- 继承—Monkey
public class Monkey { public void Monkey(String s){ } public void speak(){ System.out.println(" ...