MFC实现文件夹对话框

 
文件对话框属于通用对话框范畴(另外还有颜色,查找,查找替换,字体,打印等对话框)。
借助MFC现成的类CFileDialog你可以轻易操作文件对话框。

CFileDialog dlg( TRUE, _T( "txt" ), _T( "b.txt" ), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, _T( "文本|*.txt|所有文件|*||" ) );
if ( dlg.DoModal() == IDOK ) {
// dlg.GetPathName();
}

第一个参数TRUE:打开文件对话框,FALSE:保存文件对话框
第二个参数表示要打开文件的默认扩展名(保存文件是显得比较重要)
第三个参数表示要打开的目标文件名,如果未提供扩展名将使用第二个参数指定的名称
第四个参数 OFN_FILEMUSTEXIST表示目标必须存在, OFN_HIDEREADONLY不显示只读文件,还有些其他参数可用OFN_XXX自行检索之
第五个参数表示过滤字符串表,按照这个格式"标题|过滤表|标题|过滤表||"



打开一个文件夹对话框没有现成的MFC类可用,你需要借助一类称为Shell操控的API函数。
三个步骤:配置对话框,打开对话框,获取返回值(文件夹路径)。

// 获取特定文件夹的LPITEMIDLIST,可以将之理解为HANDLE
// 所谓的特定文件夹,你可以用CSIDL_XXX来检索之。
LPITEMIDLIST rootLoation;
SHGetSpecialFolderLocation( NULL, CSIDL_DESKTOP, &rootLoation );
if ( rootLoation == NULL ) {
   // unkown error
   // return
}

// 配置对话框
BROWSEINFO bi;
ZeroMemory( &bi, sizeof( bi ) );
bi.pidlRoot = rootLoation; // 文件夹对话框之根目录,不指定的话则为我的电脑
bi.lpszTitle = _T( "对话框抬头" ); // 可以不指定
// bi.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS;

// 打开对话框, 有点像DoModal
LPITEMIDLIST targetLocation = SHBrowseForFolder( &bi );
if ( targetLocation != NULL ) {
   TCHAR targetPath[ MAX_PATH ];
   SHGetPathFromIDList( targetLocation, targetPath );
   // MessageBox( targetPath );
}


更详细的配置

如果为BROWSEINFO配置回调函数,那么在对话框有事件发生时(比如对话框刚被打开等),回调函数被调用,这样你就有机会得以进行更详细的配置,下面是一个封装完好的例子:

//------------------------------------------------------
// 头文件

#ifndef MFCExt_Control_FolderDialog_H_INCLUDED_
#define MFCExt_Control_FolderDialog_H_INCLUDED_

namespace MFCExt { namespace Control {

    class CFolderDialog {
    public:
        CFolderDialog( 
            int rootDirFlag = CSIDL_DESKTOP, 
            const CString& focusDir = _T( "" ),
            const CString& title = _T( "" ),
            DWORD browseInfoFlag = 0
            );

        INT_PTR DoModal();
        const CString& GetPath() const { return finalPath_; }

    private:
        void OnCallback( HWND hWnd, UINT uMsg, LPARAM lParam );
        void SetFocusDirectory();

    private:
        const int rootDirFlag_;
        const CString focusDir_;
        const CString title_;
        const DWORD browseInfoFlag_;

        HWND hDialog_;
        CString finalPath_;

        friend int CALLBACK BrowseDirectoryCallback( HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData );
    };   

} }



namespace MFCExt {
    using Control::CFolderDialog;
}



namespace AutoTest {
    void TestMFCExtFolderDialog();
}

#endif // MFCExt_Control_FolderDialog_H_INCLUDED_

//------------------------------------------------------
// 实现文件

#include "stdafx.h"
#include "FolderDialog.h"

namespace MFCExt { namespace Control {
    
    static int CALLBACK BrowseDirectoryCallback( HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData ) {
        CFolderDialog* folderDialog = reinterpret_cast< CFolderDialog* >( lpData ); 
        folderDialog->OnCallback( hWnd, uMsg, lParam );            
        return 0;
    }    



    CFolderDialog::CFolderDialog( 
        int rootDirFlag, 
        const CString& focusDir,
        const CString& title,
        DWORD browseInfoFlag
        )
        : rootDirFlag_( rootDirFlag )
        , focusDir_( focusDir )
        , title_( title )
        , browseInfoFlag_( browseInfoFlag )
        , hDialog_( NULL )
        , finalPath_( _T( "" ) )
    {}



    INT_PTR CFolderDialog::DoModal() {
        LPITEMIDLIST rootLoation;
        SHGetSpecialFolderLocation( NULL, rootDirFlag_, &rootLoation );
        if ( rootLoation == NULL ) {
            throw new CInvalidArgException();
        }

        BROWSEINFO browseInfo;
        ZeroMemory( &browseInfo, sizeof( browseInfo ) );
        browseInfo.pidlRoot = rootLoation;
        browseInfo.ulFlags = browseInfoFlag_;
        browseInfo.lpszTitle = title_;
        browseInfo.lpfn = BrowseDirectoryCallback;
        browseInfo.lParam = ( LPARAM )this;
        
        LPITEMIDLIST targetLocation = SHBrowseForFolder( &browseInfo );
        if ( targetLocation == NULL ) {
            return IDCANCEL;
        }
        
        TCHAR targetPath[ MAX_PATH ] = { _T( '\0' ) };
        SHGetPathFromIDList( targetLocation, targetPath );
        finalPath_ = targetPath;
        
        return IDOK;
    }



    void CFolderDialog::OnCallback( HWND hWnd, UINT uMsg, LPARAM lParam ) {
        hDialog_ = hWnd;
        if ( uMsg == BFFM_INITIALIZED ) {
            SetFocusDirectory();            
        }
    }



    void CFolderDialog::SetFocusDirectory() {
        ASSERT( hDialog_ != NULL );
        if ( focusDir_ != _T( "" ) ) {
            ::SendMessage( hDialog_, BFFM_SETSELECTION, TRUE, ( LPARAM )focusDir_.GetString() ); 
        }
    } 

} }



namespace AutoTest {

    void TestMFCExtFolderDialog() {
        {        
            MFCExt::CFolderDialog dlg;
            if ( dlg.DoModal() == IDOK ) {
                AfxMessageBox( dlg.GetPath() );
            }
        }

        {        
            MFCExt::CFolderDialog dlg( CSIDL_DRIVES, _T( "C:\\Windows" ), _T( "Title" ) );
            if ( dlg.DoModal() == IDOK ) {
                AfxMessageBox( dlg.GetPath() );
            }
        }
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值