【问题标题】:Creating MFC dialog to let the user choose file path创建 MFC 对话框让用户选择文件路径
【发布时间】:2015-11-26 02:12:47
【问题描述】:

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

我通过使用CMFCShellTreeCtrl 来做到这一点。然而,不知何故,只有一个根项目是 Desktop。我想查看我的电脑、C盘等所有项目。

请您告诉我出了什么问题以及如何解决。谢谢。

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

// 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();
};

【问题讨论】:

    标签: windows mfc dialog


    【解决方案1】:

    问题是CShellManager 没有初始化。您必须手动完成。要初始化它,您需要在您的CWinApp 派生类的OnInitInstance() 中调用CWinAppEx::InitShellManager()。

    【讨论】:

      【解决方案2】:

      如果您只想选择一个文件夹,可以使用CMFCShellTreeCtrl 的替代方法:IFileDialog。

      这是我的选择文件夹对话框的代码(相当复杂,因为我仍然希望使用 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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-12
        • 2017-04-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多