Мультеселектный файл-диалог для WTL
От: Юнусов Булат Россия  
Дата: 16.08.02 21:03
Оценка: 46 (10)
#Имя: FAQ.wtl.filedialog.multiselect
В WTL::CFileDialog поддержку OFN_ALLOWMULTISELECT почему то не прикрутили, а парсить ручками парочно.

В общем что-то оторвал от втль, что-то от мфс.
Юзать как обычно в мфс юзали (не забывайте только, что разделители фильтра в втль нули, а не |)

        char szFilter[] = _T("Statistica Files\0*.sta\0All Files\0*.*\0");
        CFileDialogEx dlg(TRUE, _T("sta"), NULL, OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST, szFilter, this->m_hWnd);   
        dlg.m_ofn.lpstrTitle = _T("Select the statistica files to merge");

        if(IDOK == dlg.DoModal())
        {
            POSITION pos = dlg.GetStartPosition();
            while(pos)
            {
                CString fileName = dlg.GetNextPathName(pos);
            }
        }


Плюс еще прикрутил возможность получать весь список выбранных файлов как CSimpleArray<CString>. Зачем? — дотнетовый мультиселектный диалог тоже схожим образом поступает потому что. Ежли не юсфульно завсегда оторвать можно.
        if(IDOK == dlg.DoModal())
        {
            CSimpleArray<CString> FileNames = dlg.GetFileNames();
        }



Надеюсь минут пять кому то сэкономил.

Файл
atlfiledialogex.h
#pragma once

#ifndef __ATLFILEDIALOGEX_H__
#define __ATLFILEDIALOGEX_H__

#ifndef __cplusplus
    #error ATL requires C++ compilation (use a .cpp suffix)
#endif

#ifndef __ATLAPP_H__
    #error atlfiledialogex.h requires atlapp.h to be included first
#endif

#ifndef __ATLWIN_H__
    #error atlfiledialogex.h requires atlwin.h to be included first
#endif

#ifndef __ATLDLGS_H__
    #error atlfiledialogex.h requires atldlgs.h to be included first
#endif

#ifndef __ATLMISC_H__
    #error atlfiledialogex.h requires atlmisc.h to be included first
#endif

namespace WTL {

#ifndef POSITION
struct __POSITION {};
typedef __POSITION* POSITION;
#endif

class CFileDialogEx :
    public CFileDialogImpl<CFileDialogEx>
{
public:
    TCHAR m_szFileName[_MAX_PATH * 1000]; // Потому что по умолчанию маловато будет
    CSimpleArray<CString> m_FileNames;  

    CFileDialogEx(BOOL bOpenFileDialog, 
        LPCTSTR lpszDefExt = NULL,
        LPCTSTR lpszFileName = NULL,
        DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
        LPCTSTR lpszFilter = NULL,
        HWND hWndParent = NULL)
        : CFileDialogImpl<CFileDialogEx>(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
    { 
        m_szFileName[0] = '\0';
        m_ofn.lpstrFile = m_szFileName;
        m_ofn.nMaxFile = sizeof(m_szFileName); 
    }

    virtual ~CFileDialogEx()
    {
        m_FileNames.RemoveAll();
    }

    const CSimpleArray<CString>& GetFileNames() const
    {
        return m_FileNames;
    }

    POSITION GetStartPosition() const
    {
        return (POSITION) m_ofn.lpstrFile;
    }

    CString GetNextPathName(POSITION& pos) const
    {
        BOOL bExplorer = m_ofn.Flags & OFN_EXPLORER; // что для WTL завсегда правда
        TCHAR chDelimiter;
        if (bExplorer)
            chDelimiter = '\0';
        else
            chDelimiter = ' ';

        LPTSTR lpsz = (LPTSTR)pos;


        if (lpsz == m_ofn.lpstrFile)
        {
            if ((m_ofn.Flags & OFN_ALLOWMULTISELECT) == 0)
            {
                pos = NULL;
                return m_ofn.lpstrFile;
            }

            while(*lpsz != chDelimiter && *lpsz != '\0')
                lpsz = _tcsinc(lpsz);
            lpsz = _tcsinc(lpsz);

            if (*lpsz == 0)
            {
                pos = NULL;
                return m_ofn.lpstrFile;
            }
        }

        CString strPath = m_ofn.lpstrFile;
        if (!bExplorer)
        {
            LPTSTR lpszPath = m_ofn.lpstrFile;
            while(*lpszPath != chDelimiter)
                lpszPath = _tcsinc(lpszPath);
            strPath = strPath.Left(lpszPath - m_ofn.lpstrFile);
        }

        LPTSTR lpszFileName = lpsz;
        CString strFileName = lpsz;

        while(*lpsz != chDelimiter && *lpsz != '\0')
            lpsz = _tcsinc(lpsz);

        if (!bExplorer && *lpsz == '\0')
            pos = NULL;
        else
        {
            if (!bExplorer)
                strFileName = strFileName.Left(lpsz - lpszFileName);

            lpsz = _tcsinc(lpsz);
            if (*lpsz == '\0') 
                pos = NULL;
            else
                pos = (POSITION)lpsz;
        }

        if (!strPath.IsEmpty())
        {
            LPCTSTR lpsz = _tcsrchr(strPath, '\\');
            if (lpsz == NULL)
                lpsz = _tcsrchr(strPath, '/');

            if (lpsz != NULL && (lpsz - (LPCTSTR)strPath) == strPath.GetLength()-1)
            {
                ATLASSERT(*lpsz == '\\' || *lpsz == '/');
                return strPath + strFileName;
            }
        }
        return strPath + '\\' + strFileName;
    }

    INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
    {
        INT_PTR rc = CFileDialogImpl<CFileDialogEx>::DoModal(hWndParent);

        if(IDOK == rc)
        {
            m_FileNames.RemoveAll();

            POSITION pos = GetStartPosition();
            while(pos)
            {
                m_FileNames.Add(GetNextPathName(pos));
            }
        }

        return rc;
    }

    DECLARE_EMPTY_MSG_MAP()
};

} // namespace WTL

#endif // __ATLFILEDIALOGEX_H__
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.