创建MFC对话框以让用户选择文件路径

时间:2015-11-26 02:12:47

标签: windows mfc dialog

正如标题所说,我正在尝试创建基于MFC对话框的应用程序,让用户选择文件目标文件夹。

我是通过使用CMFCShellTreeCtrl来做到这一点的。但是,不知何故,只有一个根项目是桌面。我希望看到所有项目,例如我的电脑 C驱动器等。

您能告诉我错误的原因以及如何解决问题。感谢。

enter image description here

编辑:抱歉,我忘记发布我的代码了。 (非常简单的浏览对话框)

// BrowseDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MFC Grab to FTP.h"
#include "BrowseDlg.h"
#include "afxdialogex.h"


// CBrowseDlg dialog

IMPLEMENT_DYNAMIC(CBrowseDlg, CDialog)

CBrowseDlg::CBrowseDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CBrowseDlg::IDD, pParent)
{

}

CBrowseDlg::~CBrowseDlg()
{
}

void CBrowseDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_PATH, m_PathTree);
}


BEGIN_MESSAGE_MAP(CBrowseDlg, CDialog)
    ON_NOTIFY(TVN_SELCHANGED, IDC_PATH, &CBrowseDlg::OnTvnSelchangedMfcshelltree1)
    ON_BN_CLICKED(IDOK, &CBrowseDlg::OnBnClickedOk)
END_MESSAGE_MAP()


// CBrowseDlg message handlers

BOOL CBrowseDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // Set the icon for this dialog.  The framework does this automatically
    // when the application's main window is not a dialog
    m_PathTree.Expand(m_PathTree.GetRootItem(),TVE_EXPAND);

    return TRUE;  // return TRUE  unless you set the focus to a control
}

void CBrowseDlg::OnTvnSelchangedMfcshelltree1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: Add your control notification handler code here
    *pResult = 0;
}


void CBrowseDlg::OnBnClickedOk()
{
    m_PathTree.GetItemPath(path,m_PathTree.GetSelectedItem());

    // TODO: Add your control notification handler code here
    CDialog::OnOK();
}

//

#pragma once
#include "afxshelltreectrl.h"


// CBrowseDlg dialog
// header file
class CBrowseDlg : public CDialog
{
    DECLARE_DYNAMIC(CBrowseDlg)

public:
    CBrowseDlg(CWnd* pParent = NULL);   // standard constructor
    virtual ~CBrowseDlg();

// Dialog Data
    enum { IDD = IDD_BROWSER };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnTvnSelchangedMfcshelltree1(NMHDR *pNMHDR, LRESULT *pResult);
    CString path;
    CMFCShellTreeCtrl m_PathTree;
    afx_msg void OnBnClickedOk();
    virtual BOOL OnInitDialog();
};

2 个答案:

答案 0 :(得分:0)

问题是CWinAppEx::InitShellManager()未初始化。你必须手动完成。要对其进行初始化,您需要在OnInitInstance()派生类的CWinApp中调用$(".zoom").each(function(arg, el){ var image = $(el).find("img"); $(el).zoom({ on: 'mouseover', url: image.attr("src").replace("small", "big") }); });

答案 1 :(得分:0)

如果您只想选择一个文件夹,可以选择使用CMFCShellTreeCtrlIFileDialog

这是我的选择文件夹对话框的代码(相当复杂,因为我仍然希望使用XFolderDialog支持Windows XP):

HINSTANCE hEasyCTXP_DLL = NULL;

// Select Folder Dialog -- uses either CXFolderDialog or IFileDialog
// to open a folder picker dialog depending on OS version
// returns "" if Cancel was pressed or something else went wrong
// Note: This is just multi-byte code and not yet unicode compatible!
BOOL SelectFolder(LPSTR sFolder, LPCTSTR sTitle = "Choose Folder")
{
    OSVERSIONINFOEX osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    if (GetVersionEx((OSVERSIONINFO *)&osvi) && osvi.dwMajorVersion >= 6) // Vista or higher?
    {
        if (!(hEasyCTXP_DLL = LoadLibrary("XPHelper.dll")))
        {
            AfxMessageBox("Error opening Select Folder dialog. XPHelper.dll may not be installed properly.");
            return FALSE;
        }
        else
        {
            BOOL (__cdecl *pSelectFolder)(LPSTR, LPCTSTR);
            pSelectFolder = (BOOL (__cdecl *)(LPSTR, LPCTSTR))GetProcAddress(hEasyCTXP_DLL, "SelectFolder");
            if (pSelectFolder) 
            {
                return (*pSelectFolder)(sFolder, sTitle);
            }
            else
            {
                AfxMessageBox("Error opening Select Folder dialog. (SelectFolder() function entry point not found.)");
                return FALSE;
            }
        }   
    }
    else // XP
    {   
        CXFolderDialog dlg(sFolder);        
        dlg.SetTitle(sTitle);
        if (dlg.DoModal() == IDOK)
        {
            CString csPath = dlg.GetPath();
            strcpy(sFolder, (LPCTSTR)csPath);
            return TRUE;
        }
        else
            return FALSE;
    }
}

这是我在XPHelper.dll中提供的功能。这个DLL只是延迟加载,如果使用Vista或更高版本的操作系统,所以主程序不会因为在Windows XP中缺少依赖性而失败:

// sFolder should be at least MAX_FILE in size!
extern "C" BOOL SelectFolder(LPSTR sFolder, LPCTSTR sTitle)
{
    BOOL bRet = TRUE;

    IFileDialog *pfd;
    LPWSTR pwstrPath;
    HRESULT hr;
    if (SUCCEEDED(hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd))))
    {
        DWORD dwOptions;
        hr = pfd->GetOptions(&dwOptions);
        if (SUCCEEDED(hr))
            hr = pfd->SetOptions(dwOptions | FOS_PICKFOLDERS);  // put IFileDialog in folder mode
        if (SUCCEEDED(hr))
        {
            WCHAR wcTitle[MAX_PATH+1];
            if (MultiByteToWideChar(CP_ACP, 0, sTitle, (int)min(strlen(sTitle), MAX_PATH), wcTitle, sizeof(MAX_PATH + 1)))
            {
                wcTitle[min(strlen(sTitle), MAX_PATH)] = '\0';
                pfd->SetTitle(wcTitle);         // Set dialog title
            }

            char *cp = sFolder;
            WCHAR wcDefaultPath[MAX_PATH+1];
            IShellItem *psi;
            if (MultiByteToWideChar(CP_ACP, 0, cp, (int)strlen(cp), wcDefaultPath, MAX_PATH + 1))
            {
                wcDefaultPath[strlen(cp)] = '\0';
                if (SUCCEEDED(::SHCreateItemFromParsingName(wcDefaultPath, NULL, IID_PPV_ARGS(&psi))))
                {
                    hr = pfd->SetFileName(wcDefaultPath);
                    hr = pfd->SetFolder(psi);
                    psi->Release();
                }
            }
        }
        if (SUCCEEDED(hr))
            hr = pfd->Show(AfxGetMainWnd()->GetSafeHwnd());
        if (SUCCEEDED(hr))
        {
            IShellItem *psi;
            if (SUCCEEDED(pfd->GetResult(&psi)))
            {
                if(SUCCEEDED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pwstrPath)))
                {
                    int nSize = (int)wcslen(pwstrPath);
                    WideCharToMultiByte(CP_ACP, 0, pwstrPath, nSize, sFolder, MAX_PATH+1, NULL, NULL);
                    sFolder[nSize] = '\0';
                    ::CoTaskMemFree(pwstrPath);
                }
                else
                {
                    AfxMessageBox("IShellItem::GetDisplayName() failed.");
                    bRet = FALSE;
                }

                psi->Release();
            }
            else
            {
                AfxMessageBox("IFileDialog failed.");
                bRet = FALSE;
            }
        }
        pfd->Release();
    }

    if(!SUCCEEDED(hr))
        bRet = FALSE;       

    return bRet;
}