1. 程式人生 > >Windows遍歷全盤所搜檔案,並通過多執行緒顯示搜尋進度(C++/C)

Windows遍歷全盤所搜檔案,並通過多執行緒顯示搜尋進度(C++/C)

程式設計軟體,系統

軟體:VS2017
工程屬性:MFC對話方塊(其他工程屬性稍作修改也適用)
系統:windows10家庭版

主要思想

1、利用CFileFind實現查詢檔案
2、利用遞迴實現全盤搜尋
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個字母

下面這兩個函式也不是手動敲的,具體的新增方式參考這兩篇文章,OnShowWindowOnTimer

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,希望發現的朋友可以與本人聯絡,優化程式碼,互相討論,共同進步。