封装Win32打开文件和文件夹的函数

这篇博客介绍了一个C++类,用于简化打开文件和文件夹选择对话框,并读取指定类型的文件。类中包含了宽字符和窄字符版本的方法,支持打开文件对话框、选择文件夹对话框,以及从文件夹中筛选特定类型的文件(如.json)。通过示例代码展示了如何在类外部调用这些功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在应用程序当中打开文件夹选择一个或多个文件进行操作非常普遍;打开文件夹选择一个文件夹存放内容也很多。但是相关函数又很复杂,需要给复杂的结构体赋值。为此,我封装了一个类,方便以后的调用。
废话少说,上代码:
定义类的头文件:OpenFileClass.h

#pragma once
#include"stdafx.h"
#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容
#include <windows.h>//打开对话框要用到
//打开保存文件对话框
#include<Commdlg.h>
//选择文件夹对话框
#include<Shlobj.h>

#include <stdlib.h>
#include<iostream>
#include <malloc.h>
#include <string>       // string
#include <atlstr.h>		//CString的头文件:
#include<vector>
//没有照样运行:#pragma comment(lib,"Shell32.lib")

class OpenFileClass
{
public:
	OpenFileClass()
	{

	}
	~OpenFileClass()
	{

	}
private:
	/*
	从选定的文件夹里面读取所有的文件,宽字符版本
	WCHAR* szBuffer类型的参数可以实现输入输出
	*/
	void GetDirectoryW(WCHAR* szBuffer)
	{
		BROWSEINFOW bi = { 0 };
		bi.hwndOwner = NULL;//拥有着窗口句柄,为NULL表示对话框是非模态的,实际应用中一般都要有这个句柄
		bi.pszDisplayName = szBuffer;//接收文件夹的缓冲区
		bi.lpszTitle = TEXT("选择一个文件夹");//标题
		bi.ulFlags = BIF_NEWDIALOGSTYLE;
		//为显示允许用户选择一个目录而不是一个文件的对话框,要调用SHBrowseForFolder函数。
		LPITEMIDLIST idl = SHBrowseForFolderW(&bi);
		if (!SHGetPathFromIDListW(idl, szBuffer))
		{
			MessageBox(NULL, TEXT("请选择一个文件夹"), NULL, MB_ICONERROR);
		}
		else
		{
			//如果在这里使用函数GetCurrentDirectory(),是不是就可以打开文件夹所属的所有文件呢
			//MessageBoxW(NULL, szBuffer, TEXT("GetDirectory_1函数内部,你选择的文件夹"), 0);
		}
	}
	/*
	从选定的文件夹里面读取所有的文件,窄字符版本
	char* szBuffer类型的参数可以实现输入输出
	*/
	void GetDirectoryA(char* szBuffer)
	{
		BROWSEINFOA bi = { 0 };
		bi.hwndOwner = NULL;//拥有着窗口句柄,为NULL表示对话框是非模态的,实际应用中一般都要有这个句柄
		bi.pszDisplayName = szBuffer;//接收文件夹的缓冲区
		bi.lpszTitle = "选择一个文件夹";//标题
		bi.ulFlags = BIF_NEWDIALOGSTYLE;
		//为显示允许用户选择一个目录而不是一个文件的对话框,要调用SHBrowseForFolder函数。
		LPITEMIDLIST idl = SHBrowseForFolderA(&bi);
		if (!SHGetPathFromIDListA(idl, szBuffer))
		{
			MessageBoxA(NULL, "请选择一个文件夹", "发生了错误!", MB_ICONERROR);
		}
	}


	//打开文件夹,获取文件夹内文件
	//注意了,注意了,我只读取json文档
	std::vector<std::string> GetFilesFromDirectoryA(char* DirectoryPath)
	{
		//char DirectoryPath[126];
		GetCurrentDirectoryA(sizeof(DirectoryPath), DirectoryPath);//指定文件夹
		lstrcatA(DirectoryPath, "\\*.json");//给获取到的文件路径添加文件后缀,便于搜索
		WIN32_FIND_DATAA winFndData;//这个结构体是用来保存信息的,而不是为了入参(凡是以结构体指针入参的,都是输入输出)
		//lstrcpyA(winFndData.cAlternateFileName,"*/" );
		//第一个参数决定了我们在tmp这个文件夹路径下能获得什么,文件类型(后缀决定)、文件夹
		HANDLE FileHandle = FindFirstFileA(DirectoryPath, &winFndData);
		//FileNames.push_back(myFilePath);
		//FileNames.push_back(winFndData.cFileName);//找到的第一个文件
		std::vector<std::string>FileNames;
		if (FileHandle == INVALID_HANDLE_VALUE)
		{
			MessageBoxA(NULL, "文件夹内没有相对应的文件类型", "发生错误", MB_OK);
		}
		else
		{
			while (FindNextFileA(FileHandle, &winFndData))
			{
				//如果是文件,我才输入
				if (winFndData.dwFileAttributes & FILE_SHARE_READ || FILE_SHARE_WRITE)//文件属性决定了是隐藏文件还是加密文件、文件夹
				{
					FileNames.push_back(winFndData.cFileName);//这里得到的时全路径文件名
				}
			}
		}
		return FileNames;
	}
	//打开文件夹,获取文件夹内文件
	//注意了,注意了,我只读取json文档
	std::vector<CString> GetFilesFromDirectoryW(wchar_t* DirectoryPath)
	{
		//char DirectoryPath[126];
		GetCurrentDirectoryW(sizeof(DirectoryPath), DirectoryPath);//指定文件夹
		lstrcatW(DirectoryPath, L"\\*.json");//给获取到的文件路径添加文件后缀,便于搜索
		WIN32_FIND_DATAW winFndData;//这个结构体是用来保存信息的,而不是为了入参(凡是以结构体指针入参的,都是输入输出)
		//lstrcpyA(winFndData.cAlternateFileName,"*/" );
		//第一个参数决定了我们在tmp这个文件夹路径下能获得什么,文件类型(后缀决定)、文件夹
		HANDLE FileHandle = FindFirstFileW(DirectoryPath, &winFndData);
		//FileNames.push_back(myFilePath);
		//FileNames.push_back(winFndData.cFileName);//找到的第一个文件
		std::vector<CString>FileNames;//可以放入宽字符么???
		if (FileHandle == INVALID_HANDLE_VALUE)
		{
			MessageBoxW(NULL, L"文件夹内没有相对应的文件类型", L"发生错误", MB_OK);
		}
		else
		{
			while (FindNextFileW(FileHandle, &winFndData))
			{
				//如果是文件,我才输入
				if (winFndData.dwFileAttributes & FILE_SHARE_READ || FILE_SHARE_WRITE)//文件属性决定了是隐藏文件还是加密文件、文件夹
				{
					//不可以把宽字符的字符串输入到string里面。现在FileNames定义的是cstring类型
					//这里得到的时全路径文件名
					FileNames.push_back(winFndData.cFileName);
				}
			}
		}
		return FileNames;
	}

public:
	//获得文件路径及文件名,
	//char*strFilename类型的参数可以实现输入输出
	void  GetFilePathA(char*strFilenameBuffer)
	{
		OPENFILENAMEA open;							// 公共对话框结构。
		ZeroMemory(&open, sizeof(OPENFILENAME));	// 初始化选择文件对话框
		open.lStructSize = sizeof(OPENFILENAME);	//指定这个结构的大小,以字节为单位。
		open.lpstrFile = strFilenameBuffer;				//打开的文件的全路径
		open.lpstrFilter = "json文件(*.json)\0*.json\0表格文件(*.csv)\0*.csv\0表格文件(.xls)\0*.xls\0\0";  //打开文件类型
		open.nFilterIndex = 1;					//指定在文件类型控件中当前选择的过滤器的索引
		open.lpstrFile[0] = '\0';				//第一个字符串是过滤器描述的显示字符串
		open.nMaxFile = MAX_PATH;				//指定lpstrFile缓冲的大小,以TCHARs为单位
		open.lpstrTitle = "选择一个文件";		// 对话框的窗口标题
		open.lpstrFileTitle = NULL;				// 指向接收选择的文件的文件名和扩展名的缓冲(不带路径信息)。这个成员可以是NULL。
		open.nMaxFileTitle = 0;					//指定lpstrFileTitle缓冲的大小,以TCHARs为单位
		open.lpstrInitialDir = NULL;			//指向以空字符结束的字符串,可以在这个字符串中指定初始目录。
		open.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;//位标记的设置,你可以使用来初始化对话框

		//函数功能:该函数创建一个Open公共对话框,使用户指定驱动器、目录和文件名、或使用户打开文件。
		//Ipofn:指向包含初始化对话框的信息的一个OPENFILENAME结构。当OpenfileName函数返回时,此结构包含有关用户文件选择的信息。
		//返回值:如果用户指定了一个文件名,点击OK按钮,返回值为非零。
		//由OPENFILENAME结构的IPstrFile成员指向的缓冲区含有全路径和用户指定的文件名。
		//如果用户取消或关闭Open对话框或错误出现,返回值为零。若想获得更多的错误信息,请调用CommDlgExtendedError函数。
		//GetOpenFileName (&open) ;//打开文件对话框
		//GetSaveFileName(&open);//保存文件对话框
		if (!GetOpenFileNameA(&open))  // 显示打开选择文件对话框。  
		{
			printf_s("没有选择文件:%s\n", strFilenameBuffer);
			MessageBoxA(NULL, strFilenameBuffer, "发生了错误", MB_ICONERROR);//错误的
		}
		else//正确的情况
		{
			//CString path = strFilename;
			//wprintf_s(path + "\n");

			//printf_s("%s\n",file);

			//strFilename仅仅是一个文件的全路径名称,需要去掉文件名才能成为路径,以参数的形式入参下面的函数里面
			//myFiles = GetFilesFromDirectory(strFilename);
			//MessageBoxA(NULL, strFilename, "选择的文件", 0);//正确的
		}
	}

	//获得文件的全路径名称
	//WCHAR* strFilename类型的参数可以实现输入输出
	void GetFilePathW(WCHAR* strFilenameBuffer)
	{
		OPENFILENAMEW open;							// 公共对话框结构。
		ZeroMemory(&open, sizeof(OPENFILENAME));	// 初始化选择文件对话框
		open.lStructSize = sizeof(OPENFILENAME);	//指定这个结构的大小,以字节为单位。
		open.lpstrFile = strFilenameBuffer;				//打开的文件的全路径
		open.lpstrFilter = L"json文件(*.json)\0*.json\0表格文件(*.csv)\0*.csv\0表格文件(.xls)\0*.xls\0\0";  //打开文件类型
		open.nFilterIndex = 1;					//指定在文件类型控件中当前选择的过滤器的索引
		open.lpstrFile[0] = L'\0';				//第一个字符串是过滤器描述的显示字符串
		open.nMaxFile = MAX_PATH;				//指定lpstrFile缓冲的大小,以TCHARs为单位
		open.lpstrTitle = L"选择一个文件";		// 对话框的窗口标题
		open.lpstrFileTitle = NULL;				// 指向接收选择的文件的文件名和扩展名的缓冲(不带路径信息)。这个成员可以是NULL。
		open.nMaxFileTitle = 0;					//指定lpstrFileTitle缓冲的大小,以TCHARs为单位
		open.lpstrInitialDir = NULL;			//指向以空字符结束的字符串,可以在这个字符串中指定初始目录。
		open.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;//位标记的设置,你可以使用来初始化对话框

		//函数功能:该函数创建一个Open公共对话框,使用户指定驱动器、目录和文件名、或使用户打开文件。
		//Ipofn:指向包含初始化对话框的信息的一个OPENFILENAME结构。当OpenfileName函数返回时,此结构包含有关用户文件选择的信息。
		//返回值:如果用户指定了一个文件名,点击OK按钮,返回值为非零。
		//由OPENFILENAME结构的IPstrFile成员指向的缓冲区含有全路径和用户指定的文件名。
		//如果用户取消或关闭Open对话框或错误出现,返回值为零。若想获得更多的错误信息,请调用CommDlgExtendedError函数。
		//GetOpenFileName (&open) ;//打开文件对话框
		//GetSaveFileName(&open);//保存文件对话框
		if (!GetOpenFileNameW(&open))
		{
			MessageBoxW(NULL, L"请选择一个文件", NULL, MB_ICONERROR);
		}
		else//正确的情况,因为我们有了输入输出的机制
		{
			//MessageBoxW(NULL, strFilename, L"选择的文件", 0);
		}

	}

	//从选定的文件夹里面读取特定的一系列文件
	std::vector<CString>  GetDirectoryFilesW()
	{
		wchar_t szBuffer[MAX_PATH] = { 0 };//今日进一步理解了输入输出参数的机制
		GetDirectoryW(szBuffer);//这是一个弹出对话框的阻塞式函数
		//MessageBoxW(NULL, szBuffer, L"你选择的文件夹", 0);
		return GetFilesFromDirectoryW(szBuffer);
	}
	//从选定的文件夹里面读取特定的一系列文件
	std::vector<std::string> GetDirectoryFilesA()
	{
		char szBuffer[MAX_PATH] = { 0 };//今日进一步理解了输入输出参数的机制
		GetDirectoryA(szBuffer);//这是一个弹出对话框的阻塞式函数
		//MessageBoxA(NULL, szBuffer, "你选择的文件夹", 0);
		return GetFilesFromDirectoryA(szBuffer);//从文件夹里面获取我们需要的文件
	}
};




调用OpenFileClass类的cpp文件:

#include"OpenFileClass.h"

OpenFileClass OFC;
int main()
{
	//测试1、
	//wchar_t wFileName[256];
	//OFC.GetFilePathW(wFileName);			//没有问题
	//MessageBoxW(NULL, wFileName, L"宽字符,类外的结果", MB_OK);//成功了

	//测试2、
	//char cFileName[256];
	//OFC.GetFilePathA(cFileName);			//没有问题
	//MessageBoxA(NULL, cFileName, "窄字符,类外的结果", MB_OK);//成功了

	//测试3、
	//注意了,注意了,我只读取json文档
	//std::vector<std::string> myFiles =	OFC.GetDirectoryFilesA();			//没有问题
	//for (auto itr = myFiles.begin(); itr != myFiles.end(); ++itr)
	//{
	//	printf_s("文件:%s\n", itr->c_str());
	//}
	//myFiles.clear();


	//测试4、
	//注意了,注意了,我只读取json文档
	std::vector<CString> myFiles = OFC.GetDirectoryFilesW();			//没有问题
	for (auto itr = myFiles.begin(); itr != myFiles.end(); ++itr)
	{
		//printf_s("文件:%s\n", itr->c_str());//CString类型的数据更方便使用c_str()得到多字节字符串,无须转换

		//wprintf_s(L"文件:%s\n", itr->GetString());//无法输出uincode字符串,uincode字符串只在win32窗口界面下使用,不能在控制台输出
		//std::cout << itr->GetBuffer() << std::endl;//无法输出uincode字符串,uincode字符串只在win32窗口界面下使用,不能在控制台输出
		//std::cout << itr->GetString() << std::endl;//无法输出uincode字符串,uincode字符串只在win32窗口界面下使用,不能在控制台输出
	}
	MessageBoxW(NULL, myFiles.at(1), L"看看第一个文件名", MB_OK);//uincode字符串只在win32窗口界面下使用,不能在控制台输出
	myFiles.clear();




	getchar();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值