Windows遍历全盘所搜文件,并通过多线程显示搜索进度(C++/C)

编程软件,系统

软件:VS2017
工程属性:MFC对话框(其他工程属性稍作修改也适用)
系统:windows10家庭版

主要思想

1、利用CFileFind实现查找文件
2、利用递归实现全盘搜索
3、多线程实现父对话框搜索文件时,子对话框显示搜索进度

软件运行效果图

Windows遍历全盘所搜文件,并通过多线程显示搜索进度(C++/C)_第1张图片

Windows遍历全盘所搜文件,并通过多线程显示搜索进度(C++/C)_第2张图片

Windows遍历全盘所搜文件,并通过多线程显示搜索进度(C++/C)_第3张图片

代码实现

1、父对话框负责搜索文件,和分配多线程,所用函数代码如下

//全局变量定义
extern CString m_pass;  //用来显示被找到的文件路径
extern int IShowTime1;  //用来更新进度条
//父对话框类函数及变量声明
//由于静态函数无法使用动态变量,所以一下所有函数及变量多使用了静态变量/全局变量
static CString CFindFile(const TCHAR *szPath, const TCHAR *szFileName, CStringArray *paStrResult);
static CString load1;
static UINT ChangeProcessBox(LPVOID pParam);
static UINT FindFileBotton(LPVOID pParam);
//按下搜索路径按钮后执行该函数
UINT CAutoChangeBlackMapDlg::FindFileBotton(LPVOID pParam)   
{
	// TODO: 在此处添加实现代码.
	TCHAR *szPath;
	TCHAR *szFileName = _T("你要上搜索的文件名字,带后缀");
	CStringArray paStrResult;

	for (char x = 'Z'; x >= 'A'; x--) //全盘搜索
	{
		CString x1(x);
		CString StrPath1 = x1 + _T(":\\");
		if (PathIsDirectory((LPCTSTR)StrPath1) == FALSE)
		{
			x=x;
		}
		else
		{
			szPath = StrPath1.GetBuffer(StrPath1.GetLength());
			StrPath1.ReleaseBuffer();
			load1 = CAutoChangeBlackMapDlg::CFindFile(szPath, szFileName, &paStrResult); //核心搜索函数
		}
		IShowTime1++;
	}
	return 0;
}
//控制进度条变化
UINT CAutoChangeBlackMapDlg::ChangeProcessBox(LPVOID pParam) 
{
	// TODO: 在此处添加实现代码.
	while (IShowTime1 != 26)
	{
		for (int i = 0; i < 1000; i++)
		{

			//Sleep(50);
		}
	}
	return 0;
}
CString CAutoChangeBlackMapDlg::CFindFile(const TCHAR *szPath, const TCHAR *szFileName, CStringArray *paStrResult)
//递归搜索全盘文件
//第一个参数为要搜索的路径,比如"c:\\dir\\"或"c:\\dir"则在包括此目录的所有子目录下搜索
//第二个参数为要搜索的文件,比如"qq.txt",需要提供文件后缀,大小写不敏感  
//第三个参数用于保存搜索到的文件的全路径,请构造一个CStringArray对象并传入地址
{
	// TODO: 在此处添加实现代码.
	ASSERT(paStrResult != NULL);

	CString StrPath(szPath);

	CString StrFileName(szFileName);

	//检查路径字符串的最后一个字符是不是'\',不是则加上  

	if (StrPath[StrPath.GetLength() - 1] != _T('\\'))

		StrPath += _T('\\');


	CString StrFindPath = StrPath + _T("*.*");

	//开始查找  

	CFileFind finder;
	BOOL bWorking = finder.FindFile(StrFindPath);

	while (bWorking)

	{

		bWorking = finder.FindNextFile();

		//如果找到的是文件夹,递归进去  

		if (finder.IsDirectory() && !finder.IsDots())

		{

			CFindFile(StrPath + finder.GetFileName(), StrFileName, paStrResult);

		}

		//如果找到了文件,将绝对路径添加进字符串数组,大小写不敏感  

		if (finder.GetFileName().CompareNoCase(StrFileName) == 0)

		{

			paStrResult->Add(finder.GetFilePath());

		}
	}

	
	//将字符串数组中的内容存储到字符串中
	int iden = paStrResult->GetSize();
	CString load;
	
	if (iden == 0)
	{
		load = _T("1");
	}
	else if (iden > 1)
	{
		load = _T("2");
	}
	else
	{
		for (int i = 0; i < iden; i++)
		{
			load = load + paStrResult->GetAt(i);
		}
	}
	return load;
}
//多线程分配
AfxBeginThread(FindFileBotton, this);
AfxBeginThread(ChangeProcessBox, this);
//这个地方是为了打开进度条的对话框,也就是子对话框
showTime dlg2;  //showTime类是用来显示进度条的,在下面会展示该类里面的函数
dlg2.DoModal();

2、子对话框负责显示进度条,代码如下

//初始化进度条,在OnInitDialog函数中实现,这个函数是在类属性的添加虚函数中添加,不需要手动敲上去
m_process.SetRange(0, 26); //初始化进度条范围,因为有26个字母

下面这两个函数也不是手动敲的,具体的添加方式参考这两篇文章,OnShowWindow,OnTimer

void showTime::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialogEx::OnTimer(nIDEvent);
	m_process.SetPos(IShowTime1);
	if (IShowTime1 == 26)
	{
		OnOK();
	}
}
void showTime::OnShowWindow(BOOL bShow, UINT nStatus)
{
	CDialogEx::OnShowWindow(bShow, nStatus);

	// TODO: 在此处添加消息处理程序代码
	this->KillTimer(1);
	this->SetTimer(1, 20, NULL);
}

参考文献

https://www.2cto.com/kf/201303/194024.html
https://blog.csdn.net/blogcaicai01/article/details/47006879
https://blog.csdn.net/qq_33723441/article/details/54599022
http://blog.sina.com.cn/s/blog_4a4839570102v5ba.html

最后

代码在本机调试没有问题,各位朋友在使用的时候可能需要按照自身的情况加以修改,本人技术有限,代码中会有隐含的bug,希望发现的朋友可以与本人联系,优化代码,互相讨论,共同进步。

你可能感兴趣的:(编程)