C++文件和文件夹选择

2 篇文章 0 订阅

一、MFC版本

WinFileSelectDlg.h

#pragma once
#ifdef WIN32
#include <afxdlgs.h>
#include <dlgs.h> 
#include <vector>

class WinFileSelectDlg : public CFileDialog
{
    DECLARE_DYNAMIC(WinFileSelectDlg)

public:
    WinFileSelectDlg(BOOL bOpenFileDialog,
        LPCTSTR lpszDefExt = NULL,
        LPCTSTR lpszFileName = NULL,
        DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT |
        OFN_EXPLORER & (~OFN_SHOWHELP),
        LPCTSTR lpszFilter = NULL,
        CWnd* pParentWnd = NULL);
    virtual ~WinFileSelectDlg();

    enum { ID_LISTVIEW = lst2 };


    //ODM_VIEW_ICONS = 0x7029,

    enum LISTVIEWCMD
    {
        ODM_VIEW_ICONS = 0x7029,
        ODM_VIEW_LIST = 0x702b,
        ODM_VIEW_DETAIL = 0x702c,
        ODM_VIEW_THUMBS = 0x702d,
        ODM_VIEW_TILES = 0x702e,
        ODM_VIEW_LARGE_ICONS = 0x704f,
    };

    void SetSpecialStrings(wchar_t* sItemName, wchar_t* sSelect)
    {
        m_strItemName = CString(sItemName);
        m_strSelect = CString(sSelect);

    }

protected:
    virtual BOOL OnInitDialog();
    virtual void OnInitDone();
    virtual void OnFolderChange();
    virtual BOOL OnFileNameOK();
    virtual void OnFileNameChange();
    static LRESULT CALLBACK WindowProcNew(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);


    BOOL SetListView(LISTVIEWCMD cmd);
    DECLARE_MESSAGE_MAP()
private:
    CString m_strItemName;
    CString m_strSelect;
    static CString m_strError;

    CString m_strLastSelectList;
    static bool m_bSelectVirtualItem;

public:
    static CString m_strCurrendDirectory;
    static CStringArray m_SelectedItemList;
    static WNDPROC m_wndProc;

    static bool m_bCmb13Changed;


    static bool IsVirtualItemSelected()
    {
        return m_bSelectVirtualItem;
    }
    static void SetErrorInfo(wchar_t* sError)
    {
        m_strError = CString(sError);
    }
    static bool HaveSelectSomething()
    {
        return m_SelectedItemList.GetCount() > 0;
    }
};
#endif // WIN32

WinFileSelectDlg.cpp

#ifdef WIN32
#define _AFXDLL
#include <afxcmn.h>
#include "WinFileSelectDlg.h"
#include <shlobj.h>
#include <exception>
#pragma comment( lib, "shell32.lib")
using std::exception;
#pragma warning( push )
#pragma warning( disable : 4311 4312 )

#define MAX_PATH_EditControl          4*1024*1024
CString WinFileSelectDlg::m_strCurrendDirectory;
CStringArray WinFileSelectDlg::m_SelectedItemList;
CString WinFileSelectDlg::m_strError;
WNDPROC WinFileSelectDlg::m_wndProc = NULL;
bool WinFileSelectDlg::m_bCmb13Changed = false;
bool WinFileSelectDlg::m_bSelectVirtualItem = false;
IMPLEMENT_DYNAMIC(WinFileSelectDlg, CFileDialog)



WinFileSelectDlg::WinFileSelectDlg(BOOL bOpenFileDialog,
    LPCTSTR lpszDefExt,
    LPCTSTR lpszFileName,
    DWORD dwFlags,
    LPCTSTR lpszFilter,
    CWnd* pParentWnd)
    :CFileDialog(
        bOpenFileDialog,
        lpszDefExt,
        lpszFileName,
        dwFlags | OFN_EXPLORER | OFN_HIDEREADONLY & (~OFN_SHOWHELP),
        lpszFilter,
        pParentWnd,
        0, FALSE)
{
    dwFlags |= (OFN_EXPLORER | OFN_HIDEREADONLY & (~OFN_SHOWHELP));

};

WinFileSelectDlg::~WinFileSelectDlg()
{
};

BEGIN_MESSAGE_MAP(WinFileSelectDlg, CFileDialog)
END_MESSAGE_MAP()


static BOOL FindFirstFileExists(LPCTSTR lpPath, DWORD dwFilter)
{
    WIN32_FIND_DATA fd;
    HANDLE hFind = FindFirstFile(lpPath, &fd);
    BOOL bFilter = (FALSE == dwFilter) ? TRUE : fd.dwFileAttributes & dwFilter;
    BOOL RetValue = ((hFind != INVALID_HANDLE_VALUE) && bFilter) ? TRUE : FALSE;
    FindClose(hFind);
    return RetValue;
}
/*
* 检查一个  路径 是否存在(绝对路径、相对路径,文件或文件夹均可)
* 存在则返回 1 (TRUE)
*/
static BOOL FilePathExists(LPCTSTR lpPath)
{
    return FindFirstFileExists(lpPath, FALSE);
}
//判断是否是文件绝对路径,不管是否存在
static BOOL IsFileAbsolutePath(LPCTSTR lpPath)
{
    CString str(lpPath);
    int iPos = str.Find(_T(":\\"));
    if (iPos != 1) return FALSE;
    return TRUE;
}
static BOOL FileAbsolutePathExists(LPCTSTR lpPath)
{
    CString str(lpPath);
    int iPos = str.Find(_T(":\\"));
    if (iPos != 1) return FALSE;
    return FindFirstFileExists(lpPath, FALSE);
}

/*
[cpp] view plaincopyprint?
* 检查一个 文件夹 是否存在(绝对路径、相对路径均可)
[cpp] view plaincopyprint?
* 存在则返回 1 (TRUE)
[cpp] view plaincopyprint?
*/
static BOOL FolderExists(LPCTSTR lpPath)
{
    return FindFirstFileExists(lpPath, FILE_ATTRIBUTE_DIRECTORY);
}

static BOOL IsLikeDesktopFolder(CString& sSourcFolder)
{
    CString sFeature1(_T("C:\\Users"));
    sFeature1 = sFeature1.MakeLower();
    CString sFeature2(_T("Desktop"));
    sFeature2 = sFeature2.MakeLower();

    CString sLowSourceFolder = sSourcFolder.MakeLower();
    int idx = sLowSourceFolder.Find(sFeature1);
    if (0 == idx)
    {
        idx = sLowSourceFolder.Find(sFeature2);
        if (idx > 0)
        {
            return TRUE;
        }
    }
    return FALSE;
}
/*
部分文件在c:\user\pubilc\desktop下面,也会显示在桌面上,当遇到这样文件时,还原出实际路径
*/
static BOOL CheckPublicDesktopFile(CString& sSourcFolder, CString& sFileName, CString& sNewFullPath)
{
    if (IsLikeDesktopFolder(sSourcFolder))
    {
        CString sNew = _T("C:\\Users\\Public\\Desktop\\");
        sNew += sFileName;
        if (FilePathExists(sNew.GetBuffer()))
        {
            sNewFullPath = sNew;
            return TRUE;
        }
    }
    return FALSE;
}
static BOOL CheckPublicDesktopFolder(CString& sSourcFolder, CString& sFolderName, CString& sNewFullPath)
{
    if (IsLikeDesktopFolder(sSourcFolder))
    {
        CString sNew = _T("C:\\Users\\Public\\Desktop\\");
        sNew += sFolderName;
        if (FolderExists(sNew.GetBuffer()))
        {
            sNewFullPath = sNew;
            return TRUE;
        }
    }
    return FALSE;
}
static BOOL GetKnowLibraryFilesAndFolders(CStringArray& vList)
{
    const GUID guidlist[4] = { FOLDERID_DocumentsLibrary, FOLDERID_MusicLibrary,
        FOLDERID_PicturesLibrary, FOLDERID_VideosLibrary };
    IEnumShellItems* pEnum;
    IShellItem* pItem;
    LPWSTR* pDisplayName;
    HRESULT hr;

    for (int i = 0; i < 4; i++)
    {
        hr = SHGetKnownFolderItem(guidlist[i], KF_FLAG_CREATE, 0, IID_PPV_ARGS(&pItem));
        if (FAILED(hr)) continue;

        hr = pItem->BindToHandler(NULL, BHID_EnumItems, IID_PPV_ARGS(&pEnum));
        if (FAILED(hr)) continue;

        pItem = NULL;
        while (SUCCEEDED(pEnum->Next(1, &pItem, NULL)))
        {
            if (NULL == pItem) break;
            try
            {
                pDisplayName = (LPWSTR*)CoTaskMemAlloc(MAX_PATH);
                memset(pDisplayName, 0, MAX_PATH); //SIGDN_NORMALDISPLAY
                if (SUCCEEDED(pItem->GetDisplayName(SIGDN_FILESYSPATH, pDisplayName)))
                {
                    vList.Add(CString((TCHAR*)*pDisplayName));
                }
            }
            catch (exception ex)
            {
                CoTaskMemFree(pDisplayName);
                pDisplayName = NULL;
            }


            CoTaskMemFree(pDisplayName);
            pItem = NULL;
        }
    }


    return TRUE;

}
static void  GetShellLibraryNameforLibrary(CStringArray& list)
{
    ;
    IShellLibrary* pSL;
    IEnumShellItems* pEnum;
    IShellItem* pItem;
    LPWSTR* pDisplayName;
    HRESULT hr;
    //hr = SHGetKnownFolderItem(FOLDERID_DocumentsLibrary, KF_FLAG_CREATE, 0, IID_PPV_ARGS(&pItem));

    hr = SHGetKnownFolderItem(FOLDERID_Libraries, KF_FLAG_CREATE, 0, IID_PPV_ARGS(&pItem));
    if (FAILED(hr)) return;

    hr = pItem->BindToHandler(NULL, BHID_EnumItems, IID_PPV_ARGS(&pEnum));
    if (FAILED(hr)) return;

    pItem = NULL;
    while (SUCCEEDED(pEnum->Next(1, &pItem, NULL)))
    {
        if (NULL == pItem) break;
        try
        {
            pDisplayName = (LPWSTR*)CoTaskMemAlloc(MAX_PATH);
            memset(pDisplayName, 0, MAX_PATH); //SIGDN_NORMALDISPLAY
            if (SUCCEEDED(pItem->GetDisplayName(SIGDN_NORMALDISPLAY, pDisplayName)))
            {
                list.Add(CString((TCHAR*)*pDisplayName));
            }
        }
        catch (exception ex)
        {
            CoTaskMemFree(pDisplayName);
            pDisplayName = NULL;
        }


        CoTaskMemFree(pDisplayName);
        pItem = NULL;
    }
}
//1:成功找到文件, 0:没有找到文件夹, -1:是库子文件夹,但是不是系统默认的库文件夹,无法匹配选择的文件
static int FindCurFloderFiles(CFileDialog* pDlg, CStringArray& sCurFolderFileList)
{
    sCurFolderFileList.RemoveAll();
    CString sCurVirtualFolder;

    CWnd* pcmbWnd = pDlg->GetDlgItem(cmb2);
    if (pcmbWnd)
        pcmbWnd->GetWindowTextW(sCurVirtualFolder);

    CStringArray subLibraryNameList;
    GetShellLibraryNameforLibrary(subLibraryNameList);
    int iCount = subLibraryNameList.GetCount();
    bool bFindflag = false;
    for (int i = 0; i < iCount; i++)
    {
        if (sCurVirtualFolder.CompareNoCase(subLibraryNameList.GetAt(i)) == 0)
        {
            bFindflag = true;
            continue;
        }
    }
    if (!bFindflag) return 0;

    CStringArray libraryFilesAndFoldersList;
    if (!GetKnowLibraryFilesAndFolders(libraryFilesAndFoldersList)) return false;

    CWnd* pWnd = pDlg->GetDlgItem(lst2);
    if (pWnd == NULL)
        return 0;
    CListCtrl* wndLst1 = (CListCtrl*)(pWnd->GetDlgItem(1));
    int nSelected = wndLst1->GetSelectedCount();
    if (!nSelected)
        return 0;

    int nItem = wndLst1->GetNextItem(-1, LVNI_SELECTED);

    CString strItemText;
    while ((nSelected--) > 0)
    {
        strItemText = wndLst1->GetItemText(nItem, 0);

        iCount = libraryFilesAndFoldersList.GetCount();
        for (int i = 0; i < iCount; i++)
        {
            CString str = libraryFilesAndFoldersList.GetAt(i);
            int ipos = str.ReverseFind(_T('\\'));
            if (ipos > 0)
            {
                CString strtmp = str.Mid(ipos + 1);
                //if (strItemText.CompareNoCase(strtmp) == 0)
                if (strtmp.Find(strItemText) == 0)
                {
                    sCurFolderFileList.Add(str);
                    break;
                }
            }
        }

        nItem = wndLst1->GetNextItem(nItem, LVNI_SELECTED);
    }

    if (sCurFolderFileList.GetCount() <= 0) return -1;

    return 1;
}

BOOL WinFileSelectDlg::OnFileNameOK()
{
    m_bSelectVirtualItem = false;
    CWnd* pParent = GetParent();
    CFileDialog* pDlg = (CFileDialog*)CWnd::FromHandle(GetParent()->m_hWnd);
    if (pDlg)
    {
        CWnd* pWnd = pDlg->GetDlgItem(lst2);
        if (pWnd == NULL)
            return FALSE;

        m_SelectedItemList.RemoveAll();

        CListCtrl* wndLst1 = (CListCtrl*)(pWnd->GetDlgItem(1));

        int nSelected = wndLst1->GetSelectedCount();
        if (!nSelected)
            return FALSE;
        CString strItemText, strDirectory = m_strCurrendDirectory;
        if (strDirectory.Right(1) != _T("\\"))
            strDirectory += _T("\\");

        CString fileslist = _T("");
        pDlg->SendMessage(CDM_GETSPEC, (WPARAM)MAX_PATH_EditControl,
            (LPARAM)fileslist.GetBuffer(MAX_PATH_EditControl));
        fileslist.ReleaseBuffer();

        if (m_strCurrendDirectory.GetLength() <= 0)
        {
            //只有在库目录里才会有出现。
            //现在只检索系统默认的几个子库文件夹,第三方软件建立的库目录会提示错误。
            //目前算是部分解决
            CStringArray sFolderAndFileList;
            int iRtn = FindCurFloderFiles(pDlg, sFolderAndFileList);
            switch (iRtn)
            {
            case 0:
                return 1;
                break;
            case 1:
                m_SelectedItemList.Copy(sFolderAndFileList);
                pDlg->EndDialog(IDOK);
                return 1;
                break;
            case -1:
                m_bSelectVirtualItem = true;
                pDlg->EndDialog(IDCANCEL);
                return 1;
                break;
            }

        }

        strItemText = strDirectory + fileslist;
        if (nSelected == 1 && fileslist != _T(""))
        {
            CString sTmpNewFileFullPath;
            if (FilePathExists(strItemText))
            {
                m_SelectedItemList.Add(strItemText);
                return CFileDialog::OnFileNameOK();
            }
            else if (CheckPublicDesktopFile(strDirectory, fileslist, sTmpNewFileFullPath))
            {
                m_SelectedItemList.Add(sTmpNewFileFullPath);
                return CFileDialog::OnFileNameOK();

            }
            m_bSelectVirtualItem = true;
            //::MessageBoxW(NULL, m_strError.GetBuffer(), NULL, NULL);
            //return NULL;
        }
    }
    ::MessageBeep(MB_ICONQUESTION);
    return 1;
};

void WinFileSelectDlg::OnFolderChange()
{
    //TRACE(_T("CMyOpenDlg::OnFolderChange: \n"));

    CWnd* pcmbWnd = GetParent()->GetDlgItem(cmb13);
    if (pcmbWnd)
        pcmbWnd->SetWindowTextW(_T(""));

    m_strCurrendDirectory = GetFolderPath();



    //SetListView(ODM_VIEW_LARGE_ICONS);


    CFileDialog::OnFolderChange();

};
BOOL WinFileSelectDlg::OnInitDialog()
{
    //TRACE(_T("CMyOpenDlg::OnInitDialog, hwnd=%p\n"), m_hWnd);


    return CFileDialog::OnInitDialog();
}

void WinFileSelectDlg::OnInitDone()
{
    //TRACE(_T("CMyOpenDlg::OnInitDone\n"));
#ifdef _WIN64

    m_strCurrendDirectory = GetFolderPath();
    CWnd* pFD = GetParent();

    HideControl(edt1);
    HideControl(cmb1);
    HideControl(stc2);

    //HideControl(cmb13);
    //HideControl(stc3);

    /*CRect rectCancel; pFD->GetDlgItem(IDCANCEL)->GetWindowRect(&rectCancel);
    pFD->ScreenToClient(&rectCancel);

    CRect rectOK; pFD->GetDlgItem(IDOK)->GetWindowRect(&rectOK);
    pFD->ScreenToClient(&rectOK);
    pFD->GetDlgItem(IDOK)->SetWindowPos(0,rectCancel.left - rectOK.Width() - 5, rectCancel.top, 0,0, SWP_NOZORDER | SWP_NOSIZE);

    CRect rectList2; pFD->GetDlgItem(lst1)->GetWindowRect(&rectList2);
    pFD->ScreenToClient(&rectList2);
    pFD->GetDlgItem(lst1)->SetWindowPos(0,0,0,rectList2.Width(), abs(rectList2.top - (rectCancel.top - 5)), SWP_NOMOVE | SWP_NOZORDER);

    CRect rectStatic; pFD->GetDlgItem(stc3)->GetWindowRect(&rectStatic);
    pFD->ScreenToClient(&rectStatic);
    pFD->GetDlgItem(stc3)->SetWindowPos(0, rectCancel.left - 375, rectCancel.top + 5, rectStatic.Width(), rectStatic.Height(), SWP_NOZORDER);

    CRect rectEdit1; pFD->GetDlgItem(cmb13)->GetWindowRect(&rectEdit1);
    pFD->ScreenToClient(&rectEdit1);
    pFD->GetDlgItem(cmb13)->SetWindowPos(0, rectCancel.left - 320, rectCancel.top, rectEdit1.Width() - 15, rectEdit1.Height(), SWP_NOZORDER);*/

    SetControlText(stc3, m_strItemName.GetBuffer());
    SetControlText(IDOK, m_strSelect.GetBuffer());

    SetLastError(0);
    m_wndProc = (WNDPROC)::SetWindowLongPtr(pFD->m_hWnd, GWLP_WNDPROC, (LONG_PTR)WindowProcNew);
    DWORD errorNo = GetLastError();
    pFD->CenterWindow();
#elif WIN32
    m_strCurrendDirectory = GetFolderPath();
    CWnd* pFD = GetParent();

    HideControl(edt1);
    HideControl(cmb1);
    HideControl(stc2);

    //HideControl(0x4a0);


    //SetControlText(stc3, m_strItemName.GetBuffer());
    SetControlText(IDOK, m_strSelect.GetBuffer());

    SetControlText(cmb13, _T(""));



    m_wndProc = (WNDPROC)::SetWindowLong(pFD->m_hWnd, GWL_WNDPROC, (long)WindowProcNew);
    pFD->CenterWindow();
#endif
};


//
// Change the list view to desired mode if the view exists.
// Display TRACE diagnostics either way.
//
BOOL WinFileSelectDlg::SetListView(LISTVIEWCMD cmd)
{
    //TRACE(_T("CMyOpenDlg::SetListView: \n"));

    // note that real dialog is my parent, not me
    CWnd* pshell = GetParent()->GetDlgItem(lst2);
    if (pshell) {
        //	TRACE(_T("hwnd=%p.\n"), m_wndList.GetSafeHwnd());
            //TRACE(_T("SendMessage\n"));
        pshell->SendMessage(WM_COMMAND, cmd);
        return TRUE;
    }
    //TRACE(_T("failed.\n"), m_wndList.GetSafeHwnd());
    return FALSE;
}


void WinFileSelectDlg::OnFileNameChange()
{

    CWnd* pWnd = GetParent()->GetDlgItem(lst2);
    if (pWnd == NULL)
        return;
    CListCtrl* wndLst1 = (CListCtrl*)(pWnd->GetDlgItem(1));
    int nSelected = wndLst1->GetSelectedCount();
    if (!nSelected)
    {
        CWnd* pcmbWnd = GetParent()->GetDlgItem(cmb13);
        if (pcmbWnd)
            pcmbWnd->SetWindowTextW(_T(""));
        m_strLastSelectList = _T("");
        return;
    }

    CString strItemText, strDirectory = m_strCurrendDirectory;
    if (strDirectory.Right(1) != _T("\\"))
        strDirectory += _T("\\");

    CString fileslist = _T("");

    CWnd* pcmbWnd = GetParent()->GetDlgItem(cmb13);
    if (pcmbWnd)
        pcmbWnd->GetWindowTextW(fileslist);

    bool bFileFolderSameName = false;
    bool bOnlyFolder = true;
    int nItem = wndLst1->GetNextItem(-1, LVNI_SELECTED);
    while ((nSelected--) > 0)
    {
        strItemText = wndLst1->GetItemText(nItem, 0);
        if (fileslist.Find(strItemText) >= 0) bFileFolderSameName = true;

        strItemText = strDirectory + strItemText;
        DWORD attr = GetFileAttributes(strItemText);
        if (!((attr != 0xFFFFFFFF) && (attr & FILE_ATTRIBUTE_DIRECTORY)))
        {
            bOnlyFolder = false;
            break;
        }
        nItem = wndLst1->GetNextItem(nItem, LVNI_SELECTED);
    }


    while (bOnlyFolder)
    {
        //清空之前,判断是否cmb13中新写入值,如果是,就有可能是当扩展名隐藏,有同名的文件和文件夹的情况
        if (fileslist.GetLength() > 0)
        {
            if (fileslist.CompareNoCase(m_strLastSelectList))
            {
                break;
            }
            else if (m_bCmb13Changed && bFileFolderSameName && m_strLastSelectList.GetLength() > 0)
            {
                break;
            }
        }

        CWnd* pcmbWnd = GetParent()->GetDlgItem(cmb13);
        if (pcmbWnd)
            pcmbWnd->SetWindowTextW(_T(""));
        break;
    }

    m_strLastSelectList = fileslist;

    m_bCmb13Changed = false;
}

LRESULT CALLBACK WinFileSelectDlg::WindowProcNew(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message == WM_COMMAND)
    {
        if (HIWORD(wParam) == BN_CLICKED)
        {
            if (LOWORD(wParam) == IDCANCEL)
            {
                m_bSelectVirtualItem = false;
            }
            else if (LOWORD(wParam) == IDOK)
            {

                m_bSelectVirtualItem = false;
                if (CFileDialog* pDlg = (CFileDialog*)CWnd::FromHandle(hwnd))
                {

                    CString sFoldertmp = _T("");
                    pDlg->SendMessage(CDM_GETFOLDERPATH, (WPARAM)MAX_PATH_EditControl,
                        (LPARAM)sFoldertmp.GetBuffer(MAX_PATH_EditControl));
                    sFoldertmp.ReleaseBuffer();


                    CString fileslist = _T("");
                    pDlg->SendMessage(CDM_GETSPEC, (WPARAM)MAX_PATH_EditControl,
                        (LPARAM)fileslist.GetBuffer(MAX_PATH_EditControl));
                    fileslist.ReleaseBuffer();
                    DWORD tmpAttr = GetFileAttributes(fileslist);

                    //如果用户在下拉列表中直接选择最近选择的文件,则直接选择之
                    if (IsFileAbsolutePath(fileslist.GetBuffer()))
                    {
                        if (FindFirstFileExists(fileslist.GetBuffer(), FALSE))
                        {
                            m_SelectedItemList.Add(fileslist);
                            pDlg->EndDialog(IDOK);
                            return NULL;
                        }
                        else
                        {
                            pDlg->EndDialog(IDOK);
                            return NULL;
                        }

                    }


                    if (m_strCurrendDirectory.GetLength() <= 0)
                    {
                        //只有在库目录里才会有出现。
                        //现在只检索系统默认的几个子库文件夹,第三方软件建立的库目录会提示错误。
                        //目前算是部分解决
                        CStringArray sFolderAndFileList;
                        int iRtn = FindCurFloderFiles(pDlg, sFolderAndFileList);
                        switch (iRtn)
                        {
                        case 0:
                            return CallWindowProc(m_wndProc, hwnd, message, wParam, lParam);
                            break;
                        case 1:
                            m_SelectedItemList.Copy(sFolderAndFileList);
                            pDlg->EndDialog(IDOK);
                            return NULL;
                            break;
                        case -1:
                            m_bSelectVirtualItem = true;
                            pDlg->EndDialog(IDCANCEL);
                            return NULL;
                            break;
                        }

                    }
                    bool bHaveSelect = false;


                    if ((tmpAttr != 0xFFFFFFFF) && (tmpAttr & FILE_ATTRIBUTE_DIRECTORY))
                    {
                        return CallWindowProc(m_wndProc, hwnd, message, wParam, lParam);
                    }

                    //		CString Output;
                    m_SelectedItemList.RemoveAll();
                    CWnd* pWnd = pDlg->GetDlgItem(lst2);
                    if (pWnd == NULL)
                        return FALSE;
                    CListCtrl* wndLst1 = (CListCtrl*)(pWnd->GetDlgItem(1));
                    int nSelected = wndLst1->GetSelectedCount();
                    if (!nSelected)
                        return FALSE;
                    /*Output = _T("");
                    Output.Format(_T("nSelect = %d \n"), nSelected);*/
                    //		OutputDebugString(Output);
                    CString strItemText, strDirectory = m_strCurrendDirectory;
                    if (strDirectory.GetLength() > 1 && strDirectory.Right(1) != _T("\\"))
                        strDirectory += _T("\\");
                    /
                    //处理文件夹
                    BOOL isLikeDesktopFlag = IsLikeDesktopFolder(strDirectory);
                    int nItem = wndLst1->GetNextItem(-1, LVNI_SELECTED);


                    CString sTmpFileeList = fileslist;
                    while ((nSelected--) > 0)
                    {
                        strItemText = wndLst1->GetItemText(nItem, 0);
                        if (sTmpFileeList.GetLength() > 0) //处理当扩展名隐藏,有同名的文件和文件夹的情况
                        {
                            int idx = sTmpFileeList.Find(strItemText + _T("."));
                            if (idx >= 0)
                            {
                                CString stmp1 = sTmpFileeList.Left(idx);
                                CString stmp2 = sTmpFileeList.Mid(idx + strItemText.GetLength() + 1);
                                sTmpFileeList = stmp1 + stmp2;
                                nItem = wndLst1->GetNextItem(nItem, LVNI_SELECTED);
                                continue;
                            }
                        }

                        DWORD attr = GetFileAttributes(strDirectory + strItemText);
                        if ((attr != 0xFFFFFFFF) && (attr & FILE_ATTRIBUTE_DIRECTORY))
                        {
                            m_SelectedItemList.Add(strDirectory + strItemText);
                            bHaveSelect = true;
                        }
                        else if (isLikeDesktopFlag)
                        {
                            CString sTmpNewFolderFullPath;
                            if (CheckPublicDesktopFolder(strDirectory, strItemText, sTmpNewFolderFullPath))
                            {
                                m_SelectedItemList.Add(sTmpNewFolderFullPath);
                                bHaveSelect = true;
                            }
                        }
                        nItem = wndLst1->GetNextItem(nItem, LVNI_SELECTED);
                    }
                    //
                    //处理文件
                /*	Output = _T("");
                    Output.Format(_T("ItemList count = %d \n"), m_SelectedItemList.GetCount());
                    OutputDebugString(Output);*/
                    strItemText = _T("");
                    nSelected = wndLst1->GetSelectedCount();
                    if (nSelected > m_SelectedItemList.GetCount())
                    {
                        int MoreThanOnFile = fileslist.Find(_T("\""));
                        if (MoreThanOnFile != -1)
                        {
                            for (int i = 0; i < fileslist.GetLength(); i++)
                                if (fileslist[i] != '\"')
                                {
                                    strItemText.AppendFormat(_T("%c"), fileslist[i]);
                                    if (fileslist[i - 1] == '\"' && fileslist[i] == ' ')
                                        strItemText.Delete(strItemText.GetLength() - 1);
                                }
                                else if (!strItemText.IsEmpty())
                                {

                                    if (FilePathExists(strDirectory + strItemText))
                                    {
                                        m_SelectedItemList.Add(strDirectory + strItemText);
                                        strItemText.Empty();
                                        bHaveSelect = true;
                                    }
                                    else if (isLikeDesktopFlag)
                                    {
                                        CString sTmpNewFileFullPath;
                                        if (CheckPublicDesktopFile(strDirectory, strItemText, sTmpNewFileFullPath))
                                        {
                                            m_SelectedItemList.Add(sTmpNewFileFullPath);
                                            strItemText.Empty();
                                            bHaveSelect = true;
                                        }

                                    }

                                }
                        }
                        else
                        {
                            if (fileslist.GetLength() > 0)
                            {

                                if (FilePathExists(strDirectory + fileslist))
                                {
                                    m_SelectedItemList.Add(strDirectory + fileslist);
                                    bHaveSelect = true;
                                }
                                else if (isLikeDesktopFlag)
                                {
                                    CString sTmpNewFileFullPath;
                                    if (CheckPublicDesktopFile(strDirectory, fileslist, sTmpNewFileFullPath))
                                    {
                                        m_SelectedItemList.Add(sTmpNewFileFullPath);
                                        bHaveSelect = true;
                                    }

                                }
                            }
                        }
                    }
                    if (bHaveSelect)
                        pDlg->EndDialog(IDOK);
                    else
                    {
                        m_bSelectVirtualItem = true;
                        pDlg->EndDialog(IDCANCEL);
                    }
                    return NULL;
                }
            }
        }
        else if (HIWORD(wParam) == CBN_EDITCHANGE)
        {
            if (LOWORD(wParam) == cmb13)
            {
                m_bCmb13Changed = true;
            }
        }
    }
    return CallWindowProc(m_wndProc, hwnd, message, wParam, lParam);
}

#pragma warning( pop )
#endif // WIN32

二、QT版本

CustomFileDialog.h

#pragma once
#include <QFileDialog>


class QPushButton;
class QListView;
class CustomFileDialog : public QFileDialog
{
    Q_OBJECT
public:
    CustomFileDialog(const QString& qstrCaption, QWidget* pParent = nullptr);

private slots:
    void onFinish();

private:
    QPushButton* m_pBtnOk;
    QListView* m_pListview;

};


CustomFileDialog.cpp

#include "CustomFileDialog.h"
#include <QListView>
#include <QTreeView>
#include <QDialogButtonBox>
#include <QDebug>
#include <QLabel>
#include <QPushButton>
#include <QPoint>
#include <QEvent>
#include <QMouseEvent>
#include "ui/languagehelper.h"


CustomFileDialog::CustomFileDialog(const QString& qstrCaption, QWidget* pParent/* = nullptr*/)
    : QFileDialog(pParent)
    , m_pBtnOk(nullptr)
    , m_pListview(nullptr)
{
    auto funcSetLabelDisplayText = [&](QString qstrTag, QString qstrText) {
        QLabel* pLabelLookin = this->findChild<QLabel*>(qstrTag);
        if (pLabelLookin) pLabelLookin->setText(qstrText);
    };
    auto funcPrintObject = [&]() {
        QObjectList childs = this->children();
        foreach(QObject * child, childs) {
            qDebug() << QString("%1%2 : %3")
                        .arg("", 0)
                        .arg(child->metaObject()->className())
                        .arg(child->objectName());
        }
    };
    this->setWindowTitle(qstrCaption);
    this->setOption(QFileDialog::DontUseNativeDialog, true);
    // multi-select
    QListView* pListView = this->findChild<QListView*>("listView");
    if (pListView)
    {
        m_pListview = pListView;
        pListView->setSelectionMode(QAbstractItemView::ExtendedSelection);
        auto* pSelectModel = pListView->selectionModel();
        QObject::connect(pSelectModel, &QItemSelectionModel::selectionChanged,
                         [&]() {if (m_pBtnOk) { m_pBtnOk->setText(GET_TEXT_BY_LANGID(kLanguageIdUpload)); }});

    }
    QTreeView* pTreeView = this->findChild<QTreeView*>();
    if (pTreeView)
        pTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    // ok/cancel
    QDialogButtonBox* pButton = this->findChild<QDialogButtonBox*>("buttonBox");
    if (pButton)
    {
        m_pBtnOk = pButton->button(QDialogButtonBox::Open);
        m_pBtnOk->setText(GET_TEXT_BY_LANGID(kLanguageIdUpload));
        QPushButton* pBtnCancel = pButton->button(QDialogButtonBox::Cancel);
        pBtnCancel->setText(GET_TEXT_BY_LANGID(kLanguageIdCancel));
    }
    // disable the connection
    disconnect(pButton, SIGNAL(accepted()), this, SLOT(accept()));
    // custom connect
    connect(pButton, SIGNAL(accepted()), this, SLOT(onFinish()));
    // set the window dispaly info
    funcSetLabelDisplayText("lookInLabel", GET_TEXT_BY_LANGID(kLanguageIdFilePos));
    funcSetLabelDisplayText("fileNameLabel", GET_TEXT_BY_LANGID(kLanguageIdFilename));
    funcSetLabelDisplayText("fileTypeLabel", GET_TEXT_BY_LANGID(kLanguageIdFileType));
    setLabelText(QFileDialog::Accept, GET_TEXT_BY_LANGID(kLanguageIdUpload));
}

void  CustomFileDialog::onFinish()
{
    QDialog::accept();
}

三、使用

QString qstrBtnText = "上传";
    QStringList listFiles;
#ifdef WIN32
    wchar_t szBtnText[1024];
    wcscpy_s(reinterpret_cast<wchar_t*>(szBtnText),
        sizeof(szBtnText) / sizeof(wchar_t),
        reinterpret_cast<const wchar_t*>(qstrBtnText.utf16()));
    wchar_t szInitDir[] = _T("C:\\Users");
    wchar_t szItemName[] = _T("Item Name:");
    wchar_t szErrorInfo[] = _T("You can't open this location using this program.\nPlease try a different location.");
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    CWnd* pCWnd = CWnd::GetForegroundWindow();
    WinFileSelectDlg dlgSelectFile(TRUE, _T("*.*"), NULL,
        OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT,
        _T("All files and folders(*.*)|*.*||"), pCWnd);

    if (szInitDir && lstrlen(szInitDir) > 0)
        dlgSelectFile.m_ofn.lpstrInitialDir = szInitDir;
    dlgSelectFile.SetSpecialStrings(szItemName, szBtnText);
    dlgSelectFile.SetErrorInfo(szErrorInfo);
    dlgSelectFile.m_SelectedItemList.RemoveAll();
    int nCode = dlgSelectFile.DoModal();
    if (IDOK == nCode)
    {
        if (dlgSelectFile.HaveSelectSomething())
        {
            {
                if (dlgSelectFile.m_SelectedItemList.GetCount() <= 0) return listFiles;
                for (size_t nIndex = 0; nIndex < dlgSelectFile.m_SelectedItemList.GetCount(); ++nIndex)
                {
                    wchar_t szBuffer[MAX_PATH] = { 0 };
                    wcscpy_s(szBuffer, MAX_PATH, dlgSelectFile.m_SelectedItemList[nIndex].GetBuffer());
                    QString qstrFilepath = QString::fromWCharArray(szBuffer);
                    listFiles.push_back(qstrFilepath);
                }
            }
        }
    }
#else
    CustomFileDialog dlgSelectFile("上传");
    if (QDialog::Accepted == dlgSelectFile.exec())
    {
        listFiles = dlgSelectFile.selectedFiles();
    }
#endif // WIN32

    return listFiles;
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在计算机中,C语言中的判断文件文件夹的一个常用方法是使用文件处理函数。通过调用这些函数,可以判断指定路径下的对象是文件还是文件夹。 其中,常用的文件处理函数包括stat、lstat和fstat。这些函数可以获取文件文件夹的详细信息,通过判断其中的属性来确定其是文件还是文件夹。 具体实现的步骤如下: 1. 包含相关头文件,例如<sys/types.h>和<sys/stat.h>。 2. 创建一个存储文件状态信息的结构体变量,例如struct stat类型的变量。 3. 使用stat、lstat或fstat函数,传入需要判断的文件文件夹的路径作为参数,并将返回的结果保存到结构体变量中。 4. 通过检查结构体变量中的st_mode字段来判断文件类型。 - 如果st_mode字段中的标志位S_ISREG为真,则表示是一个普通文件。 - 如果st_mode字段中的标志位S_ISDIR为真,则表示是一个文件夹。 - 其他标志位可以用来判断是否是符号链接、字符设备等其他类型。 5. 根据文件类型进行相应的操作。 例如,可以使用以下代码判断文件类型: ```c #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> int main() { struct stat fileInfo; const char* path = "example.txt"; // 替换成需要判断的文件路径 if (stat(path, &fileInfo) == 0) { if (S_ISREG(fileInfo.st_mode)) { printf("这是一个文件。\n"); } else if (S_ISDIR(fileInfo.st_mode)) { printf("这是一个文件夹。\n"); } else { printf("其他类型。\n"); } } else { printf("文件不存在或访问出错。\n"); } return 0; } ``` 以上是一个简单的示例代码,通过调用stat函数来判断文件类型。根据返回的文件信息中的st_mode字段,我们可以了解文件的具体类型,并进行相应的处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值