28_UI通用对话框多少会一点之浏览文件夹与遍历目录

这篇具有很好参考价值的文章主要介绍了28_UI通用对话框多少会一点之浏览文件夹与遍历目录。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

UI通用对话框多少会一点之浏览文件夹与遍历目录

要想让用户选择一个文件夹,可以调用SHBrowseForFolder()函数∶

PIDLIST_ABSOLUTE SHBrowseForFolder(_in_ BROWSEINFO lpbi);

函数返回值为PIDLIST_ABSOLUTE数据类型,在shtypes.h头文件中定义如下︰

#define PIDLIST_ABSOLUTE LPITEMIDLIST 

typedef ITEMIDLIST *LPITEMIDLIST
    
typedef struct _ITEMIDLIST
{
	SHITEMID mkid;
} ITEMIDLIST;

typedef struct _SHITEMID
{
	USHORT cb;
	BYTE abID[ 1 ];
}SHITEMID;

返回值类型PIDLIST_ABSOLUTE指定所选文件夹相对于命名空间根目录的位置。如果用户在对话框中单击了"取消"按钮、关闭了对话框或发生了错误,则返回值为NULL.

lpbi参数是一个指向BROWSEINFO结构的指针,BROWSEINFO结构在ShlObj.h头文件中定义如下∶

typedef struct _browseinfo {
	HWND	hwndOwner; //对话框的拥有者窗口句柄
	PCIDLIST_ABSOLUTE pidlRoot; //开始浏览的根文件夹的位置,不需要可以设置为NULL
	LPTSTR pszDisplayName;//返回用户选择的文件夹名称的缓冲区
	LPCTSTR lpszTitle; //显示在对话框上部静态控件中的文字
	UINT	ulFlags;//标志位
	BFFCALLBACK lpfn;
	LPARAM	lParam;
	int ilmage;
}BROWSEINFO,*PBROWSEINFO,*LPBROWSEINFO;
  • ulFlags字段指定标志位,常用的标志如下表所示。
标识宏 含义
BIF_RETURNONLYFSDIRS 如果用户选择不属于文件系统的文件夹(例如网络、家庭组),则对话框的“确定"按钮将显示为灰色
BIF_NEWDIALOGSTYLE 使用新的用户界面,新的用户界面具有多项新功能
BIF_EDITBOX 在对话框中包含一个编辑控件,允许用户输入文件夹名称
BIF_USENEWUI 使用新用户界面,对话框中包含一个编辑控件,相当于BIF_NEWDIALOGSTYLE
BIF_BROWSEINCLUDEFILES 对话框中显示文件和文件夹,通常不设置该标志
BIF_BROWSEINCLUDEURLS 对话框可以显示URL快捷方式,还必须设置BIF_USENEWUI和BIF_BROWSEINCLUDEFILES标志,通常不设置该标志

SHBrowseForFolder()函数返回一个PIDLIST_ABSOLUTE类型值,即指向ITEMIDLIST结构的指针。不必深究这个结构,因为使用SHGetPathFromIDList()函数可以很方便地将它转换成目录名称字符串(完整路径)∶

BOOL SHGetPathFromIDList
(
    _in_ PCIDLIST_ABSOLUTE pid, //指向ITEMIDLIST结构的指针
    _out_LPTSTR pszPath //返回目录名称的缓冲区
);

要逼历一个目录中的子目录或文件,首先调用FindFirstFile()函数。该函数返回一个HANDLE类型的查找句柄hFindFile,并返回找到的第一个子目录或文件的信息﹔如果FindFirstFile()函数执行成功,则接下来可以利用hFindFile句柄循环调用FindNextFile()函数继续查找其他目录或文件,直到FindNextFile()函数返回FALSE为止;最后调用FindClose()函数关闭hFindFile查找句柄。使用这几个函数查找文件的代码通常如下所示∶

wWIN32_FIND_DATA fd = { 0 };
	//遍历目录
hFindFile = FindFirstFile(szDir, &fd);
if (hFindFile != INVALID_HANDLE_VALUE)
{
	do
	{
		//处理本次找到的文件
	
	} while (FindNextFile(hFindFile, &fd));
	FindClose(hFindFile);
}
  • lpFileName参数指定要查找的文件名。如果文件名中不包含路径,那么将在当前目录中查找,包含路径的话将在指定路径中查找。在文件名中可以使用通配符"*""?"指定查找符合指定特征的文件。下面是文件名格式的几个示例︰
c:\Windows\*.* //在C:\Windows目录中查找所有类型的文件
c.\Windows\System32\*.dll //在C:\Windows\System32目录中查找所有扩展名为.dll的文件
C:\Windows\System.ini //在C:\Windows目录中查找System.ini文件
C:\Windowsla???.* //在C:\Windows目录中查找所有以a开头的长度为4个字符的任何文件
Test.dat //在当前目录中查找Test.dat文件
*.*//在当前目录中查找所有文件

lpFindFileData参数是一个指向查找结构WIN32_FIND_DATA的指针。该结构返回找到的目录或文件的信息,在minwinbase.h头文件中定义如下∶

typedef struct _WIN32_FIND_DATA 
{
	DWORD dwFileAttributes;//文件系统属性
	FILETIME ftCreationTime; // FILETIME格式的文件创建时间
	FILETIME ftLastAccessTime; //FILETIME格式的最后访问时间
	FILETIME ftLastWriteTime; //FILETIME格式的最后修改时间
	DWORD nFileSizeHigh; //文件大小的高32位DWORD值,以字节为单位
    DWORD nFileSizeLow; //文件大小的低32位DWORD值,以字节为单位
	DWORD dwReserved0; //保留字段
	DWORD dwReservedl; //保留字段
	TCHAR cFileName[MA×_PATH] //文件名称(不包括路径)
	TCHAR cAlternateFileName[14];//该文件的替代名称,8.3文件名格式,通常用不到
} WIN32_FIND_DATA,*PWIN32_FIND_DATA,*LPWIN32_FIND_DATA;
  • dwFileAttributes字段包含文件系统属性,通过这个字段可以检查找到的究竟是一个子目录还是一个文件,以及其他文件系统属性,常见的属性如下表所示。
属性宏 含义
FILE_ATTRIBUTE_NORMAL 普通文件
FILE_ATTRIBUTE_DIRECTORY 找到的是一个目录
FILE_ATTRIBUTE_READONLY 只读文件
FILE_ATTRIBUTE_TEMPORARY 用于临时存储的文件
FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录
FILE_ATTRIBUTE_SYSTEM 操作系统使用的文件或目录
FILE_ATTRIBUTE_ARCHIVE 存档文件或目录
FILE_ATTRIBUTE_COMPRESSED 压缩的文件或目录
FILE_ATTRIBUTE_ENCRYPTED 已加密的文件或目录

如果FindFirstFile()函数执行成功,则返回值是在后续调用FindNextFile()FindClose()时使用的查找句柄,而lpFindFileData参数指向的WIN32_FIND_DATA结构包含找到的第一个目录或文件的信息﹔如果函数执行失败或无法从lpFileName参数指定的搜索字符串中找到目录或文件,则返回值为INVALID_HANDLE_VALUE(-1),这种情况下的IpFindFileData参数指向的结构的内容不确定。
FindNextFile函数以查找句柄和查找结构为参数继续查找目录或文件∶

BOOL WINAPl FindNextFile(
_in_ HANDLEhFindFile, //查找句柄
_out_ LPWIN32_FlIND_DATA lpFindFileData //指向查找结构WIN32_FIND_DATA的指针
);

如果函数执行成功,则返回值为TRUE,lpFindFileData参数指向的结构包含找到的下一个目录或文件的信息﹔如果函数执行失败,则返回值为FALSE,这种情况下的lpFindFileData参数指向的结构的内容不确定。

下面我们来做一个小练习,调用SHBrowseForFolder()函数创建一个浏览文件夹对话框,然后调用SHGetPathFromIDList()函数把上一个函数的返回值转换为完整目录名称字符串,拼接一个查找字符串szSearch用于FindFirstFile()函数,接着就是FindNextFile(hFindFile,&findData)的循环调用。如果找到的是一个目录,那么应该递归往下一层找。这有点麻烦,本例中仅处理了找到的各种文件,例如普通文件、临时文件、隐藏文件等;

WIN32实现

  • resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 SHBrowseForFolder.rc 使用
//
#define IDD_MAIN                        101
#define IDC_STATIC_DIR                  1001
#define IDC_LIST_FILENAME               1002
#define IDC_BTN_BROWSE                  1003

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1004
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

28_UI通用对话框多少会一点之浏览文件夹与遍历目录,深入浅出WINDOW程序设计,c++

  • SHBrowseForFolder.cpp
#include <windows.h>
#include <Shlobj.h>
#include <tchar.h>
#include <strsafe.h>
#include "resource.h"

#pragma comment(linker,"\"/manifestdependency:type='win32' \
    name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
    processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

HINSTANCE g_hInstance;
INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    g_hInstance = hInstance;

    // 创建模态对话框
    DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogProc, NULL);
    return 0;
}

INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static HWND hwndList; 
    PIDLIST_ABSOLUTE pItemIdList;   // SHBrowseForFolder函数返回值


    TCHAR szDir[MAX_PATH] = { 0 };  // SHGetPathFromIDList函数返回的目录名称的缓冲区
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
    WIN32_FIND_DATA findData = { 0 };
    TCHAR szSearch[MAX_PATH] = { 0 };
    TCHAR szDirFile[MAX_PATH] = { 0 };

 
    if (uMsg == WM_INITDIALOG)
    {
        hwndList = ::GetDlgItem(hwndDlg, IDC_LIST_FILENAME);
        return TRUE;
    }
    else if (uMsg == WM_COMMAND)
    {
        if (wParam == IDC_BTN_BROWSE)
        {
            BROWSEINFO bi = { 0 };
            bi.hwndOwner = hwndDlg;
            bi.lpszTitle = TEXT("请选择一个文件夹");
            bi.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
            pItemIdList = SHBrowseForFolder(&bi);


            if (pItemIdList)
            {
                //根据IDList 查当前用户选择目录的全路径
                SHGetPathFromIDList(pItemIdList, szDir);


                //设置STATIC控件文本值
                SetDlgItemText(hwndDlg, IDC_STATIC_DIR, szDir);

               
                if (szDir[_tcslen(szDir) - 1] != TEXT('\\'))
                {
                    StringCchCat(szDir, _countof(szDir), TEXT("\\"));
                }
       
                // 拼接搜索字符串
                StringCchCopy(szSearch, _countof(szSearch), szDir);
                StringCchCat(szSearch, _countof(szSearch), TEXT("*.*"));
               

                hFindFile = ::FindFirstFile(szSearch, &findData);
                if (hFindFile != INVALID_HANDLE_VALUE)
                {

                    //清空 ListBox内容
                    SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
                    do
                    {
                        // 查这个目录下文件  不进行处理子目录。
                        if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
                        {
                            StringCchCopy(szDirFile, _countof(szDirFile), szDir);
                            StringCchCat(szDirFile, _countof(szDirFile), findData.cFileName);
                        
                            ::SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)szDirFile);
                        }

                    } while (::FindNextFile(hFindFile, &findData));

                    // 关闭查找句柄
                    ::FindClose(hFindFile);
                }
            }
        }
        else if (wParam == IDCANCEL)
        {
            ::EndDialog(hwndDlg, 0);
        }
    }

    return FALSE;
}

28_UI通用对话框多少会一点之浏览文件夹与遍历目录,深入浅出WINDOW程序设计,c++

MFC实现

MFC 中 CFolderPickerDialog 同样是对WIN32 进行的二次封装,来实现浏览文件夹的功能。这里笔者相同需求下,给出MFC版本的实现。文章来源地址https://www.toymoban.com/news/detail-786563.html


// HelloMFCDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "HelloMFC.h"
#include "HelloMFCDlg.h"
#include "afxdialogex.h"
#include <strsafe.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


BEGIN_MESSAGE_MAP(CHelloMFCDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BTN_BROWSE, &CHelloMFCDlg::OnBnClickedBtnBrowse)
END_MESSAGE_MAP()


CHelloMFCDlg::CHelloMFCDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_HELLOMFC_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CHelloMFCDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}
BOOL CHelloMFCDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);
	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		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);
		}
	}
	SetIcon(m_hIcon, TRUE);			
	SetIcon(m_hIcon, FALSE);	
	return TRUE;  
}
void CHelloMFCDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	CDialogEx::OnSysCommand(nID, lParam);
}
void CHelloMFCDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); 
		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}
HCURSOR CHelloMFCDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void CHelloMFCDlg::OnBnClickedBtnBrowse()
{
	// TODO: 在此添加控件通知处理程序代码
	
	HWND hwndList;
	TCHAR szSearch[MAX_PATH];
	CFileFind cFileFinder;
	BOOL bRet = FALSE;


	CFolderPickerDialog  
		cFolderPikerDialog(NULL, BIF_USENEWUI | BIF_RETURNONLYFSDIRS,this,0);
	cFolderPikerDialog.m_ofn.lpstrTitle = TEXT("请选择一个文件夹");
	cFolderPikerDialog.ApplyOFNToShellDialog();
	
	hwndList = ::GetDlgItem(this->m_hWnd, IDC_LIST_FILENAME);
	if (cFolderPikerDialog.DoModal() == IDOK)
	{
		::SetDlgItemText(this->m_hWnd, IDC_STATIC_DIR,cFolderPikerDialog.GetPathName());
		::StringCchCopy(szSearch,_countof(szSearch), cFolderPikerDialog.GetPathName());

		if (szSearch[_tcslen(szSearch) - 1] != TEXT('\\'))
		{
			::StringCchCat(szSearch, _countof(szSearch), TEXT("\\"));
		}

		::StringCchCat(szSearch, _countof(szSearch), TEXT("*"));
		 bRet = cFileFinder.FindFile(szSearch);
		 if (bRet)
		 {
			 ::SendMessage(hwndList, LB_RESETCONTENT,0,0);
			 do
			 {
				 bRet = cFileFinder.FindNextFile();
				 if (!cFileFinder.IsDirectory())
				 {
					 
					 ::SendMessage(hwndList,LB_ADDSTRING,0, (LPARAM) cFileFinder.GetFilePath().GetString());

				 }


			 } while (bRet);


		 }


		
	}


}

到了这里,关于28_UI通用对话框多少会一点之浏览文件夹与遍历目录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • element Ui对话框样式修改(样式篇)

    先给对话框添头部和尾部添加边框线 在给对话框添加圆角

    2024年02月14日
    浏览(43)
  • element-ui实现一个动态布局的对话框

     我把组件上传到npm了,具体使用方法请看:https://gitee.com/zengyanfang/tablelist-way/blob/master/README.md#%E5%8F%82%E6%95%B0 前言:在工作中有各种各样的对话框,最多就是填写信息这些的,一般这样的内容都是el-input输入框,el-select选择框等等之内的,这时我们就可以封装成一个组件,想

    2024年02月01日
    浏览(45)
  • NextJS开发:封装shadcn/ui中的AlertDialog确认对话框

    shadcn/ui很灵活可以方便的自己修改class样式,但是仅仅一个确认删除弹窗,需要拷贝太多代码和导入太多包,重复的代码量太多,不利于代码维护。所以进一步封装以符合项目中使用。 封装cx-alert-dialog.tsx custom-button.tsx 使用CxAlertDialog组件

    2024年02月04日
    浏览(43)
  • element-ui的 Dialog 对话框添加背景图片

    效果展示

    2024年02月12日
    浏览(37)
  • Element UI Dialog 对话框改成固定高度,超出部分滚动条滚动

    elememt ui 中的el-dialog对话框如果 内容过多高度会被无限拉长 。要将其设置成固定高度,此处我设置的是 页面总高度的70% ,内容过多时在对话框内出现 滚动条 。但是这样设置会造成高度不能根据内容自适应,始终是70%。可以有两种方法实现: 方法二 : 主要是运用element ui 中

    2024年02月12日
    浏览(37)
  • Pyside6(3): 自动生成UI的Qt参数输入对话框

    参数输入界面是桌面软件开发最繁琐的部分之一。特别是当系统中存在多种可编辑的数值模型时,由于各个模型的字段不同,每个字段的输入类型也不同,需要制作不同的UI,使用不同的UI控件,无疑会耗费大量时间,同时拓展性也非常差,因为每增加一个数值模型,都需要制

    2024年02月03日
    浏览(56)
  • Rust UI开发(三):iced如何打开图片(对话框)并在窗口显示图片?

    注:此文适合于对rust有一些了解的朋友 iced是一个跨平台的GUI库,用于为rust语言程序构建UI界面。 这是一个系列博文,本文是第三篇,前两篇的链接: 1、Rust UI开发(一):使用iced构建UI时,如何在界面显示中文字符 2、Rust UI开发(二):iced中如何为窗口添加icon图标 本篇是

    2024年02月04日
    浏览(85)
  • element ui Dialog 对话框关闭后——清除表单的效验方法(更简便写法)

    效果展示: 主要代码:在关闭弹窗时 有个组件的关闭的回调 @close=\\\'cancel\\\' 调用这 cancel方法就可以实现 关闭的同时清除表单效验 完整代码展示 父组件: 子组件:

    2024年02月03日
    浏览(40)
  • 解决问题:Element ui组件中Dialog对话框只显示遮罩层,不显示弹框内容

    以下是Dialog 对话框的基本用法: 这个时候页面只显示了遮罩层,但是不显示弹框的内容,查阅文档后,发现有这样一条: append-to-body的默认值是false,所以需要自己在el-dialog标签中手动设置为true,  加上之后弹框内容就可以显示了。

    2024年02月06日
    浏览(54)
  • QT调用不同UI界面响应,对话框跳转到主页面UI,用信号与槽传递信息,两级信号传递

    在MainWindow界面有一个按键”新建”,点击后需要生成一个输入对话框,实例用到了processDialog类对象。 我新建一行数据完成后,需要更新MainWindow表格的视图,此时就需要调用写在MainWIndow下的函数MainWindow::showProcess(vectorPCB* readyQueue) 但是如果实例化一个MainWidow对象,此时修改的

    2024年02月12日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包