繁体   English   中英

允许用户在基于对话框的 MFC 应用程序上选择文件夹和文件

[英]Enable user to choose folders and files on dialog based MFC app

============================== 更新 ================== ============

我试过使用 Barrnet Chou 的建议。 我已经使用评论中提到的实现创建了SelectDialog.hSelectDialog.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM