簡體   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