MFC选择目录SHBrowseForFolder选择文件CFileDialog对话框设置默认路径

CFileDialog会自动记住上一次路径,
SHBrowseForFolder需要写个回调函数,
传值给BROWSEINFO
BaseFunc.h
#include <string>

using namespace std;
namespace BaseFunc
{
    // 选择文件,可设置定位到默认目录
    unsigned selFile(string &strFile,const string &strExt,bool bOpen);

    // 选择目录,可设置定位初始目录
    unsigned selDir(string &strDir,void *hwnd = NULL);
}
BaseFunc.cpp
#include "stdafx.h"
#include <Windows.h>
#include "BaseFunc.h"

using namespace std;
using namespace BaseFunc;

unsigned BaseFunc::selFile( string &strFile,const string &strExt,bool bOpen )
{
    string strDir = "D:\\Downloads";//这里通过strFile解析目录,CFileDialog会自动记住
    string filename = "hi.txt";  //通过strFile解析文件名
    string filter = strExt + "文件 (*." + strExt + ")|*." + strExt + "||";
    string ext = "." + strExt;

    CFileDialog dlg(bOpen,ext.c_str(),filename.c_str(),OFN_READONLY|OFN_OVERWRITEPROMPT,filter.c_str(),NULL);
    dlg.GetOFN().lpstrInitialDir = strFile.c_str();// 默认目录

    if (dlg.DoModal())
    {
        strFile = dlg.GetPathName();
        return IDOK;
    }

    return IDCANCEL;
}

int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)
{
    switch(uMsg)
    {
    case BFFM_INITIALIZED:
        ::SendMessage(hwnd,BFFM_SETSELECTION,TRUE,lpData);
        break;
    }

    return 0;
}

unsigned BaseFunc::selDir( string &strDir,void *hwnd/* = NULL*/ )
{
    char szDir[MAX_PATH];
    BROWSEINFO bi; 
    bi.hwndOwner = (HWND)hwnd;
    bi.pidlRoot = NULL;
    bi.pszDisplayName = szDir;
    bi.lpszTitle = "选择位置:";
    bi.iImage = 0;

    bi.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
    bi.lpfn = BrowseCallbackProc;
    bi.lParam = (LPARAM)(LPCTSTR)strDir.c_str();

    LPITEMIDLIST lp = SHBrowseForFolder(&bi);
    if (lp && SHGetPathFromIDList(lp,szDir))
    {
        strDir = szDir;
        return IDOK;
    }

    return IDCANCEL;
}
selDirDlg.cpp
void CselDirDlg::OnBnClickedButtonFile()
{
    CString sFile;
    GetDlgItemText(IDC_EDIT_FILE,sFile);

    std::string strFile = sFile;
    if (IDOK == BaseFunc::selFile(strFile,"mp3",true))
    {
        SetDlgItemText(IDC_EDIT_FILE,strFile.c_str());
    }
}


void CselDirDlg::OnBnClickedButtonDir()
{
    CString sDir;
    GetDlgItemText(IDC_EDIT_DIR,sDir);//可扩展个返回string

    std::string strDir = sDir;
    if (IDOK == BaseFunc::selDir(strDir,GetSafeHwnd()))
    {
        SetDlgItemText(IDC_EDIT_DIR,strDir.c_str());
    }
}
需要源码的留下邮箱。
url:http://greatverve.cnblogs.com/archive/2012/12/16/SHBrowseForFolder-CFileDialog.html 

注意:目录浏览函数不仅可以选择目录,也可以用来选择一个文件。

下例是一个既可以选择目录也可以选择文件的代码范例。该范例中详细说明了相关消息的含义及使用方法。

 

//目录浏览对话框可能会像回调函数发送3种消息:

//BFFM_INITIALIZED --   通知对话框已经初始化结束。

//                   回调函数响应此消息时通常是做初始选择

//BFFM_SELCHANGED -- 目录浏览对话框当前选择项发生变化时调用此消息。

//                   回调函数响应此消息时通常是显示所选项的相关信息

//BFFM_VALIDATEFAILED -- 表示用户按确认按钮时却发现浏览对话框的编辑框内输入了一个非法名称

//                   回调函数响应此消息时通常是提示客户选择项非法,并确定是否继续显示该对话框

//回调函数可以发送如下几个消息给目录浏览对话框,从而改变目录浏览对话框的面目

//BFFM_SETSELECTION  -- 改变当前选择项目

//BFFM_ENABLEOK      -- 改变“确认”按钮的状态

//BFFM_SETSTATUSTEXT-- 改变目录浏览对话框中状态行消息,当然前提是目录浏览对话框中有状态行

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

{

      switch (uMsg)

      {

      case BFFM_INITIALIZED:

           {

                 //BFFM_INITIALIZED表示浏览对话框已经初化结束,参数lParam为NULL

 

                 //设置初始选项

                 ::SendMessage(hwnd,BFFM_SETSELECTION,TRUE,lpData);

 

                 //关于BFFM_SETSELECTION消息的说明

                 //wParam :标记lParam参数包含一个ITEMIDLIST结构(PIDL)还是一个目录路径名

                 //          如果为TRUE,lParam内容为路径名;否则lParam包含一个路径PIDL。

                 //lParam :内容为浏览对话框所选的路径。如果wParam为TRUE,lParam内容为一个

                 //         以NULL结尾的字符串的指针,否则为PIDL

 

                 break;

           }

      case BFFM_SELCHANGED:

           {

                 //BFFM_SELCHANGED表示选择项已经发生变化,参数lParam包含列表中最新选中项的条目ID

                

                 ITEMIDLIST * pidl; 

                 char path[MAX_PATH]; 

 

                 //根据条目ID取路径信息

                 pidl = (ITEMIDLIST*) lParam;

                 if (SHGetPathFromIDList(pidl, path))

                 {

                      //使得“确认”按钮生效

                      //关于BFFM_ENABLEOK消息的说明

                      //wParam :无意义,可设置为0

                      //lParam :如果为非0,则使能确认按钮;否则失效“确认”按钮

                      ::SendMessage(hwnd,BFFM_ENABLEOK,0,TRUE);

 

                      //读属性

                      DWORD attributes = ::GetFileAttributes(path);

 

                      //命令状态行显示当前所选项的全路径名及其文件属性

                      //关于BFFM_SETSTATUSTEXT消息的说明

                      //wParam :无意义,可设置为0

                      //lParam :指向一个内含状态行提示信息的字符串

                      CString strText;

                      strText.Format("%s%s%s%s",

                            path,

                            attributes & FILE_ATTRIBUTE_HIDDEN ? ",H":"",

                            attributes & FILE_ATTRIBUTE_READONLY ? ",R":"",

                            attributes & FILE_ATTRIBUTE_SYSTEM ? ",S":""

                            );

                      ::SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)(LPTSTR)(LPCTSTR)strText);

                 }

                 else

                 {

                      //使得“确认”按钮失效

                      ::SendMessage(hwnd,BFFM_ENABLEOK,0,FALSE);

                      //清状态行信息

                      ::SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)(LPTSTR)(LPCTSTR)"");

                 }

 

                 break;

           }

      case BFFM_VALIDATEFAILED:

           {

                 //BFFM_VALIDATEFAILED表示用户在浏览对话框的编辑框内输入了一个非法名称

                 //该消息在用户按“确认”时送出——当然前提是编辑框内输入的名称非法

                 //lParam参数包含了非法输入内容的地址,应用程序可以使用这个消息提示用户输入非法。

                 //另外,此消息的回调函数返回0表示目录浏览对话框旋即关闭,返回其他值则允许对话框继续显示。

 

                 //仅当目录浏览对话框中含有编辑框并且设置了BIF_VALIDATE标记才可能出现此消息

                 //即BROWSEINFO结构中ulFlags含有BIF_EDITBOX|BIF_VALIDATE标志

                 CString strTip;

                 strTip.Format("目录%s非法!",lParam);

 

                 //返回0允许对话框提前关闭,SHBrowseForFolder()返回NULL

                 AfxMessageBox(strTip);

                 return 0;

 

                 //返回1对话框继续显示,因为对话框仍继续显示,可以在状态行显示出错消息

                 //注意:如果此时仍用AfxMessageBox来显示提示信息,提示信息框关闭后,要使焦点重返目录

                 //浏览对话框,需要客户手工移动鼠标激活该对话框才行,这样会使得后继操作不是很方便,所以在状态行显示提示信息比较好

                 //::SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)(LPTSTR)(LPCTSTR)strTip);

                 //return 1;

 

                 break;

           }

      default:

           {

                 ASSERT(FALSE);

           }

      }

      return 0;

}

 

void CModifyFileAttributeDlg::OnSelectpath()

{文件目录选择函数SHBrowseForFolder()及其回调函数

      UpdateData(TRUE);

 

      BROWSEINFO bi; 

      char dispname[MAX_PATH], path[MAX_PATH]; 

      ITEMIDLIST * pidl; 

     

      //定义目录浏览对话框的属主

      bi.hwndOwner = 0;

      //确定浏览范围(根目录)

      //只有根目录及其子目录下可以浏览

      //定义为NULL表示名字空间下皆可用

      bi.pidlRoot = NULL;

      //用于接收用户所选目录的显示名

      //经测试,该项并不包含全路径名

      bi.pszDisplayName = dispname; 

      //设置目录浏览对话框的对话框标题

      bi.lpszTitle = "请选择路径:"; 

      //设置状态

      //BIF_BROWSEINCLUDEFILES

      //BIF_RETURNONLYFSDIRS表示只返回目录,

      //BIF_STATUSTEXT表示对话框中有状态行

      //BIF_EDITBOX表示对话框中有编辑框

      //BIF_VALIDATE表示客户按“确认”按钮时检查编辑框内容的合法性

      bi.ulFlags = BIF_BROWSEINCLUDEFILES|BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT|BIF_EDITBOX|BIF_VALIDATE;

      //设置回调函数

      //如果需要设置初始选择项、显示所选项的相关信息、让系统自动校验用户输入

      //的合法性,那么应该使用回调函数;否则可将该项设置为NULL

      bi.lpfn = BrowseCallbackProc; 

      //设置回调函数的lParam参数

      //此处用来传递目录浏览对话框的初始选项

      bi.lParam = (LPARAM)(LPCTSTR)m_strFilePath; 

      //用来接收所选目录的图标(系统图像列表中的序号)

      bi.iImage = 0; 

     

      //显示目录浏览对话框

      if (pidl = SHBrowseForFolder(&bi))

      { 

           //将PIDL转换为字符串

           if (SHGetPathFromIDList(pidl, path))

           {

                 //更新对话框显示,以显示用户的最新选择

                 m_strFilePath = path;

                 TRACE("%s",bi.pszDisplayName);

                 UpdateData(FALSE);

           }

      }

 }

posted @ 2012-12-16 14:01  大气象  阅读(19349)  评论(1编辑  收藏  举报
http://www.tianqiweiqi.com