由于各种应用,我们需要调用系统的打开文件对话框或者打开文件夹对话框,或两者兼有。今遇到这个情况已经解决,特写下这篇博文。

1.打开文件对话框常用的方法是使用系统的CFileDialog。这里介绍另外一种方法就是使用OPENFILENAME这个结构体和GetOpenFileName()这个函数,可以实现单选文件或者多选文件,代码如下:

需引入头文件#include "CommDlg.h"

  1. TCHAR szBuffer[MAX_PATH] = {0};
  2. OPENFILENAME ofn= {0};
  3. ofn.lStructSize = sizeof(ofn);
  4. ofn.hwndOwner = m_hWnd;
  5. ofn.lpstrFilter = _T("Exe文件(*.exe)\0*.exe\0所有文件(*.*)\0*.*\0");//要选择的文件后缀
  6. ofn.lpstrInitialDir = _T("D:\\Program Files");//默认的文件路径
  7. ofn.lpstrFile = szBuffer;//存放文件的缓冲区
  8. ofn.nMaxFile = sizeof(szBuffer)/sizeof(*szBuffer);
  9. ofn.nFilterIndex = 0;
  10. ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER ;//标志如果是多选要加上OFN_ALLOWMULTISELECT
  11. BOOL bSel = GetOpenFileName(&ofn);

这样就可以打开选择文件对话框了。可以选择需要的文件。szBuffer是存放的选择的文件路径。

1.1 多选

下面的代码演示了如何得到GetOpenFileName允许多选的情况下选择的文件名
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
 OPENFILENAME ofn;
 TCHAR szOpenFileNames[80*MAX_PATH];
 TCHAR szPath[MAX_PATH];
 TCHAR szFileName[80*MAX_PATH];
 TCHAR* p;
 int nLen = 0;
 ZeroMemory( &ofn, sizeof(ofn) );
 ofn.Flags = OFN_EXPLORER | OFN_ALLOWMULTISELECT;
 ofn.lStructSize = sizeof(ofn);
 ofn.lpstrFile = szOpenFileNames;
 ofn.nMaxFile = sizeof(szOpenFileNames);
 ofn.lpstrFile[0] = '/0';
 ofn.lpstrFilter = TEXT("All Files(*.*)/0*.*/0");
 if( GetOpenFileName( &ofn ) )
 {  
  //把第一个文件名前的复制到szPath,即:
  //如果只选了一个文件,就复制到最后一个'/'
  //如果选了多个文件,就复制到第一个NULL字符
  lstrcpyn(szPath, szOpenFileNames, ofn.nFileOffset );
  //当只选了一个文件时,下面这个NULL字符是必需的.
  //这里不区别对待选了一个和多个文件的情况
  szPath[ ofn.nFileOffset ] = '/0';
  nLen = lstrlen(szPath);
  
  if( szPath[nLen-1] != '//' )   //如果选了多个文件,则必须加上'//'
  {
   lstrcat(szPath, TEXT("//"));
  }
  
  p = szOpenFileNames + ofn.nFileOffset; //把指针移到第一个文件
  
  ZeroMemory(szFileName, sizeof(szFileName));
  while( *p )
  {   
   lstrcat(szFileName, szPath);  //给文件名加上路径  
   lstrcat(szFileName, p);    //加上文件名  
   lstrcat(szFileName, TEXT("/n")); //换行   
   p += lstrlen(p) +1;     //移至下一个文件
  }
  MessageBox(NULL, szFileName, TEXT("MultiSelect"), MB_OK);
 }
} 

2.打开文件夹对话框方法:

需引入头文件:#include "Shlobj.h"

  1. TCHAR szBuffer[MAX_PATH] = {0};
  2. BROWSEINFO bi;
  3. ZeroMemory(&bi,sizeof(BROWSEINFO));
  4. bi.hwndOwner = NULL;
  5. bi.pszDisplayName = szBuffer;
  6. bi.lpszTitle = _T("从下面选文件夹目录:");
  7. bi.ulFlags = BIF_RETURNFSANCESTORS;
  8. LPITEMIDLIST idl = SHBrowseForFolder(&bi);
  9. if (NULL == idl)
  10. {
  11. return;
  12. }
  13. SHGetPathFromIDList(idl,szBuffer);

上面的代码就可以打开一个选择文件夹对话框了。

3.选择文件或文件夹对话框的调用:

  1. TCHAR szBuffer[MAX_PATH] = {0};
  2. BROWSEINFO bi;
  3. ZeroMemory(&bi,sizeof(BROWSEINFO));
  4. bi.hwndOwner = NULL;
  5. bi.pszDisplayName = szBuffer;
  6. bi.lpszTitle = _T("从下面选择文件或文件夹:");
  7. bi.ulFlags = BIF_BROWSEINCLUDEFILES;
  8. LPITEMIDLIST idl = SHBrowseForFolder(&bi);
  9. if (NULL == idl)
  10. {
  11. return;
  12. }
  13. SHGetPathFromIDList(idl,szBuffer);

使用了上面的代码就可以根据需要选择文件或者文件夹了。

4. 创建一个可以新建文件夹且指定选中初始路径的浏览文件夹对话框

由于我在实际工作中需要的就是一个有新建文件夹功能且指定初始选中路径的浏览文件夹对话框,就把这个需求当做扩展应用吧,由于对话框样式由ulFlags标记确定,而在系统头文件SHLOBJ.h头文件中给出的对话框样式只有如下几种

// Browsing for directory.

#define BIF_RETURNONLYFSDIRS   0x0001  // For finding a folder to start document searching

#define BIF_DONTGOBELOWDOMAIN  0x0002  // For starting the Find Computer

#define BIF_STATUSTEXT         0x0004

#define BIF_RETURNFSANCESTORS  0x0008

#define BIF_EDITBOX            0x0010

#define BIF_VALIDATE           0x0020   // insist on valid result (or CANCEL)

#define BIF_BROWSEFORCOMPUTER  0x1000  // Browsing for Computers.

#define BIF_BROWSEFORPRINTER   0x2000  // Browsing for Printers

#define BIF_BROWSEINCLUDEFILES 0x4000  // Browsing for Everything

没有满足我需求的样式,通过csdn查到其实有一个支持新建文件夹功能的样式值0x40,通常网络上给出宏为BIF_NEWDIALOGSTYLE和BIF_USENEWUI,由于不知道在具体哪个头文件中,所以我们可以在代码中自己定义一下这两个宏,具体如下

#define BIF_NEWDIALOGSTYLE   0x40

#define BIF_USENEWUI (BIF_NEWDIALOGSTYLE|BIF_EDITBOX)

这样一来第一个问题解决了,那么如何让对话框有初始选中的文件夹路径呢,我起初想着通过pidlRoot,结果撞了一鼻子灰,原来设定初始选中文件夹路径,是通过那个神奇的回调函数来实现,换句话来说你调用SHBrowseForFolder也就好比你调用了CDialog:: DoModal()函数,具体这个对话框里面的类似初始化,选择等操作的不同实现就通过lpfn这个回调函数来实现了。

下面给出这个简单扩展的代码

#define BIF_NEWDIALOGSTYLE   0x40

int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)

{

if(uMsg == BFFM_INITIALIZED)

{

SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);

}

return 0;

}

void CSisAppendMidDlg::OnButtonSisdes()

{

// TODO: Add your control notification handler code here

BROWSEINFO bi;

char Buffer[MAX_PATH];

//初始化入口参数bi开始

bi.hwndOwner = NULL;

bi.pidlRoot =NULL;//初始化制定的root目录很不容易

bi.pszDisplayName = Buffer;//此参数如为NULL则不能显示对话框

bi.lpszTitle = "选择Sis目标文件路径";

bi.ulFlags = BIF_EDITBOX|BIF_NEWDIALOGSTYLE;

CFileFind   finder;

if(finder.FindFile(m_cSisDes)==FALSE)

{

bi.lParam =0;

bi.lpfn = NULL;

}

else

{

bi.lParam = (long)(m_cSisDes.GetBuffer(m_cSisDes.GetLength()));//初始化路径,形如(_T("c:\\Symbian"));

bi.lpfn = BrowseCallbackProc;

}

finder.Close();

bi.iImage=IDR_MAINFRAME;

//初始化入口参数bi结束

LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//调用显示选择对话框

if(pIDList)

{

SHGetPathFromIDList(pIDList, Buffer);

//取得文件夹路径到Buffer里

m_cSisDes = Buffer;//将路径保存在一个CString对象里

}

UpdateData(FALSE);

// free memory used

IMalloc * imalloc = 0;

if ( SUCCEEDED(SHGetMalloc( &imalloc)))

{

imalloc->Free (pIDList);

imalloc->Release();

}

}

好了,简单扩展就到这里为止,至于很多大神需要再做更深一步的扩展,那就沿着这个思路走下去就可以了。毕竟我目前也就走到这一步了,呵呵。

C++文件(夹)选择对话框的更多相关文章

  1. [VB.NET]调用系统的文件夹选择对话框

    以下示例代码展示如何调用系统的文件夹选择对话框: Private Function SelectFolder(ByVal Describe As String, Optional ByVal Show ...

  2. c# 打开、保存文件对话框 和 文件夹选择对话框

    1. OpenFileDialog openImageDialog = new OpenFileDialog(); openImageDialog.Filter = "Image Files ...

  3. 【转】python qt(pyqt)的文件打开、文件保存、文件夹选择对话框

    import PyQt4.QtCore,PyQt4.QtGui # 获取文件路径对话框 file_name = QFileDialog.getOpenFileName(self,"open ...

  4. WPF:自定义Metro样式文件夹选择对话框FolderBrowserDialog

    1.前言 WPF并没有文件选择对话框,要用也就只有使用Winform版的控件.至今我也没有寻找到一个WPF版本的文件选择对话框. 可能是我眼浊,如果各位知道有功能比较健全的WPF版文件选择对话框.文件 ...

  5. 在WPF中使用文件夹选择对话框

    开发中有时会想实现"选择某个文件夹"的效果: 在WPF中,使用Microsoft.Win32.OpenFileDialog只能选择文件,FolderBrowserDialog只能用 ...

  6. (WPF) 文件和文件夹选择对话框。

    点击button,选择一个excel文件,并将文件名显示在textbox上. private void btnSelectErrorTableFile_Click(object sender, Rou ...

  7. MFC 文件夹选择对话框

    CString setSavePath() { CString strPath = _T(""); HRESULT hr; LPITEMIDLIST pItemList; BROW ...

  8. Asp.net点击按钮弹出文件夹选择框的实现(网页)

    本文地址:http://www.cnblogs.com/PiaoMiaoGongZi/p/4092112.html 在Asp.net网站实际的开发中,比如:需要实现点击一个类似于FileUpload的 ...

  9. javascript文件夹选择框的两种解决方案

    javascript文件夹选择框的两种解决方案 解决方案1:调用windows 的shell,但会有安全问题. * browseFolder.js * 该文件定义了BrowseFolder()函数,它 ...

随机推荐

  1. 笔记-scrapy-item

    笔记-scrapy-item 1.总述 爬虫数据保存用,一般情况下无需过多处理,引用并使用Field方法即可. 2.使用 常规使用: import scrapy class Product(scrap ...

  2. Echarts 解决饼图文字过长重叠的问题

    之前在网上查找了很多关于解决饼图文字描述过长导致重叠的问题,找了很多一直没有一个合适的解决方案,最后自己只能花时间研究echarts文档,功夫不负有心人,终于解决了文字重叠展示不全等问题. 废话不多说 ...

  3. Spark 源码阅读——任务提交过程

    当我们在使用spark编写mr作业是,最后都要涉及到调用reduce,foreach或者是count这类action来触发作业的提交,所以,当我们查看这些方法的源码时,发现底层都调用了SparkCon ...

  4. Android面试收集录4 Fragment详解

    1.什么是Fragment? 你可以简单的理解为,Fragment是显示在Activity中的Activity. 它可以显示在Activity中,然后它也可以显示出一些内容. 因为它拥有自己的生命周期 ...

  5. 全方位认识HDMI接口技术

    HDMI接口并不是一个开放的标准.制造商必须向HDMI标准制定协会支付版税,来换取一个生产许可证.不过这个版税可不便宜,每年要交纳15000美元的许可费,并且更黑的是每生产一个HDMI接口就要支付0. ...

  6. 1 Mongodb安装

    1.NoSQL简介 NoSQL,全名Not Only SQL,指的是非关系型的数据库 随着访问量的上升,网站的数据库性能出现了问题,于是NoSQL被设计出来了 优点.缺点 优点 高扩展性 分布式计算 ...

  7. java身份证计算年龄

    技术交流群: 233513714 /** * 根据身份证计算年龄 * * @param idcard * @return */ public static Integer idCardToAge(St ...

  8. 用Mapreduce求共同好友

    import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs ...

  9. Android学习记录(2)—Android中数据库的常见操作

    android中数据库操作是非常常见了,我们会经常用到,操作的方法也有很多种形式,这里我就把最常见的两种形式记录下来了,以备以后用到方便查看.我就不写注释和解释了,因为android数据库的操作和其它 ...

  10. 《Cracking the Coding Interview》——第16章:线程与锁——题目1

    2014-04-27 19:09 题目:线程和进程有什么区别? 解法:理论题,操作系统教材上应该有很详细的解释.我回忆了一下,写了如下几点. 代码: // 16.1 What is the diffe ...