MFC C + + build file explorer (tree control version)

Posted by madrazel on Tue, 01 Feb 2022 05:45:58 +0100

Today, let's teach you how to make a self-made file resource manager (・).

compiler:Visual Studio 2019

Objectives:
1. Learn to use multithreading
2. Learn to recursively traverse all folders

Here are the teaching hours:

  1. Open the compiler and create an MFC application


  2. Draw bed mouth




  1. Create a thread
    Note: because the workload is large when traversing the file, multithreading should be used to prevent the interface from faking death.
    Write under / / CFileTreeDlg message handler
DWORD WINAPI EnumFileThread(LPARAM lParam)
{
	CFileTreeDlg* dlg = (CFileTreeDlg*)lParam;
	return 0;
}

Then create a thread in OnInitDialog():

BOOL CFileTreeDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// Set the icon for this dialog box. When the main window of the application is not a dialog box, the frame will automatically
	//  Do this
	SetIcon(m_hIcon, TRUE);			// Set large icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: add additional initialization code here
	//Prevent interface fake death
	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)EnumFileThread, this, 0, NULL);

	return TRUE;  // Returns TRUE unless the focus is set to the control
}
  1. Get drive letter
    When inserting a file, we need to know where to insert it, so add a member variable:
HTREEITEM m_hTreeItem;

In OnInitDialog() / / TODO: add additional initialization code here. Write below

	//Tree Root control operation
	m_hRootItem = m_tree.InsertItem(L"My computer");

Now let's get the drive letter.
We will use this function: GetLogicalDriveStrings

DWORD GetLogicalDriveStrings(
  DWORD nBufferLength,
  LPTSTR lpBuffer
);

Parameters:

  • nBufferLength
    [in]lpBuffer indicates the maximum size of the buffer, in TCHARS. This size does not include terminating null characters. If this parameter is zero, lpBuffer is not used.

  • lpBuffer.
    [out] pointer to a buffer that receives a series of null terminated strings, one for each valid dnive in the system, plus an additional null character. Each string is a device name.

Then CFileTreeDlg* dlg = (CFileTreeDlg*)lParam; Write below

	wchar_t szBuffer[256] = { 0 };
	DWORD dwLength = GetLogicalDriveStrings(sizeof szBuffer, szBuffer);

	//Cycle display drive letter
	for (int i = 0; i < dwLength / 4/*Here we should pay attention to divide by 4*/; i++)
	{
		CString strPANFU = szBuffer + 4 * i;
		//Insert tree control
		HTREEITEM hRootItem = dlg->m_FileTree.InsertItem(strPANFU, dlg->m_hRootItem);
	}
	return 0;
  1. Traversal file
    The next step is the most important step of the file tree.
    First define a member function FindFile();
void FindFile(
		/*route*/		CString strFileRootPath,
		/*Temp Tree node*/	HTREEITEM hRootItem);

In a multithreaded function, htreeitem hroottitem = DLG - > m_ FileTree. InsertItem(strPANFU, dlg->m_hRootItem); Write below

dlg->FindFile(strPANFU, hRootItem);

The function looks like this:

void CFileTreeDlg::FindFile(
	/*File directory*/		CString strFileRootPath,
	/*Temp Tree node*/	HTREEITEM hRootItem)
{
	CFileFind finder;
	CString strFilePath;
	strFilePath = strFileRootPath + L"*.*";//*. * ☞ all documents

	//Record current node
	HTREEITEM hTemp;

	BOOL bRes;
	bRes = finder.FindFile(strFilePath);//See if this path exists
	while (bRes)
	{
		bRes = finder.FindNextFile();//Find the next file along the
		if (!finder.IsDots())//Whether IsDots is Or
		{
			if (finder.IsDirectory())
			{
				CString strFileName = finder.GetFileName();
				CString strFilePath = finder.GetFilePath() + L"\\*.*";
				hTemp = m_tree.InsertItem(strFileName, hRootItem);
				FindFile(strFilePath, hTemp);
			}
			else
			{
				CString strFileName = finder.GetFileName();
				m_tree.InsertItem(strFileName, hRootItem);
			}
		}
	}
}

Here we traverse the file using a class called CFileFind

  • MFC class CFileFind performs local file search and is the base class of CGopherFileFind and CFtpFileFind; The latter two categories are used for Internet File lookup. CFileFind includes member functions to start searching, locate files, and return Title names or paths. For Internet lookup, GetFileURL returns the URL of the file.
    CFileFind is the base class of MFC class designed for other two kinds of special servers. CGopherFileFind works on Gopher server and CFtpFileFind works on FTP server. These classes provide a seamless mechanism for users to find files, which is independent of server protocol, file type, location, local machine or remote server.

First, enter the drive letter, like this:

	CFileFind finder;
	CString strFilePath;
	strFilePath = strFileRootPath + L"*.*";//*. * ☞ all documents

	//Record current node
	HTREEITEM hTemp;

	BOOL bRes;
	bRes = finder.FindFile(strFilePath);//See if this path exists

After successful entry, traverse the file:

	while (bRes)
	{
		bRes = finder.FindNextFile();
		if (finder.IsDirectory())//If it is a folder, go into the folder and find it
		{
			CString strFileName = finder.GetFileName();
			CString strFilePath = finder.GetFilePath() + L"\\*.*";
			hTemp/*Mark the path this time*/ = m_tree.InsertItem(strFileName, hRootItem);
			/*Recursive search*/FindFile(strFilePath, hTemp);
		}
		else//If a file is found, a tree control is inserted
		{
			CString strFileName = finder.GetFileName();
			m_tree.InsertItem(strFileName, hRootItem);
		}
	}

Now let's try to run

Therefore, when traversing the file, we should avoid "." And "..."
Modification code:

	while (bRes)
	{
		bRes = finder.FindNextFile();
		if (!finder.IsDots())//Whether IsDots is Or
		{
			if (finder.IsDirectory())
			{
				CString strFileName = finder.GetFileName();
				CString strFilePath = finder.GetFilePath() + L"\\*.*";
				hTemp = m_tree.InsertItem(strFileName, hRootItem);
				FindFile(strFilePath, hTemp);
			}
			else
			{
				CString strFileName = finder.GetFileName();
				m_tree.InsertItem(strFileName, hRootItem);
			}
		}
	}

Try in one run:

Success!!!!

If it's not easy to make comments in this tutorial area (・ if it's not easy to make comments.). Bye bye!

Topics: C++