大氣象學習園地
- 部落格園
- 新聞
- 新随筆
- 管理
- 訂閱
随筆- 664 文章- 1 評論- 2638
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 )
{
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()
{
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);
}
}
}