[英]Enable user to choose folders and files on dialog based MFC app
============================== 更新 ================== ============
我试过使用 Barrnet Chou 的建议。 我已经使用评论中提到的实现创建了SelectDialog.h
和SelectDialog.cpp
文件,我已经在主.cpp
文件中包含了SelectDialog.h
并且我尝试使用我的主.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
作为IInspectable提到的,当我调用构造函数ofd
varibale,但它并没有帮助的。 关于我错过了什么的任何想法?
================================================== ==========
我正在用 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
,但我不确定如何使用它来选择文件或文件夹。 我认为这就是我需要的解决方案,如果有人可以向我推荐一些如何使用它的示例,我将不胜感激? 我已经看到了一些诸如这个来自微软的文档文件和这一个从Git和也这样和一个从堆栈溢出的问题,但我没能运用它们。 我尝试使用前面提到的代码构建类似的东西,但我只做到了这一点:
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, 0,0, SWP_NOZORDER | SWP_NOSIZE);
CRect rectList2; pFD->GetDlgItem(lst1)->GetWindowRect(&rectList2);
pFD->ScreenToClient(&rectList2);
pFD->GetDlgItem(lst1)->SetWindowPos(0,0,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,rectCancel.top, 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, UINT message, WPARAM wParam, 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, (WPARAM)MAX_PATH,
(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 )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.