问题描述
=============================更新================ =============
我尝试使用Barrnet Chou的建议。我已经使用注释中提到的实现创建了SelectDialog.h
和SelectDialog.cpp
文件,已经在主SelectDialog.h
文件中包含了.cpp
,并且尝试使用该代码从我的主要.cpp
文件中获取,如下所示:
CSelectDialog ofd(TRUE,_T("*.*"),NULL,OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT,_T("All files and folders(*.*)|*.*||"));
CString path,nFile,info;
if (ofd.DoModal() != IDOK)
return;
for (int i = 0; i < ofd.m_SelectedItemList.GetCount(); i++) {
nFile = ofd.GetFileName();
path = ofd.GetFolderPath();
info = ofd.m_SelectedItemList[i].GetString();
}
MessageBox(path);
MessageBox(nFile);
MessageBox(info);
我不知道我做错了什么,但是我仍然遇到同样的问题,我只能选择文件而不能选择文件夹。我还尝试添加标志FOS_PICKFOLDERS
,正如我在调用ofd
varibale的构造函数时提到的IInspectable一样,但它也无济于事。关于我错过的任何想法吗?
================================================ ============
我正在C ++上的Visual Studio 2017上编写基于对话框的MFC应用程序。我想让用户选择一个文件或文件夹,稍后他将写入其中。用户选择所需的文件或文件夹后,我要将路径保存到pFile
变量中以供以后使用。
我已经看到了有关此主题的一些问题,但是这些帖子的所有答案仅提供一种功能-选择文件还是文件夹。
我尝试过的事情:
方法1
OPENFILENAME file;
TCHAR szFileName[MAX_PATH] = _T("");
SecureZeroMemory(&file,sizeof(file));
file.lStructSize = sizeof(OPENFILENAME);
file.hwndOwner = NULL;
file.lpstrFilter = NULL;
file.lpstrFile = szFileName;
file.nMaxFile = MAX_PATH;
file.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
file.lpstrDefExt = "txt";
GetSaveFileName(&file);
pFile = file.lpstrFile;
问题:仅允许选择文件,如下图所示:
方法2
CFileDialog dlgFile(TRUE);
CString fileName;
const int c_cMaxFiles = 100;
const int c_cbBuffSize = (c_cMaxFiles * (MAX_PATH + 1)) + 1;
dlgFile.GetOFN().lpstrFile = fileName.GetBuffer(c_cbBuffSize);
dlgFile.GetOFN().nMaxFile = c_cbBuffSize;
CString file_name,dir_path;
if (dlgFile.DoModal() == IDOK) {
file_name = dlgFile.GetFileName();
dir_path = dlgFile.GetFolderPath();
pFile = dir_path + "\\" + file_name;
}
fileName.ReleaseBuffer();
问题:仅允许用户选择文件,方法如方法1所附图片所示
方法3
LPCSTR m_strFolderPath = ("C:\\"); // Just for sample
LPCSTR m_strDisplayName;
CFolderDialog dlg(_T("Dialog Title"),m_strFolderPath,this);
if (dlg.DoModal() == IDOK)
{
pFile = dlg.GetFolderPath();
}
问题:仅允许用户选择文件夹,如下图所示:
方法4
BROWSEINFO bi;
ZeroMemory(&bi,sizeof(bi));
TCHAR szDisplayName[MAX_PATH];
szDisplayName[0] = (TCHAR)("");
bi.hwndOwner = NULL;
bi.pidlRoot = NULL;
bi.pszDisplayName = szDisplayName;
bi.lpszTitle = _T("Please select a folder for storing received files :");
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lParam = NULL;
bi.iImage = 0;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
TCHAR szPathName[MAX_PATH];
if (NULL != pidl)
{
BOOL bRet = SHGetPathFromIDList(pidl,szPathName);
if (FALSE == bRet)
return;
AfxMessageBox(szPathName);
}
问题:仅允许用户选择文件夹,如方法3附带的图片所示
方法5
为此,我尝试使用IFileDialog
,但不确定如何使用它来选择文件或文件夹。我认为这是我需要的解决方案,如果有人可以推荐我一些使用它的示例,我将不胜感激。我从Microsoft Docs文档中看到了诸如this,在git中还看到了this,还从堆栈溢出问题中看到了this和that one,但是我无法申请他们。我已经尝试过使用前面提到的代码来构造类似的东西,但是我只走了这么远:
IFileDialog *pfd;
IFileSaveDialog *pfsd;
HRESULT hr = pfd->QueryInterface(&pfsd);
LPWSTR *pszName;
if (SUCCEEDED(hr)) {
hr = pfd->GetFileName(pszName);
if (SUCCEEDED(hr)) {
MessageBox((LPCSTR)pszName);
}
}
我真的很感激,如果有人可以向我解释如何使用IFileDialog允许用户选择文件和文件夹,或者如果有其他解决方案可以解决此问题,我想尝试一下。
谢谢。
解决方法
如果要同时选择文件和文件夹,建议您参考以下示例:CSelectDialog
。
说明:
CSelectDialog ofd(TRUE,_T("*.*"),NULL,OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT,_T("All files and folders(*.*)|*.*||") );
if( ofd.DoModal() != IDOK )
return;
for( int i=0; i<ofd.m_SelectedItemList.GetCount(); i++ ){
//...
}
详细实现: 1。
#pragma once
#include <dlgs.h> // for (MULTI)FILEOPENORD
// CSelectDialog
class CSelectDialog : public CFileDialog
{
DECLARE_DYNAMIC(CSelectDialog)
public:
CSelectDialog(BOOL bOpenFileDialog,// TRUE for FileOpen,FALSE for FileSaveAs
LPCTSTR lpszDefExt = NULL,LPCTSTR lpszFileName = NULL,DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT |
OFN_EXPLORER & (~OFN_SHOWHELP),LPCTSTR lpszFilter = NULL,CWnd* pParentWnd = NULL);
virtual ~CSelectDialog();
protected:
virtual void OnInitDone();
virtual void OnFolderChange();
virtual BOOL OnFileNameOK();
static LRESULT CALLBACK WindowProcNew(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
DECLARE_MESSAGE_MAP()
public:
static CString m_strCurrendDirectory;
static CStringArray m_SelectedItemList; /*this list includes files and folders
are selected by user. */
static WNDPROC m_wndProc;
};
#include "stdafx.h"
#include "SelectDialog.h"
#pragma warning( push )
#pragma warning( disable : 4311 4312 )
// CSelectDialog
CString CSelectDialog::m_strCurrendDirectory;
CStringArray CSelectDialog::m_SelectedItemList;
WNDPROC CSelectDialog::m_wndProc = NULL;
IMPLEMENT_DYNAMIC(CSelectDialog,CFileDialog)
CSelectDialog::CSelectDialog(BOOL bOpenFileDialog,LPCTSTR lpszDefExt,LPCTSTR lpszFileName,DWORD dwFlags,LPCTSTR lpszFilter,CWnd* pParentWnd)
:CFileDialog(
bOpenFileDialog,lpszDefExt,lpszFileName,dwFlags | OFN_EXPLORER | OFN_HIDEREADONLY & (~OFN_SHOWHELP),lpszFilter,pParentWnd)
{
dwFlags |= (OFN_EXPLORER | OFN_HIDEREADONLY & (~OFN_SHOWHELP));
};
CSelectDialog::~CSelectDialog()
{
};
BEGIN_MESSAGE_MAP(CSelectDialog,CFileDialog)
END_MESSAGE_MAP()
// CSelectDialog message handlers
BOOL CSelectDialog::OnFileNameOK()
{
if (CFileDialog* pDlg = (CFileDialog*)CWnd::FromHandle(GetParent()->m_hWnd))
{
CWnd* pWnd = pDlg->GetDlgItem(lst2); //getting list
if (pWnd == NULL)
return FALSE;
m_SelectedItemList.RemoveAll(); // emptying list
CListCtrl* wndLst1 = (CListCtrl*)(pWnd->GetDlgItem(1));
int nSelected = wndLst1->GetSelectedCount();
if (!nSelected) // nothing selected -- don't retrieve list
return FALSE;
CString strItemText,strDirectory = m_strCurrendDirectory;
if (strDirectory.Right(1) != _T("\\"))
strDirectory += _T("\\");
CString fileslist = _T("");
pDlg->SendMessage(CDM_GETSPEC,(WPARAM)MAX_PATH,(LPARAM)fileslist.GetBuffer(MAX_PATH));
fileslist.ReleaseBuffer();
strItemText = strDirectory + fileslist;
if(nSelected == 1 && fileslist != _T(""))
{
m_SelectedItemList.Add(strItemText);
return CFileDialog::OnFileNameOK();
}
}
::MessageBeep( MB_ICONQUESTION );
return 1; //don't let the dialog to close
};
void CSelectDialog::OnFolderChange()
{
m_strCurrendDirectory = GetFolderPath();
CFileDialog::OnFolderChange();
};
void CSelectDialog::OnInitDone()
{
m_strCurrendDirectory = GetFolderPath();
CWnd* pFD = GetParent();
HideControl(edt1);
HideControl(cmb1);
HideControl(stc2);
//HideControl(cmb13);
//HideControl(stc3);
CRect rectCancel; pFD->GetDlgItem(IDCANCEL)->GetWindowRect(&rectCancel);
pFD->ScreenToClient(&rectCancel);
CRect rectOK; pFD->GetDlgItem(IDOK)->GetWindowRect(&rectOK);
pFD->ScreenToClient(&rectOK);
pFD->GetDlgItem(IDOK)->SetWindowPos(0,rectCancel.left - rectOK.Width() - 5,rectCancel.top,SWP_NOZORDER | SWP_NOSIZE);
CRect rectList2; pFD->GetDlgItem(lst1)->GetWindowRect(&rectList2);
pFD->ScreenToClient(&rectList2);
pFD->GetDlgItem(lst1)->SetWindowPos(0,rectList2.Width(),abs(rectList2.top - (rectCancel.top - 5)),SWP_NOMOVE | SWP_NOZORDER);
CRect rectStatic;pFD->GetDlgItem(stc3)->GetWindowRect(&rectStatic);
pFD->ScreenToClient(&rectStatic);
pFD->GetDlgItem(stc3)->SetWindowPos(0,rectCancel.left - 375,rectCancel.top + 5,rectStatic.Width(),rectStatic.Height(),SWP_NOZORDER);
CRect rectEdit1;pFD->GetDlgItem(cmb13)->GetWindowRect(&rectEdit1);
pFD->ScreenToClient(&rectEdit1);
pFD->GetDlgItem(cmb13)->SetWindowPos(0,rectCancel.left - 320,rectEdit1.Width() - 15,rectEdit1.Height(),SWP_NOZORDER);
SetControlText(stc3,_T("Item name:"));
SetControlText(IDOK,_T("Select"));
m_wndProc = (WNDPROC)::SetWindowLong(pFD->m_hWnd,GWL_WNDPROC,(long)WindowProcNew);
pFD->CenterWindow();
};
LRESULT CALLBACK CSelectDialog::WindowProcNew(HWND hwnd,LPARAM lParam)
{
if (message == WM_COMMAND)
{
if (HIWORD(wParam) == BN_CLICKED)
{
if (LOWORD(wParam) == IDOK)
{
if (CFileDialog* pDlg = (CFileDialog*)CWnd::FromHandle(hwnd))
{
m_SelectedItemList.RemoveAll(); // emptying list
CWnd* pWnd = pDlg->GetDlgItem(lst2); //getting list
if (pWnd == NULL)
return FALSE;
CListCtrl* wndLst1 = (CListCtrl*)(pWnd->GetDlgItem(1));
int nSelected = wndLst1->GetSelectedCount();
if (!nSelected) // nothing selected -- don't retrieve list
return FALSE;
CString strItemText,strDirectory = m_strCurrendDirectory;
if (strDirectory.Right(1) != _T("\\"))
strDirectory += _T("\\");
int nItem = wndLst1->GetNextItem(-1,LVNI_SELECTED);
CString fileslist = _T("");
pDlg->SendMessage(CDM_GETSPEC,(LPARAM)fileslist.GetBuffer(MAX_PATH));
fileslist.ReleaseBuffer();
// Add directory names to list
while((nSelected--) > 0)
{
strItemText = wndLst1->GetItemText(nItem,0);
strItemText = strDirectory + strItemText;
DWORD attr = GetFileAttributes(strItemText);
if((attr != 0xFFFFFFFF) && (attr & FILE_ATTRIBUTE_DIRECTORY))
m_SelectedItemList.Add(strItemText);
nItem = wndLst1->GetNextItem(nItem,LVNI_SELECTED);
}
// Add FILE names to list
strItemText = _T("");
nSelected = wndLst1->GetSelectedCount();
if(nSelected > m_SelectedItemList.GetCount())
{
int MoreThanOnFile = fileslist.Find(_T("\""));
if(MoreThanOnFile != -1)
{
for(int i=0; i<fileslist.GetLength(); i++)
if(fileslist[i] != '\"')
{
strItemText.AppendFormat(_T("%c"),fileslist[i]);
if(fileslist[i-1] == '\"' && fileslist[i] == ' ')
strItemText.Delete(strItemText.GetLength()-1);
}
else if(!strItemText.IsEmpty())
{
m_SelectedItemList.Add((strDirectory+strItemText));
strItemText.Empty();
}
}
else
m_SelectedItemList.Add(strDirectory+fileslist);
}
pDlg->EndDialog(IDOK);
return NULL;
} // if IDOK
}
} // if BN_CLICKED
}// if WM_COMMAND
return CallWindowProc(m_wndProc,hwnd,message,wParam,lParam);
}
#pragma warning( pop )