WTL文件选择对话框 - CFileDialogImpl

来源:互联网 发布:哪里可以买淘宝店铺 编辑:程序博客网 时间:2024/06/15 20:26

WTL文件选择对话框 - CFileDialogImpl

 

1)首先下面的代码是直接使用Win32 API来打开单个文件的代码:

 

void WinSDK_OpenFileDemo()
{
    OPENFILENAME    ofn = {0};
    char   szFile[MAX_PATH];
    *szFile = 0;

    // 开始设置OPENFILENAME结构成员
    ofn.lStructSize   = sizeof(OPENFILENAME);
    ofn.hwndOwner   =   hDlg;
    ofn.lpstrFile   =   szFile;
    ofn.nMaxFile   =   MAX_PATH;
    ofn.lpstrFilter    =  "ESRI Shape文件(*.SHP)/0*.shp/0AutoCAD交换文件(*.DXF;*.DXF.GZ)/0*.dxf;*.dxf.gz /0所有图像文件/0*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.tif;*.tiff/0所有文件(*.*)/0*.*/0/0";

    ofn.nFilterIndex   =  1;
    ofn.lpstrTitle   =  "打开地图文件";
    ofn.lpstrInitialDir = 0;

    ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;

    // 指派给"打开"对话框, 并显示对话框
    if (::GetOpenFileName(&ofn))
    {

        // 现在下面的成员中存放了我们要的文件名
        // ofn.lpstrFile;
    }
}

 

2)类似的用WTL来实现文件打开的功能就简单多了。下面的代码同时打开多个文件:


LRESULT CMainFrame::OnFileOpen(...)
{
    CMyFileDialog  openFileDlg( TRUE,
                                _T("shp"),
                                _T(""),
                                OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT,
                                _T("Shape 文件(*.shp)|*.shp|CAD交换文件(*.dxf)|*.dxf|图像文件|*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.tif;*.tiff|所有文件(*.*)|*.*|"),
                                this->m_hWnd,
                                _T("打开地图文件")
                               );

    if ( IDOK == openFileDlg.DoModal() )
    {
        int nOpenFiles = openFileDlg.GetOpenFileCount();
       
        if (nOpenFiles>0)
        {
            for (int i=0; i<nOpenFiles; i++)
            {
                //文件名:openFileDlg.GetOpenFileAt(i);
            }
        }
    }   

    return 0;
}

 

3)完整的CMyFileDialog的代码如下(在WTL8.0, 8.1测试通过):


class CMyFileDialog :
    public CFileDialogImpl<CMyFileDialog>
{
public:
    // Construction
    CMyFileDialog (BOOL         bOpenFileDialog,
                  _U_STRINGorID szDefExt = 0U,
                  _U_STRINGorID szFileName = 0U,
                  DWORD         dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
                  _U_STRINGorID szFilter = 0U,
                  HWND          hwndParent = NULL,
                  _U_STRINGorID szTitle= 0U ) :
        CFileDialogImpl<CMyFileDialog>(bOpenFileDialog, NULL, NULL, dwFlags, NULL, hwndParent),
        m_sDefExt(szDefExt.m_lpstr),
        m_sFileName(szFileName.m_lpstr),
        m_sFilter(szFilter.m_lpstr),
        m_sTitle(szTitle.m_lpstr),
        _FilesCount(-1)
    {
        m_ofn.lpstrDefExt = m_sDefExt;
        m_ofn.lpstrFilter = PrepFilterString ( m_sFilter );
        m_ofn.lpstrTitle = m_sTitle;

        // setup initial file name
        if ( !m_sFileName.IsEmpty() )
            lstrcpyn ( m_szFileName, m_sFileName, _MAX_PATH );
    }

    // Maps
    BEGIN_MSG_MAP(CMyFileDialog)
        CHAIN_MSG_MAP(CFileDialogImpl<CMyFileDialog>)
    END_MSG_MAP()

    // Overrides
    void OnInitDone ( LPOFNOTIFY lpon )
    {
        GetFileDialogWindow().CenterWindow(lpon->lpOFN->hwndOwner);
    }

    // Get Open Files Count
    int GetOpenFileCount(void)
    {
        if (!m_bOpenFileDialog)
            return 0;

        if (_FilesCount==-1)
        {
            int i = 0;       
            int i0 = 0;
            _FilesCount = 0;
           
            while(i < _MAX_PATH-1){
                if (m_szFileName[i]==0){
                    _FileStarts[_FilesCount++] = i0;
                    i0 = i+1;

                    if (m_szFileName[i+1]==0)
                       break;
                }
                i++;
            }
           
            if (_FilesCount>1){
                _tcsncpy_s(_FileName, _MAX_PATH, m_szFileName, _FileStarts[1]);
                _FileName[ _FileStarts[1] ] = 0;
                _FileName[ _FileStarts[1]-1 ] = _T('//');
                _FilesCount--;
            }
        }

        return _FilesCount;
    }

    // Get Open FileName: index 0-based
    LPCTSTR GetOpenFileAt(int index)
    {
        ATLASSERT(_FilesCount > 0);
       
        if (_FilesCount==1){
            ATLASSERT(index==0);
            return m_szFileName;
        }

        _FileName[ _FileStarts[1] ] = 0;
        _tcscat_s(_FileName, _MAX_PATH, m_szFileName + _FileStarts[index+1]);
    
        return _FileName;
    }

protected:
    LPCTSTR PrepFilterString ( CString& sFilter )
    {
        LPTSTR psz = sFilter.GetBuffer(0);
        LPCTSTR pszRet = psz;

        while ( '/0' != *psz )
        {
            if ( '|' == *psz )
                *psz++ = '/0';
            else
                psz = CharNext ( psz );
        }

        return pszRet;
    }   
  
    int     _FilesCount;
    int     _FileStarts[_MAX_PATH];
    TCHAR   _FileName[_MAX_PATH];

    CString m_sDefExt, m_sFileName, m_sFilter, m_sTitle;
};

 

4)结论

编写windows客户端界面程序有不少于100种方法可用。经典的如MFC;时髦的如DHTML,Form,WPF;纯理论的如SDK;跨平台的如Java(这里面就有N多框架),QT等等。可是至今我觉得还是WTL/ATL最干净利落,也最强大。尤其WTL,虽然不是MS力推的主流,但这主要是因为MS为了.NET平台推广而有意压制的技术。WTL也是最适合我们玩的东西。

 

 

 

 

 

 

 

 

 

 

原创粉丝点击