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

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. python-8错误调试测试

    1-错误处理 import logging try: print('try.......') r = 10/0 except ValueError as e: print('result:', e) ...

  2. HTML中body相关标签-03

    今日主要内容: 列表标签 <ul>.<ol>.<dl> 表格标签 <table> 表单标签 <fom> 一.列表标签 列表标签分为三种. 1 ...

  3. 《Cracking the Coding Interview》——第12章:测试——题目3

    2014-04-24 23:28 题目:玩象棋游戏,你要设计一个bool型的方法来检测一个棋子能否移动到指定位置. 解法:不同的棋子有不同的移动规则,那么应该采取棋子基类实现接口,各个棋子子类来实现的 ...

  4. Django笔记 —— MySQL安装

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...

  5. unity灯光Lightmapping、LightProbes

    1.为什么要用Lightmapping? 简单来说就是实时灯光计算十分耗时,随着光源越多,计算耗时会倍增.使用Lightmap模拟灯光带来的效果,便不用去计算灯光,会带来性能上的大大提升. 当然一个复 ...

  6. 爬虫:Scrapy9 - Feed exports

    实现爬虫时最经常提到的需求就是能合适的保存爬取到的数据,或者说,生成一个带有爬取数据的“输出文件”(通常叫“输出 feed”),来供其它系统使用. Scrapy 自带了 Feed 输出,并且支持多种序 ...

  7. HDU 4107 Gangster(线段树 特殊懒惰标记)

    两种做法. 第一种:标记区间最大值和最小值,若区间最小值>=P,则本区间+2c,若区间最大值<P,则本区间+c.非常简单的区间更新. 最后发一点牢骚:最后query查一遍就行,我这个2B竟 ...

  8. python与MySQL数据库

    python与MySQL数据库 慕课网连接 我使用的软件:python2.7 + MySQL+ Navicat for MySQL + Atom 注意:你的数据库表格类型的引擎为:InnoDB :字符 ...

  9. WebIDE

    1 1 1 WebIDE 是什么? WebIDE 是 一款在线集成开发环境( Integrated Development Environment ). 开发者只需要一个浏览器就可以编写代码,并在We ...

  10. RabbitMQ磁盘警报

    RabbitMQ磁盘警报 当可用磁盘空间低于配置的限制(默认为50MB)时,将触发警报,所有生产者将被阻止.目标是避免填满整个磁盘,这将导致节点上的所有写操作失败,并可能导致RabbitMQ终止.为了 ...