Windows应用开发-目录比对

下载本应用
有时我们安装一个软件,想知道哪些文件是该软件创建的,这时就需要,将当前的磁盘目录与安装软件前的磁盘目录进行比较。出于此目的,编写了“目录比对”Windows应用。
在这里插入图片描述

使用方法

软件界面有两个树控件,左侧的我们将其命名为“原始目录”,右侧的命名为“当前目录”;使用任一树控件,右击弹出右键菜单,点击“加载磁盘目录”菜单项,可以选择某个文件夹,或直接选择根目录,比如C盘;将磁盘目录加载到树控件,然后点击右键菜单项,保存到文件。可以将文件命名为“原始C目录”,这时安装需要检测其安装文件目录信息的软件,安装完成后,将“原始C目录”文件加载到“原始目录”树控件,在“当前目录”树控件加载现在的C盘目录。加载完成后,点击“开始比对”按钮,将“原始目录”树控件,与“当前目录”树控件的项文本进行比较,新增的文件和文件夹项,在其左侧添加了“+”状态图像,如果是文件夹,其所有子项都为新增项。这时,可以直观的知道那些文件新创建的。还可以将新创建的文件路径保存到TXT文件。方法是选中根目录项,或其某个子项,在右键菜单中点击“添加的文件信息”,弹出“添加的文件信息”对话框,所有添加文件的路径列表显示在窗口中,全选路径列表然后保存到文件。具有红色图像的项,表示其子项中包含具有“+”图像的项。比对完成后,“原始目录”还可以显示被删除的项,其添加了“-”图像,被删除项的所有父项将添加黑色图像。

“目录比对”开发信息

树控件是可以比较的,本示例就是比较两个树控件的项文本。相同项不做标记,给不同项添加状态图像。比较在MyCheck函数中进行,GetChildInfo函数获取指定项的所有子项的数量,项文本,项句柄,并做标记。首先传递给MyCheck函数两个NULL参数,分别获取“原始目录”,“当前目录”的NULL子项信息,也就是获取所有根项信息,将“原始目录”所有根项标记-1,将“当前目录”所有根项标记1。建立嵌套的for循环,将“原始目录”中的文本相同项,重新标记为0,将“当前目录”中的文本相同项,也标记为0,这样,“原始目录”中的不同项标记仍为-1,“当前目录”中的不同项标记仍为1,将“原始目录”中标记-1的项添加状态图像“-”,将“当前目录”中标记1的项添加状态图像“+”。不同项就没有比较的需要了,将所有相同项进行子项的比较,在MyCheck函数内,调用MyCheck函数,传入的参数为“原始目录”相同项的句柄和“当前目录”相同项的句柄。获取子项信息时,为每个子项信息都使用new创建了INFO结构对象,使用完成后,需delete。
程序使用MFC对话框应用程序创建。

“目录比对”应用的所有代码

目录比对Dlg.h


// 目录比对Dlg.h : 头文件
//

#pragma once
#include "afxcmn.h"
#include "afxwin.h"
#include "afxshelltreectrl.h"
#include "MyTree.h"
#include "MyButton.h"
#include "Dlg1.h"
#include "Dlg2.h"

class USE//用于在不同线程中访问对话框控件时,避免访问冲突
{
public:
	USE()
	{
		hNotUse = CreateEvent(NULL, TRUE, TRUE, NULL);//手动重置,初始有信号
	}
	HANDLE hNotUse = NULL;//“没有占用”事件句柄
	void BeginUse()//开始占用
	{
		WaitForSingleObject(hNotUse, INFINITE);
		ResetEvent(hNotUse);
	}
	void EndUse()//结束占用
	{
		SetEvent(hNotUse);
	}
};

class C目录比对Dlg : public CDialogEx
{
// 构造
public:
	C目录比对Dlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_MY_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	USE use;
	CStatic sta2;//静态文本控件“原始目录”
	CStatic sta3;//静态文本控件“当前目录”
	CStatic sta5;//静态文本控件,显示状态文本
	CMyTree tree1;//树控件1
	CMyTree tree2;//树控件2
	CEdit edit1;//编辑控件1,显示树控件1项数量
	CEdit edit2;//编辑控件2,显示树控件2项数量
	CMyButton Stop_btn;//“停止比对”按钮
	CMyButton Star_btn;//“开始比对”按钮

	CImageList imagelist;
	CFont font1;
	CBrush brush;
	CBrush brush1;
	WCHAR* Path;//当前路径

	afx_msg void OnBnClickedOk();
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);

	void _SetPos();//定位控件

	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);

	HANDLE hExit1;
	BOOL SeekFor1(CString pstr, HTREEITEM h);
	HANDLE hLoadDiskThread1 = NULL;//tree1“加载磁盘目录”线程句柄
	int Count1;
	afx_msg void OnTree132773();//tree1“加载磁盘目录”菜单项,单击响应函数

	HANDLE hLoadFileThread1 = NULL;//tree1“加载文件”线程句柄
	int FileCount1;
	afx_msg void OnTree132771();//tree1“加载文件”菜单项,单击响应函数
	afx_msg void OnTree132774();//tree1“保存到文件”菜单项,单击响应函数
	afx_msg void OnTree132775();//tree1“折叠所有项”菜单项,单击响应函数
	afx_msg void OnTree132780();//tree1“终止任务”菜单项,单击响应函数

	HANDLE hExit2;
	BOOL SeekFor2(CString pstr, HTREEITEM h);
	HANDLE hLoadDiskThread2 = NULL;//tree2“加载磁盘目录”线程句柄
	int Count2;
	afx_msg void OnTree232772();//tree2"加载磁盘目录"菜单项,单击响应函数

	HANDLE hLoadFileThread2 = NULL;
	int FileCount2;
	afx_msg void OnTree232776();//tree2“加载文件”菜单项,单击响应函数
	afx_msg void OnTree232777();//tree2“保存到文件”菜单项,单击响应函数
	afx_msg void OnTree232778();//tree2“折叠所有项”菜单项,单击响应函数
	afx_msg void OnTree232779();//tree2“终止任务”菜单项,单击响应函数

	afx_msg void OnDestroy();

	void Save(CMyTree* pTree);
	void Expand(CMyTree* pTree);

	HANDLE hStop;//"比对停止"事件句柄
	HANDLE hCheckThread = NULL;//比对线程句柄
	UINT COUNT = 0;
	UINT CUR = 0;
	UINT XuHao = 0;
	afx_msg void OnBnClickedButton1();//开始比对
	afx_msg void OnBnClickedButton2();//停止比对

	void MyCheck(HTREEITEM hA, HTREEITEM hB);
	int GetChildInfo(CObArray& X, CMyTree* pTree, HTREEITEM hItem);//获取直接子项的信息,不包括子项的子项
	void SetMask(CMyTree* pTree, HTREEITEM hItem, int index);
	void SetPar(CMyTree* pTree, HTREEITEM hPar, int index);

	CString StateText;
	void SetStateText(CString text);//显示工作状态文本
	CProgressCtrl pro;
	CDlg1 dlg1;
	CDlg2 dlg2;
	afx_msg void OnTree132781();//“删除的文件信息”菜单项,单击响应函数
	afx_msg void OnTree232782();//“增加的文件信息”菜单项,单击响应函数
	CString PlusInfo;
	int GetStateImage(CMyTree* pTree, HTREEITEM hItem);//获取状态图像的索引
	UINT GetCJ(HTREEITEM hItem, CMyTree* pTree);//获取指定项的层次
	CString GetString(HTREEITEM hItem, CMyTree* pTree);//获取项描述字符串
};

目录比对Dlg.cpp


// 目录比对Dlg.cpp : 实现文件
//

#include "stdafx.h"
#include "目录比对.h"
#include "目录比对Dlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// C目录比对Dlg 对话框

C目录比对Dlg::C目录比对Dlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_MY_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);//加载应用程序图标
	font1.CreatePointFont(100, L"微软雅黑");
	brush.CreateSolidBrush(RGB(70, 50, 50));
	brush1.CreateSolidBrush(RGB(70, 90, 90));
	hExit1 = CreateEvent(NULL, TRUE, FALSE, NULL);//手动重置,初始无信号
	hExit2 = CreateEvent(NULL, TRUE, FALSE, NULL);//手动重置,初始无信号
	hStop = CreateEvent(NULL, TRUE, FALSE, NULL);//手动重置,初始无信号
}

void C目录比对Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_TREE1, tree1);
	DDX_Control(pDX, IDC_TREE2, tree2);
	DDX_Control(pDX, IDC_STA2, sta2);
	DDX_Control(pDX, IDC_STA3, sta3);
	DDX_Control(pDX, IDC_STA5, sta5);
	DDX_Control(pDX, IDC_EDIT1, edit1);
	DDX_Control(pDX, IDC_EDIT2, edit2);
	DDX_Control(pDX, IDC_BUTTON2, Stop_btn);
	DDX_Control(pDX, IDC_BUTTON1, Star_btn);
	DDX_Control(pDX, IDC_PROGRESS1, pro);
}

BEGIN_MESSAGE_MAP(C目录比对Dlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDOK, &C目录比对Dlg::OnBnClickedOk)
	ON_BN_CLICKED(IDC_BUTTON1, &C目录比对Dlg::OnBnClickedButton1)
	ON_WM_ERASEBKGND()
	ON_WM_CTLCOLOR()
	ON_COMMAND(ID_TREE2_32772, &C目录比对Dlg::OnTree232772)
	ON_COMMAND(ID_TREE1_32773, &C目录比对Dlg::OnTree132773)
	ON_COMMAND(ID_TREE1_32771, &C目录比对Dlg::OnTree132771)
	ON_COMMAND(ID_TREE1_32774, &C目录比对Dlg::OnTree132774)
	ON_WM_DESTROY()
	ON_COMMAND(ID_TREE1_32775, &C目录比对Dlg::OnTree132775)
	ON_COMMAND(ID_TREE2_32776, &C目录比对Dlg::OnTree232776)
	ON_COMMAND(ID_TREE2_32777, &C目录比对Dlg::OnTree232777)
	ON_COMMAND(ID_TREE2_32778, &C目录比对Dlg::OnTree232778)
	ON_COMMAND(ID_TREE1_32780, &C目录比对Dlg::OnTree132780)
	ON_COMMAND(ID_TREE2_32779, &C目录比对Dlg::OnTree232779)
	ON_BN_CLICKED(IDC_BUTTON2, &C目录比对Dlg::OnBnClickedButton2)
	ON_COMMAND(ID_TREE1_32781, &C目录比对Dlg::OnTree132781)
	ON_COMMAND(ID_TREE2_32782, &C目录比对Dlg::OnTree232782)
END_MESSAGE_MAP()

BOOL C目录比对Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	imagelist.Create(16, 16, ILC_COLOR32, 0, 0);//创建图像列表
	imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON1));//第1个图像不使用
	imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON2));//索引1,“+”图像
	imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON3));//索引2,“-”图像
	imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON4));//索引3,红色图像
	imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON5));//索引4,黑色图像

	tree1.SetImageList(&imagelist, TVSIL_STATE); tree2.SetImageList(&imagelist, TVSIL_STATE);
	sta2.SetFont(&font1); sta3.SetFont(&font1); sta5.SetFont(&font1);
	edit1.SetFont(&font1); edit2.SetFont(&font1);
	tree1.SetFont(&font1); tree2.SetFont(&font1);
	tree1.SetBkColor(RGB(156, 145, 132)); tree2.SetBkColor(RGB(156, 145, 132));
	SetWindowTheme(pro.GetSafeHwnd(), _T(""), _T(""));//设置进度条颜色和背景颜色需关闭视觉样式
	pro.SetBarColor(RGB(250, 60, 10));//设置进度条颜色
	pro.SetBkColor(RGB(70, 90, 90));//设置进度条背景色
	pro.SetRange(0, 100);//指定进度条范围

	CRect rect(0, 0, 780, 600);//设置客户区大小,宽780像素,高600像素
	DWORD style = GetExStyle();//获取对话框扩展样式
	if (style & WS_EX_CLIENTEDGE)//如果对话框包含WS_EX_CLIENTEDGE样式,CalcWindowRect函数参数2使用CWnd::adjustOutside
	{
		CalcWindowRect(rect, CWnd::adjustOutside);//计算带边框的对话框窗口大小。CalcWindowRect函数为CWnd类函数
	}
	else//如果对话框不包含WS_EX_CLIENTEDGE样式,CalcWindowRect函数参数2使用CWnd::adjustBorder
	{
		CalcWindowRect(rect, CWnd::adjustBorder);//计算带边框的对话框窗口大小
	}
	MoveWindow(&rect);//设置对话框的大小
	CenterWindow();//居中对话框

	_SetPos();//定位控件
	CreateDirectory(L"比对数据", NULL);//创建文件夹
	Path = new WCHAR[MAX_PATH];
	GetCurrentDirectory(MAX_PATH, Path);//获取当前路径
	return TRUE;  
}

void C目录比对Dlg::OnDestroy()
{
	CDialogEx::OnDestroy();
	delete[] Path;
}

void C目录比对Dlg::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 C目录比对Dlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void C目录比对Dlg::OnBnClickedOk()
{
}

BOOL C目录比对Dlg::OnEraseBkgnd(CDC* pDC)
{
	CRect rect;
	GetClientRect(rect);
	pDC->FillSolidRect(rect, RGB(70, 50, 50));
	CRect r2, r3;
	tree1.GetWindowRect(r2); ScreenToClient(r2); r2.InflateRect(1, 1);
	tree2.GetWindowRect(r3); ScreenToClient(r3); r3.InflateRect(1, 1);
	pDC->FrameRect(r2, &CBrush(RGB(0, 0, 0)));
	pDC->FrameRect(r3, &CBrush(RGB(0, 0, 0)));
	CRect r5, r6, r7;
	edit1.GetWindowRect(r5); ScreenToClient(r5); r5.InflateRect(1, 1);
	edit2.GetWindowRect(r6); ScreenToClient(r6); r6.InflateRect(1, 1);
	pDC->FrameRect(r5, &CBrush(RGB(0, 0, 0)));
	pDC->FrameRect(r6, &CBrush(RGB(0, 0, 0)));

	CRgn rgn;
	rgn.CreateRectRgn(0, 0, 0, 0);
	pro.GetWindowRgn((HRGN)rgn);
	rgn.GetRgnBox(r7);
	pro.ClientToScreen(r7); ScreenToClient(r7); r7.InflateRect(2, 2,0,0);
	pDC->FrameRect(r7, &CBrush(RGB(0, 0, 0)));
	
	return TRUE;
//	return CDialogEx::OnEraseBkgnd(pDC);
}


void C目录比对Dlg::_SetPos()//
{
	sta2.MoveWindow(10, 6, 376, 20);
	sta3.MoveWindow(394, 6, 376, 20);
	CRect Client_rect;
	GetClientRect(Client_rect);
	sta5.MoveWindow(12, Client_rect.bottom-30, Client_rect.right-24, 20);//静态文本控件,用作状态栏
	tree1.MoveWindow(10, 30, 376, 389);
	tree2.MoveWindow(394, 30, 376, 389);
	edit1.MoveWindow(10, 425, 376, 20);
	edit2.MoveWindow(394, 425, 376, 20);
	pro.MoveWindow(9, 450, Client_rect.right - 16, 24);
	Stop_btn.MoveWindow(108, 486, 180, 40);
	Star_btn.MoveWindow(492, 486, 180, 40);
	
	CRect r1;
	pro.GetClientRect(r1);  r1.DeflateRect(1, 1);
	CRgn rgn;
	rgn.CreateRectRgn(r1.left, r1.top, r1.right, r1.bottom);
	pro.SetWindowRgn(rgn.operator HRGN(), 1);
}


HBRUSH C目录比对Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
	if (pWnd->GetDlgCtrlID() == IDC_STA2 || pWnd->GetDlgCtrlID() == IDC_STA3 || pWnd->GetDlgCtrlID() == IDC_STA5)//
	{
		pDC->SetBkColor(RGB(70, 50, 50));//设置背景颜色
		pDC->SetTextColor(RGB(186, 175, 162));//设置文本颜色
		return (HBRUSH)brush;
	}
	if (pWnd->GetDlgCtrlID() == IDC_EDIT1 || pWnd->GetDlgCtrlID() == IDC_EDIT2)
	{
		pDC->SetBkColor(RGB(70, 90, 90));//设置背景颜色
		pDC->SetTextColor(RGB(187, 186, 220));//设置文本颜色
		return (HBRUSH)brush1;
	}
	return hbr;
}

BOOL C目录比对Dlg::SeekFor1(CString pstr, HTREEITEM h)
{
	CFileFind ff;
	BOOL bWorking = ff.FindFile(pstr, 0);
	while (bWorking)
	{
		DWORD dw = WaitForSingleObject(hExit1, 0);
		if (dw == WAIT_OBJECT_0)
		{
			return TRUE;
		}
		bWorking = ff.FindNextFile();
		if (ff.IsDots())continue;
		CString str1, str2;
		str1 = ff.GetFileName(); str2 = ff.GetFilePath();
		HTREEITEM hItem = tree1.InsertItem(str1, h);
		Count1++;
		use.BeginUse();
		SetDlgItemInt(IDC_EDIT1, Count1);
		use.EndUse();
		if (ff.IsDirectory())//如果是文件夹
			SeekFor1(str2 + L"\\*.*", hItem);
	}
	return FALSE;
}

UINT LoadDiskThread1(LPVOID pParam)//树控件1加载磁盘目录线程
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)pParam;
	BROWSEINFO bi;
	char buffer[MAX_PATH];
	ZeroMemory(buffer, MAX_PATH);
	bi.hwndOwner = pDlg->GetSafeHwnd();
	bi.pidlRoot = NULL;
	bi.pszDisplayName = LPWSTR(buffer);
	bi.lpszTitle = _T("选择一个文件夹");
	bi.ulFlags = BIF_EDITBOX;   
	bi.lpfn = NULL;
	bi.lParam = 0;
	bi.iImage = 0;
	LPITEMIDLIST pList = NULL;
	if ((pList = SHBrowseForFolder(&bi)) == NULL)return (UINT)(pDlg->hLoadDiskThread1 = NULL);
	char path[MAX_PATH];
	ZeroMemory(path, MAX_PATH);
	SHGetPathFromIDList(pList, LPWSTR(path));
	CString SeekPath = LPCTSTR(path);
	CString R = SeekPath.Right(1);
	if (R == L"\\")SeekPath += L"*.*";
	else SeekPath += L"\\*.*";
	CString SeekText = SeekPath;
	int find = SeekText.Find(L"\\*.*");
	if (find != -1)
		SeekText.Delete(find, 4);
	pDlg->tree1.DeleteAllItems();
	ResetEvent(pDlg->hExit1);
	pDlg->use.BeginUse();
	pDlg->sta2.SetWindowText(SeekText);
	pDlg->sta5.SetWindowText(L"“原始目录”加载磁盘目录进行中");
	pDlg->use.EndUse();
	pDlg->Count1 = 0;
	HTREEITEM hITEM = pDlg->tree1.InsertItem(SeekText, NULL);
	pDlg->Count1++;
	pDlg->SeekFor1(SeekPath, hITEM);
	HTREEITEM hRoot = pDlg->tree1.GetRootItem();
	pDlg->tree1.Expand(hRoot, TVE_EXPAND);
	pDlg->SetStateText(L"加载磁盘目录完成");
	return (UINT)(pDlg->hLoadDiskThread1 = NULL);
}

void C目录比对Dlg::OnTree132773()//tree1“加载磁盘目录”菜单项,单击响应函数
{
	if (hLoadDiskThread1 != NULL)return;//如果线程正在运行,不再创建新的线程
	hLoadDiskThread1 = AfxBeginThread(LoadDiskThread1, this, 0, 0, 0)->m_hThread;
}

UINT LoadFileThread1(LPVOID pParam)//树控件1加载文件线程
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)pParam;
	CFileDialog FD(TRUE);
	FD.m_ofn.lpstrInitialDir = (CString)pDlg->Path + L"\\比对数据";//指定初始目录
	FD.m_ofn.lpstrFilter = _T("DAT文件\0*.dat\0\0");//指定过滤器
	if (FD.DoModal() != IDOK)return (UINT)(pDlg->hLoadFileThread1 = NULL);
	ResetEvent(pDlg->hExit1);
	CString PathName = FD.GetPathName();
	CString Name = FD.GetFileName();
	pDlg->use.BeginUse();
	pDlg->sta2.SetWindowText(Name); pDlg->sta5.SetWindowText(L"“原始目录”加载文件进行中");
	pDlg->use.EndUse();
	pDlg->FileCount1 = 0;
	pDlg->tree1.DeleteAllItems();
	CFile F(PathName, CFile::modeRead);
	CArchive ar(&F, CArchive::load);
	HTREEITEM h[256];
	CString item_str; UINT cj, count;//记录项文本,项层级,项总数
	ar >> count;
	for (UINT i = 0; i < count; i++)
	{
		ar >> item_str >> cj;
		if (cj == 0)
		{
			h[cj] = pDlg->tree1.InsertItem(item_str, 0, 0); pDlg->FileCount1++;
		}
		else
		{
			h[cj] = pDlg->tree1.InsertItem(item_str, h[cj - 1], TVI_LAST); pDlg->FileCount1++;
		}
		pDlg->use.BeginUse();
		pDlg->SetDlgItemInt(IDC_EDIT1, pDlg->FileCount1);
		pDlg->use.EndUse();
		DWORD dw = WaitForSingleObject(pDlg->hExit1, 0);
		if (dw == WAIT_OBJECT_0)
		{
			pDlg->SetStateText(L"已终止任务");
			return (UINT)(pDlg->hLoadFileThread1 = NULL);
		}
	}
	HTREEITEM hRoot = pDlg->tree1.GetRootItem();//获取第一个根项
	pDlg->tree1.Expand(hRoot, TVE_EXPAND);//展开根项的子项
	pDlg->SetStateText(L"加载文件完成");
	return (UINT)(pDlg->hLoadFileThread1 = NULL);
}

void C目录比对Dlg::OnTree132771()//tree1“加载文件”菜单项,单击响应函数
{
	if (hLoadFileThread1 != NULL)return;
	hLoadFileThread1=AfxBeginThread(LoadFileThread1, this, 0, 0, 0)->m_hThread;
}

void C目录比对Dlg::OnTree132774()//tree1“保存到文件”菜单项,单击响应函数
{
	Save(&tree1);
}

void C目录比对Dlg::OnTree132775()//tree1“折叠所有项”菜单项,单击响应函数
{
	Expand(&tree1);
}

void C目录比对Dlg::OnTree132780()//tree1“终止任务”菜单项,单击响应函数
{
	SetEvent(hExit1);
}

BOOL C目录比对Dlg::SeekFor2(CString pstr, HTREEITEM h)
{
	CFileFind ff;
	BOOL bWorking = ff.FindFile(pstr, 0);
	while (bWorking)
	{
		DWORD dw = WaitForSingleObject(hExit2, 0);
		if (dw == WAIT_OBJECT_0)
		{
			return TRUE;
		}
		bWorking = ff.FindNextFile();
		if (ff.IsDots())continue;
		CString str1, str2;
		str1 = ff.GetFileName(); str2 = ff.GetFilePath();
		HTREEITEM hItem = tree2.InsertItem(str1, h);
		Count2++;
		use.BeginUse();
		SetDlgItemInt(IDC_EDIT2, Count2);
		use.EndUse();
		if (ff.IsDirectory())//如果是文件夹
			SeekFor2(str2 + L"\\*.*", hItem);
	}
	return FALSE;
}

UINT LoadDiskThread2(LPVOID pParam)//树控件2加载磁盘目录线程
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)pParam;
	BROWSEINFO bi;
	char buffer[MAX_PATH];
	ZeroMemory(buffer, MAX_PATH);
	bi.hwndOwner = pDlg->GetSafeHwnd();
	bi.pidlRoot = NULL;
	bi.pszDisplayName = LPWSTR(buffer);
	bi.lpszTitle = _T("选择一个文件夹");
	bi.ulFlags = BIF_EDITBOX;
	bi.lpfn = NULL;
	bi.lParam = 0;
	bi.iImage = 0;
	LPITEMIDLIST pList = NULL;
	if ((pList = SHBrowseForFolder(&bi)) == NULL)return (UINT)(pDlg->hLoadDiskThread2 = NULL);
	char path[MAX_PATH];
	ZeroMemory(path, MAX_PATH);
	SHGetPathFromIDList(pList, LPWSTR(path));
	CString SeekPath = LPCTSTR(path);
	CString R = SeekPath.Right(1);
	if (R == L"\\")SeekPath += L"*.*";
	else SeekPath += L"\\*.*";
	CString SeekText = SeekPath;
	int find = SeekText.Find(L"\\*.*");
	if (find != -1)
		SeekText.Delete(find, 4);
	pDlg->tree2.DeleteAllItems();
	ResetEvent(pDlg->hExit2);
	pDlg->use.BeginUse();
	pDlg->sta3.SetWindowText(SeekText);
	pDlg->sta5.SetWindowText(L"“当前目录”加载磁盘目录进行中");
	pDlg->use.EndUse();
	pDlg->Count2 = 0;
	HTREEITEM hITEM = pDlg->tree2.InsertItem(SeekText, NULL);
	pDlg->Count2++;
	pDlg->SeekFor2(SeekPath, hITEM);
	HTREEITEM hRoot = pDlg->tree2.GetRootItem();
	pDlg->tree2.Expand(hRoot, TVE_EXPAND);
	pDlg->SetStateText(L"加载磁盘目录完成");
	return (UINT)(pDlg->hLoadDiskThread2 = NULL);
}

void C目录比对Dlg::OnTree232772()//tree2"加载磁盘目录"菜单项,单击响应函数
{
	if (hLoadDiskThread2 != NULL)return;//如果线程正在运行,不再创建新的线程
	hLoadDiskThread2 = AfxBeginThread(LoadDiskThread2, this, 0, 0, 0)->m_hThread;
}

UINT LoadFileThread2(LPVOID pParam)//树控件2加载文件线程
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)pParam;
	CFileDialog FD(TRUE);
	FD.m_ofn.lpstrInitialDir = (CString)pDlg->Path + L"\\比对数据";//指定初始目录
	FD.m_ofn.lpstrFilter = _T("DAT文件\0*.dat\0\0");//指定过滤器
	if (FD.DoModal() != IDOK)return (UINT)(pDlg->hLoadFileThread2 = NULL);
	ResetEvent(pDlg->hExit2);
	CString PathName = FD.GetPathName();
	CString Name = FD.GetFileName();
	pDlg->use.BeginUse();
	pDlg->sta3.SetWindowText(Name); pDlg->sta5.SetWindowText(L"“当前目录”加载文件进行中");
	pDlg->use.EndUse();
	pDlg->FileCount2 = 0;
	pDlg->tree2.DeleteAllItems();
	CFile F(PathName, CFile::modeRead);
	CArchive ar(&F, CArchive::load);
	HTREEITEM h[256];
	CString item_str; UINT cj, count;//记录项文本,项层级,项总数
	ar >> count;
	for (UINT i = 0; i < count; i++)
	{
		ar >> item_str >> cj;
		if (cj == 0)
		{
			h[cj] = pDlg->tree2.InsertItem(item_str, 0, 0); pDlg->FileCount2++;
		}
		else
		{
			h[cj] = pDlg->tree2.InsertItem(item_str, h[cj - 1], TVI_LAST); pDlg->FileCount2++;
		}
		pDlg->use.BeginUse();
		pDlg->SetDlgItemInt(IDC_EDIT2, pDlg->FileCount2);
		pDlg->use.EndUse();
		DWORD dw = WaitForSingleObject(pDlg->hExit2, 0);
		if (dw == WAIT_OBJECT_0)
		{
			pDlg->SetStateText(L"已终止任务");
			return (UINT)(pDlg->hLoadFileThread2 = NULL);
		}
	}
	HTREEITEM hRoot = pDlg->tree2.GetRootItem();//获取第一个根项
	pDlg->tree2.Expand(hRoot, TVE_EXPAND);//展开根项的子项
	pDlg->SetStateText(L"加载文件完成");
	return (UINT)(pDlg->hLoadFileThread2 = NULL);
}

void C目录比对Dlg::OnTree232776()//tree2“加载文件”菜单项,单击响应函数
{
	if (hLoadFileThread2 != NULL)return;
	hLoadFileThread2 = AfxBeginThread(LoadFileThread2, this, 0, 0, 0)->m_hThread;
}

void C目录比对Dlg::OnTree232777()//tree2“保存到文件”菜单项,单击响应函数
{
	Save(&tree2);
}

void C目录比对Dlg::OnTree232778()//tree2“折叠所有项”菜单项,单击响应函数
{
	Expand(&tree2);
}

void C目录比对Dlg::OnTree232779()//tree2“终止任务”菜单项,单击响应函数
{
	SetEvent(hExit2);
}

void C目录比对Dlg::Save(CMyTree* pTree)
{
	HTREEITEM h_item = pTree->GetRootItem();//获取第一个根项
	CString item_str; UINT cj = 0; //记录项文本,项层级
	if (h_item == NULL)return;   //如果树控件不包含任何项返回
	else
	{
		item_str = pTree->GetItemText(h_item); //获取项文本
	}
	CFileDialog FD(FALSE, L"dat", NULL, OFN_FILEMUSTEXIST, NULL);
	FD.m_ofn.lpstrInitialDir = (CString)Path + L"\\比对数据";//指定初始目录
	FD.m_ofn.lpstrFilter = _T("DAT文件\0*.dat\0\0");//指定过滤器
	if (FD.DoModal() != IDOK)return;
	if (*pTree == tree1)
	{
		sta5.SetWindowText(L"“原始目录”保存到文件进行中");
	}
	else
	{
		sta5.SetWindowText(L"“当前目录”保存到文件进行中");
	}
	CString PathName = FD.GetPathName();
	CFile F(PathName, CFile::modeCreate | CFile::modeWrite);
	CArchive ar(&F, CArchive::store);
	UINT count = pTree->GetCount();
	ar << count;
	ar << item_str << cj;//写入项文本,项层级
jump1:
	if (pTree->ItemHasChildren(h_item))    //如果有子项
	{
		h_item = pTree->GetChildItem(h_item);//获取子项
		cj += 1;//层级加1
		item_str = pTree->GetItemText(h_item);//获取项文本
		ar << item_str << cj;//写入项文本,项层级
		goto jump1;
	}
jump2:
	if (pTree->GetNextSiblingItem(h_item) == NULL)    //如果没有下一个兄弟项
	{
		if (cj == 0)goto end;//如果层级到达0,且没有下一个兄弟项,跳出循环
		h_item = pTree->GetParentItem(h_item);//获取父项
		cj -= 1;//层级减1
		goto jump2;
	}
	else    //如果有下一个兄弟项
	{
		h_item = pTree->GetNextSiblingItem(h_item);//获取下一个兄弟项
		item_str = pTree->GetItemText(h_item);//获取项文本
		ar << item_str << cj;//写入项文本,项层级
		goto jump1;
	}
end:
	SetStateText(L"保存到文件完成");
}

void C目录比对Dlg::Expand(CMyTree* pTree)//折叠树控件所有项
{
	HTREEITEM h_item = pTree->GetRootItem();//获取第一个根项
	if (h_item == NULL)return;   //如果树控件不包含任何项返回
	int cj = 0;
jump1:
	if (pTree->ItemHasChildren(h_item))    //如果有子项
	{
		pTree->Expand(h_item, TVE_COLLAPSE);
		h_item = pTree->GetChildItem(h_item);//获取子项
		cj += 1;//层级加1
		goto jump1;
	}
jump2:
	if (pTree->GetNextSiblingItem(h_item) == NULL)    //如果没有下一个兄弟项
	{
		if (cj == 0)goto end;//如果层级到达0,且没有下一个兄弟项,跳出循环
		h_item = pTree->GetParentItem(h_item);//获取父项
		cj -= 1;//层级减1
		goto jump2;
	}
	else    //如果有下一个兄弟项
	{
		h_item = pTree->GetNextSiblingItem(h_item);//获取下一个兄弟项
		goto jump1;
	}
end:
	SetStateText(L"折叠所有项完成");
}

UINT CheckThread(LPVOID pParam)//比对线程
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)pParam;
	pDlg->COUNT = pDlg->tree1.GetCount();//获取树控件1项总数
	pDlg->CUR = 0;
	ResetEvent(pDlg->hStop);
	pDlg->sta5.SetWindowText(L"比对进行中");
	pDlg->MyCheck(NULL, NULL);
	pDlg->SetStateText(L"比对完成");
	pDlg->MessageBox(L"比对完成");
	return (UINT)(pDlg->hCheckThread = NULL);
}

void C目录比对Dlg::OnBnClickedButton1()//开始比对
{
	if (hCheckThread  || hLoadDiskThread1 || hLoadDiskThread2 || hLoadFileThread1 || hLoadFileThread2)return;
	hCheckThread = AfxBeginThread(CheckThread, this, 0, 0, 0)->m_hThread;
}

void C目录比对Dlg::OnBnClickedButton2()//停止比对
{
	SetEvent(hStop);
}

struct INFO {
	HTREEITEM hItem;//项句柄
	WCHAR name[MAX_PATH];//项文本
	int  mask;//标记
	BOOL Child = FALSE;//TRUE有子项,FALSE没有子项
};

struct T {
	INFO* pA = NULL;
	INFO* pB = NULL;
};

void C目录比对Dlg::MyCheck(HTREEITEM hA, HTREEITEM hB)
{
	DWORD dw = WaitForSingleObject(hStop, 0);
	if (dw == WAIT_OBJECT_0)return;

	CObArray OA, OB, OT;
	int CountA = GetChildInfo(OA, &tree1, hA);//获取直接子项的信息
	int CountB = GetChildInfo(OB, &tree2, hB);//获取直接子项的信息

	CUR += CountA;
	pro.SetPos(CUR * 100 / COUNT);//进度条设置当前位置

	for (int i = 0; i < CountA; i++)//标记树控件1中的相同项
	{
		INFO* pInfoA = (INFO*)OA.GetAt(i);
		for (int j = 0; j < CountB; j++)
		{
			INFO* pInfoB = (INFO*)OB.GetAt(j);
			if (wcscmp(pInfoA->name, pInfoB->name)==0)//如果项文本相同
			{
				pInfoA->mask = 0;//相同项标记0
			}
		}
	}

	for (int i = 0; i < CountB; i++)//标记树控件2中的相同项
	{
		INFO* pInfoB = (INFO*)OB.GetAt(i);
		for (int j = 0; j < CountA; j++)
		{
			INFO* pInfoA = (INFO*)OA.GetAt(j);
			if (wcscmp(pInfoA->name, pInfoB->name) == 0)//如果项文本相同
			{
				pInfoB->mask = 0;//相同项标记0
				T* pT = new T();
				pT->pA = pInfoA;
				pT->pB = pInfoB;
				OT.Add((CObject*)pT);//将相同项加入OT数组
			}
		}
	}

	for (int i = 0; i < CountA; i++)//将树控件1中标记-1的项,添加状态图像“-”
	{
		INFO* pInfoA = (INFO*)OA.GetAt(i);
		if (pInfoA->mask == -1)
		{
			SetMask(&tree1, pInfoA->hItem, 2);
		}
	}

	for (int i = 0; i < CountB; i++)//将树控件2中标记1的项,添加状态图像“+”
	{
		INFO* pInfoB = (INFO*)OB.GetAt(i);
		if (pInfoB->mask == 1)
		{
			SetMask(&tree2, pInfoB->hItem, 1);
		}
	}

	int TCount = OT.GetCount();
	for (int i = 0; i < TCount; i++)//将相同项进行迭代
	{
		T* pT = (T*)OT.GetAt(i);
		MyCheck(pT->pA->hItem, pT->pB->hItem);
	}

	for (int i = 0; i < CountA; i++)//删除OA数组中所有元素
	{
		INFO* pInfo = (INFO*)OA.GetAt(i); delete pInfo;
	}
	for (int i = 0; i < CountB; i++)//删除OB数组中所有元素
	{
		INFO* pInfo = (INFO*)OB.GetAt(i); delete pInfo;
	}
	for (int i = 0; i < OT.GetCount(); i++)//删除OT数组中所有元素
	{
		T* pT = (T*)OT.GetAt(i); delete pT;
	}
}


int C目录比对Dlg::GetChildInfo(CObArray& X, CMyTree* pTree, HTREEITEM hItem)//获取直接子项的信息,不包括子项的子项
{
	int Count = 0;
	HTREEITEM hChild = pTree->GetChildItem(hItem);//获取第1个子项
	if(hChild==NULL)return 0;
	CString text = pTree->GetItemText(hChild);
	Count++;

	INFO* pInfo = new INFO();
	pInfo->hItem = hChild;
	wmemset(pInfo->name, 0, MAX_PATH);
	CopyMemory(pInfo->name, text, (text.GetLength() + 1) * 2);
	if (*pTree == tree1)pInfo->mask = -1;
	if (*pTree == tree2)pInfo->mask = 1;
	if (pTree->ItemHasChildren(hChild))pInfo->Child=TRUE;//如果该子项也有子项,Child标记TRUE
	else pInfo->Child = FALSE;//没有子项,标记FALSE
	X.Add((CObject*)pInfo);

	HTREEITEM hNext = pTree->GetNextSiblingItem(hChild);//获取下一个兄弟项
	while (hNext != NULL)
	{
		Count++;
		text = pTree->GetItemText(hNext);

		INFO* pInfo = new INFO();
		pInfo->hItem = hNext;
		wmemset(pInfo->name, 0, MAX_PATH);
		CopyMemory(pInfo->name, text, (text.GetLength() + 1) * 2);
		if (*pTree == tree1)pInfo->mask = -1;
		if (*pTree == tree2)pInfo->mask = 1;
		if (pTree->ItemHasChildren(hNext))pInfo->Child = TRUE;//如果该子项也有子项,Child标记TRUE
		else pInfo->Child = FALSE;//没有子项,标记FALSE
		X.Add((CObject*)pInfo);

		hNext = pTree->GetNextSiblingItem(hNext);
	}
	return Count;
}


void C目录比对Dlg::SetMask(CMyTree* pTree, HTREEITEM hItem, int index)//给指定项添加状态图像“+”或“-”
{
	TVITEM tvItem;
	tvItem.mask = TVIF_HANDLE | TVIF_STATE;
	tvItem.hItem = hItem;//要设置状态图像的项的句柄
	tvItem.stateMask = TVIS_STATEIMAGEMASK;//此掩码指定项使用状态图像
	tvItem.state = INDEXTOSTATEIMAGEMASK(index);
	pTree->SetItem(&tvItem);
	if (index == 1)//如果状态图像是“+”
		SetPar(pTree, hItem, 3);
	else//如果状态图像是“-”
		SetPar(pTree, hItem, 4);
}

void C目录比对Dlg::SetPar(CMyTree* pTree, HTREEITEM hPar, int index)//给所有父项添加红色或黑色状态图像
{
	hPar = pTree->GetParentItem(hPar);
	while (hPar != NULL)
	{
		TVITEM tvItem;
		tvItem.mask = TVIF_HANDLE | TVIF_STATE;
		tvItem.hItem = hPar;//要设置状态图像的项的句柄
		tvItem.stateMask = TVIS_STATEIMAGEMASK;//此掩码指定项使用状态图像
		tvItem.state = INDEXTOSTATEIMAGEMASK(index);
		pTree->SetItem(&tvItem);
		hPar = pTree->GetParentItem(hPar);
	}
}

UINT StateTextThread(LPVOID pParam)
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)pParam;
	pDlg->use.BeginUse();
	pDlg->sta5.SetWindowText(pDlg->StateText);
	pDlg->use.EndUse();
	Sleep(5000);
	pDlg->use.BeginUse();
	pDlg->sta5.SetWindowText(NULL);
	pDlg->use.EndUse();
	return 1;
}

void C目录比对Dlg::SetStateText(CString text)//显示工作状态文本
{
	StateText = text;
	AfxBeginThread(StateTextThread, this, 0, 0, 0);
}


void C目录比对Dlg::OnTree132781()//“删除的文件信息”菜单项,单击响应函数
{
	XuHao = 0;
	CString Info;
	UINT cj, cj0;
	HTREEITEM hSel = tree1.GetSelectedItem();
	if (hSel != NULL)
	{
		if (GetStateImage(&tree1, hSel) == 2)//如果具有“-”图像
		{
			Info += GetString(hSel, &tree1);
		}
		HTREEITEM h_item = tree1.GetChildItem(hSel);
		if (h_item == NULL)goto End;
		if (GetStateImage(&tree1, h_item) == 2)//如果具有“-”图像
		{
			Info += GetString(h_item, &tree1);
		}
		cj = cj0 = GetCJ(h_item, &tree1);//获取h_item项的层级

	jump1:
		if (tree1.ItemHasChildren(h_item))//如果有子项
		{
			h_item = tree1.GetChildItem(h_item);//获取子项
			cj += 1;
			if (GetStateImage(&tree1, h_item) == 2)//如果具有“ - ”图像
			{
				Info += GetString(h_item, &tree1);
			}
			goto jump1;
		}
	jump2:
		if (tree1.GetNextItem(h_item, TVGN_NEXT) == NULL)//如果没有下一个兄弟项
		{
			if (cj == cj0)goto End;//如果层级到达cj0,且没有下一个兄弟项,跳出循环
			h_item = tree1.GetParentItem(h_item);//获取父项
			cj -= 1;
			goto jump2;
		}
		else//如果有下一个兄弟项
		{
			h_item = tree1.GetNextItem(h_item, TVGN_NEXT);//获取下一个兄弟项
			if (GetStateImage(&tree1, h_item) == 2)//如果具有“-”图像
			{
				Info += GetString(h_item, &tree1);
			}
			goto jump1;
		}
	}
End:
	int len = Info.GetLength();
	Info.Delete(len - 2, 2);//删除最后的“\r\n”
	dlg2.Info = Info;
	dlg2.DestroyWindow();
	dlg2.Create(IDD_DIALOG2);
}


void C目录比对Dlg::OnTree232782()//“增加的文件信息”菜单项,单击响应函数
{
	XuHao = 0;
	CString Info;
	UINT cj, cj0;
	HTREEITEM hSel = tree2.GetSelectedItem();
	if (hSel != NULL)
	{
		if (GetStateImage(&tree2, hSel) == 1)//如果具有“+”图像
		{
			Info += GetString(hSel, &tree2);
		}
		HTREEITEM h_item = tree2.GetChildItem(hSel);
		if (h_item == NULL)goto End;
		if (GetStateImage(&tree2, h_item) == 1)//如果具有“+”图像
		{
			Info += GetString(h_item, &tree2);
		}
		cj = cj0 = GetCJ(h_item, &tree2);//获取h_item项的层级

	jump1:
		if (tree2.ItemHasChildren(h_item))//如果有子项
		{
			h_item = tree2.GetChildItem(h_item);//获取子项
			cj += 1;
			if (GetStateImage(&tree2, h_item) == 1)//如果具有“+”图像
			{
				Info += GetString(h_item, &tree2);
			}
			goto jump1;
		}
	jump2:
		if (tree2.GetNextItem(h_item, TVGN_NEXT) == NULL)//如果没有下一个兄弟项
		{
			if (cj == cj0)goto End;//如果层级到达cj0,且没有下一个兄弟项,跳出循环
			h_item = tree2.GetParentItem(h_item);//获取父项
			cj -= 1;
			goto jump2;
		}
		else//如果有下一个兄弟项
		{
			h_item = tree2.GetNextItem(h_item, TVGN_NEXT);//获取下一个兄弟项
			if (GetStateImage(&tree2, h_item) == 1)//如果具有“+”图像
			{
				Info += GetString(h_item, &tree2);
			}
			goto jump1;
		}
	}
End:
	int len = Info.GetLength();
	Info.Delete(len - 2, 2);//删除最后的“\r\n”
	dlg1.Info = Info;
	dlg1.DestroyWindow();
	dlg1.Create(IDD_DIALOG1);
}


int C目录比对Dlg::GetStateImage(CMyTree* pTree, HTREEITEM hItem)//获取状态图像的索引
{
	TVITEM tvItem;
	tvItem.mask = TVIF_HANDLE | TVIF_STATE;
	tvItem.hItem = hItem;
	pTree->GetItem(&tvItem);
	int index = (tvItem.state & TVIS_STATEIMAGEMASK) >> 12;
	return index;
}


UINT C目录比对Dlg::GetCJ(HTREEITEM hItem, CMyTree* pTree)//获取指定项的层次
{
	UINT cj = 0;
	HTREEITEM hPar = pTree->GetParentItem(hItem);
	while (hPar != NULL)
	{
		cj++;
		hPar = pTree->GetParentItem(hPar);
	}
	return cj;
}


CString C目录比对Dlg::GetString(HTREEITEM hItem, CMyTree* pTree)//获取项描述字符串
{
	CString str;
	CString item = pTree->GetItemText(hItem);
	str = item + L"\r\n";
	HTREEITEM hPar = pTree->GetParentItem(hItem);
	while (hPar != NULL)
	{
		item = pTree->GetItemText(hPar);
		str = item + L"\\" + str;
		hPar = pTree->GetParentItem(hPar);
	}
	XuHao++;
	CString xh;
	xh.Format(L"%u\t", XuHao);
	str = xh + str;
	return str;
}

Dlg1.h

#pragma once
#include "afxcmn.h"
#include "MyRichEdit.h"

// CDlg1 对话框

class CDlg1 : public CDialogEx
{
	DECLARE_DYNAMIC(CDlg1)

public:
	CDlg1(CWnd* pParent = NULL);   // 标准构造函数
	virtual ~CDlg1();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_DIALOG1 };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedOk();
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	virtual BOOL OnInitDialog();
	BOOL B = TRUE;
	CMyRichEdit richedit;
	CString Info;
	afx_msg void OnPaint();
	afx_msg void OnRichedit32783();//全选
	afx_msg void OnRichedit32784();//复制
	afx_msg void OnRichedit32785();//粘贴
	afx_msg void OnRichedit32786();//剪切
	afx_msg void OnRichedit32787();//撤销
	afx_msg void OnRichedit32788();//重做
	afx_msg void OnRichedit32789();//保存到文件
	afx_msg void OnRichedit32790();//打开文件
	void SetFormat();
	afx_msg void OnSize(UINT nType, int cx, int cy);
};

Dlg1.cpp

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

#include "stdafx.h"
#include "目录比对.h"
#include "Dlg1.h"
#include "afxdialogex.h"
#include "目录比对Dlg.h"

// CDlg1 对话框

IMPLEMENT_DYNAMIC(CDlg1, CDialogEx)

CDlg1::CDlg1(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_DIALOG1, pParent)
{

}

CDlg1::~CDlg1()
{
}

void CDlg1::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_RICHEDIT21, richedit);
}


BEGIN_MESSAGE_MAP(CDlg1, CDialogEx)
	ON_BN_CLICKED(IDOK, &CDlg1::OnBnClickedOk)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_COMMAND(ID_RICHEDIT_32783, &CDlg1::OnRichedit32783)
	ON_COMMAND(ID_RICHEDIT_32784, &CDlg1::OnRichedit32784)
	ON_COMMAND(ID_RICHEDIT_32785, &CDlg1::OnRichedit32785)
	ON_COMMAND(ID_RICHEDIT_32786, &CDlg1::OnRichedit32786)
	ON_COMMAND(ID_RICHEDIT_32787, &CDlg1::OnRichedit32787)
	ON_COMMAND(ID_RICHEDIT_32788, &CDlg1::OnRichedit32788)
	ON_COMMAND(ID_RICHEDIT_32789, &CDlg1::OnRichedit32789)
	ON_COMMAND(ID_RICHEDIT_32790, &CDlg1::OnRichedit32790)
	ON_WM_SIZE()
END_MESSAGE_MAP()

void CDlg1::OnBnClickedOk()
{
}


BOOL CDlg1::OnEraseBkgnd(CDC* pDC)
{
	CRect rect;
	GetClientRect(rect);
	pDC->FillSolidRect(rect, RGB(50, 50, 50));
	return TRUE;
//	return CDialogEx::OnEraseBkgnd(pDC);
}


BOOL CDlg1::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	CRect rectC(0, 0, 780, 600);//设置客户区大小,宽780像素,高600像素
	DWORD style = GetExStyle();//获取对话框扩展样式
	if (style & WS_EX_CLIENTEDGE)//如果对话框包含WS_EX_CLIENTEDGE样式,CalcWindowRect函数参数2使用CWnd::adjustOutside
	{
		CalcWindowRect(rectC, CWnd::adjustOutside);//计算带边框的对话框窗口大小。CalcWindowRect函数为CWnd类函数
	}
	else//如果对话框不包含WS_EX_CLIENTEDGE样式,CalcWindowRect函数参数2使用CWnd::adjustBorder
	{
		CalcWindowRect(rectC, CWnd::adjustBorder);//计算带边框的对话框窗口大小
	}
	MoveWindow(&rectC);//设置对话框的大小
	CenterWindow();//居中对话框
	richedit.SetBackgroundColor(FALSE, RGB(255, 193, 132));
	CRect rect;
	GetClientRect(rect);
	rect.DeflateRect(5, 5, 5, 5);
	richedit.MoveWindow(rect);
	richedit.SetWindowText(Info);
	SetFormat();
	B = TRUE;
	return TRUE; 
}


void CDlg1::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	if (B)
	{
		B = FALSE;
		richedit.SetSel(0, 0);
	}
}


void CDlg1::OnRichedit32783()//全选
{
	richedit.SetSel(0, -1);
}


void CDlg1::OnRichedit32784()//复制
{
	richedit.Copy();
}


void CDlg1::OnRichedit32785()//粘贴
{
	richedit.Paste();
}


void CDlg1::OnRichedit32786()//剪切
{
	richedit.Cut();
}


void CDlg1::OnRichedit32787()//撤销
{
	richedit.Undo();
}


void CDlg1::OnRichedit32788()//重做
{
	richedit.Redo();
}


void CDlg1::OnRichedit32789()//保存到文件
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)theApp.m_pMainWnd;
	CStringA Text = (CStringA)richedit.GetSelText();
	CFileDialog FD(FALSE, L"txt", NULL, OFN_FILEMUSTEXIST, NULL);
	FD.m_ofn.lpstrInitialDir = (CString)pDlg->Path + L"\\比对数据";//指定初始目录
	FD.m_ofn.lpstrFilter = _T("TXT文件\0*.txt\0\0");//指定过滤器
	if (FD.DoModal() != IDOK)return;
	CString PathName = FD.GetPathName();
	CFile F(PathName, CFile::modeCreate | CFile::modeWrite);
	F.Write(Text, Text.GetLength() + 1);
	F.Close();
}


void CDlg1::OnRichedit32790()//打开文件
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)theApp.m_pMainWnd;
	CFileDialog FD(TRUE);
	FD.m_ofn.lpstrInitialDir = (CString)pDlg->Path + L"\\比对数据";//指定初始目录
	FD.m_ofn.lpstrFilter = _T("TXT文件\0*.txt\0\0");//指定过滤器
	if (FD.DoModal() != IDOK)return;
	CString PathName = FD.GetPathName();
	CStringA Text;
	CFile F(PathName, CFile::modeRead);
	UINT len = (UINT)F.GetLength();
	F.Read(Text.GetBufferSetLength(len), len);
	F.Close();
	richedit.SetWindowText((CString)Text);
	Text.ReleaseBuffer();
	SetFormat();
}


void CDlg1::SetFormat()//为多格式编辑控件文本指定字体格式
{
	richedit.SetSel(0, -1);
	CHARFORMAT2 cf;
	cf.cbSize = sizeof(CHARFORMAT2);
	cf.dwMask = CFM_FACE | CFM_SIZE | CFM_COLOR | CFM_WEIGHT | CFM_CHARSET;
	wcsncpy_s(cf.szFaceName, LF_FACESIZE, _T("微软雅黑"), LF_FACESIZE);//设置字体名称
	cf.yHeight = 10 * 20;//设置字体大小为12点
	cf.crTextColor = RGB(123, 36, 6);//设置字体颜色
	cf.wWeight = 400;//400为正常字体
	cf.dwEffects = 0;//字符效果设置为0
	cf.bCharSet = GB2312_CHARSET;//设置中文字符集
	richedit.SetWordCharFormat(cf);//设置当前字符格式
	wcsncpy_s(cf.szFaceName, LF_FACESIZE, _T("Cambria"), LF_FACESIZE);//设置字体名称
	cf.bCharSet = ANSI_CHARSET;
	richedit.SetWordCharFormat(cf);//设置当前字符格式
	richedit.SetSel(0, 0);
}


void CDlg1::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);
	CRect rect;
	GetClientRect(rect);
	rect.DeflateRect(5, 5, 5, 5);
	if (richedit.GetSafeHwnd())
		richedit.MoveWindow(rect);
}

Dlg2.h

#pragma once
#include "afxcmn.h"
#include "MyRichEdit.h"

// CDlg2 对话框

class CDlg2 : public CDialogEx
{
	DECLARE_DYNAMIC(CDlg2)

public:
	CDlg2(CWnd* pParent = NULL);   // 标准构造函数
	virtual ~CDlg2();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_DIALOG2 };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	BOOL B = TRUE;
	CString Info;
	virtual BOOL OnInitDialog();
	CMyRichEdit richedit;
	afx_msg void OnPaint();
	afx_msg void OnRichedit32783();//全选
	afx_msg void OnRichedit32784();//复制
	afx_msg void OnRichedit32785();//粘贴
	afx_msg void OnRichedit32786();//剪切
	afx_msg void OnRichedit32787();//撤销
	afx_msg void OnRichedit32788();//重做
	afx_msg void OnRichedit32789();//保存到文件
	afx_msg void OnRichedit32790();//打开文件
	void SetFormat();
	afx_msg void OnSize(UINT nType, int cx, int cy);
};

Dlg2.cpp

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

#include "stdafx.h"
#include "目录比对.h"
#include "Dlg2.h"
#include "afxdialogex.h"
#include "目录比对Dlg.h"



IMPLEMENT_DYNAMIC(CDlg2, CDialogEx)

CDlg2::CDlg2(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_DIALOG2, pParent)
{

}

CDlg2::~CDlg2()
{
}

void CDlg2::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_RICHEDIT22, richedit);
}


BEGIN_MESSAGE_MAP(CDlg2, CDialogEx)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_COMMAND(ID_RICHEDIT_32783, &CDlg2::OnRichedit32783)
	ON_COMMAND(ID_RICHEDIT_32784, &CDlg2::OnRichedit32784)
	ON_COMMAND(ID_RICHEDIT_32785, &CDlg2::OnRichedit32785)
	ON_COMMAND(ID_RICHEDIT_32786, &CDlg2::OnRichedit32786)
	ON_COMMAND(ID_RICHEDIT_32787, &CDlg2::OnRichedit32787)
	ON_COMMAND(ID_RICHEDIT_32788, &CDlg2::OnRichedit32788)
	ON_COMMAND(ID_RICHEDIT_32789, &CDlg2::OnRichedit32789)
	ON_COMMAND(ID_RICHEDIT_32790, &CDlg2::OnRichedit32790)
	ON_WM_SIZE()
END_MESSAGE_MAP()

BOOL CDlg2::OnEraseBkgnd(CDC* pDC)
{
	CRect rect;
	GetClientRect(rect);
	pDC->FillSolidRect(rect, RGB(50, 50, 50));
	return TRUE;
	//	return CDialogEx::OnEraseBkgnd(pDC);
}


BOOL CDlg2::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	CRect rectC(0, 0, 780, 600);//设置客户区大小,宽780像素,高600像素
	DWORD style = GetExStyle();//获取对话框扩展样式
	if (style & WS_EX_CLIENTEDGE)//如果对话框包含WS_EX_CLIENTEDGE样式,CalcWindowRect函数参数2使用CWnd::adjustOutside
	{
		CalcWindowRect(rectC, CWnd::adjustOutside);//计算带边框的对话框窗口大小。CalcWindowRect函数为CWnd类函数
	}
	else//如果对话框不包含WS_EX_CLIENTEDGE样式,CalcWindowRect函数参数2使用CWnd::adjustBorder
	{
		CalcWindowRect(rectC, CWnd::adjustBorder);//计算带边框的对话框窗口大小
	}
	MoveWindow(&rectC);//设置对话框的大小
	CenterWindow();//居中对话框
	richedit.SetBackgroundColor(FALSE, RGB(255, 193, 132));
	CRect rect;
	GetClientRect(rect);
	rect.DeflateRect(5, 5, 5, 5);
	richedit.MoveWindow(rect);
	richedit.SetWindowText(Info);
	SetFormat();
	B = TRUE;
	return TRUE; 
}


void CDlg2::OnPaint()
{
	CPaintDC dc(this); 
	if (B)
	{
		B = FALSE;
		richedit.SetSel(0, 0);
	}
}


void CDlg2::OnRichedit32783()//全选
{
	richedit.SetSel(0, -1);
}


void CDlg2::OnRichedit32784()//复制
{
	richedit.Copy();
}


void CDlg2::OnRichedit32785()//粘贴
{
	richedit.Paste();
}


void CDlg2::OnRichedit32786()//剪切
{
	richedit.Cut();
}


void CDlg2::OnRichedit32787()//撤销
{
	richedit.Undo();
}


void CDlg2::OnRichedit32788()//重做
{
	richedit.Redo();
}


void CDlg2::OnRichedit32789()//保存到文件
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)theApp.m_pMainWnd;
	CStringA Text = (CStringA)richedit.GetSelText();
	CFileDialog FD(FALSE, L"txt", NULL, OFN_FILEMUSTEXIST, NULL);
	FD.m_ofn.lpstrInitialDir = (CString)pDlg->Path + L"\\比对数据";//指定初始目录
	FD.m_ofn.lpstrFilter = _T("TXT文件\0*.txt\0\0");//指定过滤器
	if (FD.DoModal() != IDOK)return;
	CString PathName = FD.GetPathName();
	CFile F(PathName, CFile::modeCreate | CFile::modeWrite);
	F.Write(Text, Text.GetLength() + 1);
	F.Close();
}


void CDlg2::OnRichedit32790()//打开文件
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)theApp.m_pMainWnd;
	CFileDialog FD(TRUE);
	FD.m_ofn.lpstrInitialDir = (CString)pDlg->Path + L"\\比对数据";//指定初始目录
	FD.m_ofn.lpstrFilter = _T("TXT文件\0*.txt\0\0");//指定过滤器
	if (FD.DoModal() != IDOK)return;
	CString PathName = FD.GetPathName();
	CStringA Text;
	CFile F(PathName, CFile::modeRead);
	UINT len = (UINT)F.GetLength();
	F.Read(Text.GetBufferSetLength(len), len);
	F.Close();
	richedit.SetWindowText((CString)Text);
	Text.ReleaseBuffer();
	SetFormat();
}


void CDlg2::SetFormat()//为多格式编辑控件文本指定字体格式
{
	richedit.SetSel(0, -1);
	CHARFORMAT2 cf;
	cf.cbSize = sizeof(CHARFORMAT2);
	cf.dwMask = CFM_FACE | CFM_SIZE | CFM_COLOR | CFM_WEIGHT | CFM_CHARSET;
	wcsncpy_s(cf.szFaceName, LF_FACESIZE, _T("微软雅黑"), LF_FACESIZE);//设置字体名称
	cf.yHeight = 10 * 20;//设置字体大小为12点
	cf.crTextColor = RGB(123, 36, 6);//设置字体颜色
	cf.wWeight = 400;//400为正常字体
	cf.dwEffects = 0;//字符效果设置为0
	cf.bCharSet = GB2312_CHARSET;//设置中文字符集
	richedit.SetWordCharFormat(cf);//设置当前字符格式
	wcsncpy_s(cf.szFaceName, LF_FACESIZE, _T("Cambria"), LF_FACESIZE);//设置字体名称
	cf.bCharSet = ANSI_CHARSET;
	richedit.SetWordCharFormat(cf);//设置当前字符格式
	richedit.SetSel(0, 0);
}


void CDlg2::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);
	CRect rect;
	GetClientRect(rect);
	rect.DeflateRect(5, 5, 5, 5);
	if (richedit.GetSafeHwnd())
		richedit.MoveWindow(rect);
}

MyButton.h

#pragma once


// CMyButton

class CMyButton : public CButton
{
	DECLARE_DYNAMIC(CMyButton)

public:
	CMyButton();
	virtual ~CMyButton();

protected:
	DECLARE_MESSAGE_MAP()
public:
	CFont font1;
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
};

MyButton.cpp

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

#include "stdafx.h"
#include "目录比对.h"
#include "MyButton.h"


// CMyButton

IMPLEMENT_DYNAMIC(CMyButton, CButton)

CMyButton::CMyButton()
{
	font1.CreatePointFont(130, L"微软雅黑");
}

CMyButton::~CMyButton()
{
}


BEGIN_MESSAGE_MAP(CMyButton, CButton)
END_MESSAGE_MAP()

void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	CDC dc; CDC comdc;
	dc.Attach(lpDrawItemStruct->hDC);
	if (lpDrawItemStruct->CtlID == IDC_BUTTON1 || lpDrawItemStruct->CtlID == IDC_BUTTON2)//绘制按钮
	{
		CRect rect(lpDrawItemStruct->rcItem);
		dc.FillSolidRect(&rect, RGB(70, 50, 50));
		CRgn rgn; rgn.CreateRoundRectRgn(rect.left, rect.top, rect.right, rect.bottom, 6, 6);
		dc.FillRgn(&rgn, &CBrush(RGB(150, 150, 150)));
		CRect r1; r1.CopyRect(rect); r1.DeflateRect(2, 2);
		CRgn rgn1; rgn1.CreateRoundRectRgn(r1.left, r1.top, r1.right, r1.bottom, 4, 4);
		CRgn rgnA; rgnA.CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
		rgnA.CombineRgn(&rgn, &rgn1, RGN_DIFF);
		dc.FillRgn(&rgnA, &CBrush(RGB(0, 0, 0)));
		dc.SelectObject(&font1); dc.SetTextColor(RGB(0, 0, 0)); dc.SetBkColor(RGB(150, 150, 150));
		CString str; GetWindowText(str);
		dc.DrawText(str, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	}
	dc.Detach();
}

MyRichEdit.h

#pragma once


// CMyRichEdit

class CMyRichEdit : public CRichEditCtrl
{
	DECLARE_DYNAMIC(CMyRichEdit)

public:
	CMyRichEdit();
	virtual ~CMyRichEdit();

protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
};

MyRichEdit.cpp

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

#include "stdafx.h"
#include "目录比对.h"
#include "MyRichEdit.h"


// CMyRichEdit

IMPLEMENT_DYNAMIC(CMyRichEdit, CRichEditCtrl)

CMyRichEdit::CMyRichEdit()
{

}

CMyRichEdit::~CMyRichEdit()
{
}


BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)
	ON_WM_RBUTTONDOWN()
END_MESSAGE_MAP()

void CMyRichEdit::OnRButtonDown(UINT nFlags, CPoint point)
{
	if (GetDlgCtrlID() == IDC_RICHEDIT21 )
	{
		CMenu menu;
		menu.LoadMenu(IDR_MENU1);
		CMenu* pmenu = menu.GetSubMenu(2);
		ClientToScreen(&point);//需将point转换为屏幕坐标
		pmenu->TrackPopupMenu(TPM_LEFTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, point.x, point.y, GetParent());
	}
	if (GetDlgCtrlID() == IDC_RICHEDIT22)
	{
		CMenu menu;
		menu.LoadMenu(IDR_MENU1);
		CMenu* pmenu = menu.GetSubMenu(3);
		ClientToScreen(&point);//需将point转换为屏幕坐标
		pmenu->TrackPopupMenu(TPM_LEFTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, point.x, point.y, GetParent());
	}
	CRichEditCtrl::OnRButtonDown(nFlags, point);
}

MyTree.h

#pragma once


// CMyTree

class CMyTree : public CTreeCtrl
{
	DECLARE_DYNAMIC(CMyTree)

public:
	CMyTree();
	virtual ~CMyTree();

protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
};

MyTree.cpp

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

#include "stdafx.h"
#include "目录比对.h"
#include "MyTree.h"
#include "目录比对Dlg.h"

// CMyTree

IMPLEMENT_DYNAMIC(CMyTree, CTreeCtrl)

CMyTree::CMyTree()
{

}

CMyTree::~CMyTree()
{
}


BEGIN_MESSAGE_MAP(CMyTree, CTreeCtrl)
	ON_WM_RBUTTONDOWN()
END_MESSAGE_MAP()

void CMyTree::OnRButtonDown(UINT nFlags, CPoint point)
{
	C目录比对Dlg* pDlg = (C目录比对Dlg*)theApp.m_pMainWnd;
	if (GetDlgCtrlID() == IDC_TREE1 && pDlg->hCheckThread == NULL)
	{
		CMenu menu; menu.LoadMenu(IDR_MENU1);
		CMenu* p = menu.GetSubMenu(0);
		if (pDlg->hLoadDiskThread1 || pDlg->hLoadFileThread1)
		{
			p->EnableMenuItem(0, MF_BYPOSITION | MF_DISABLED);
			p->EnableMenuItem(1, MF_BYPOSITION | MF_DISABLED);
			p->EnableMenuItem(2, MF_BYPOSITION | MF_DISABLED);
			p->EnableMenuItem(3, MF_BYPOSITION | MF_DISABLED);
			p->EnableMenuItem(5, MF_BYPOSITION | MF_DISABLED);
		}
		if (pDlg->tree1.GetSelectedItem() == NULL)
		{
			p->EnableMenuItem(5, MF_BYPOSITION | MF_DISABLED);
		}
		ClientToScreen(&point);
		p->TrackPopupMenu(TPM_LEFTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, point.x + 20, point.y, GetParent());//
		menu.DestroyMenu();
	}
	if (GetDlgCtrlID() == IDC_TREE2 && pDlg->hCheckThread == NULL)
	{
		CMenu menu; menu.LoadMenu(IDR_MENU1);
		CMenu* p = menu.GetSubMenu(1);
		if (pDlg->hLoadDiskThread2 || pDlg->hLoadFileThread2)
		{
			p->EnableMenuItem(0, MF_BYPOSITION | MF_DISABLED);
			p->EnableMenuItem(1, MF_BYPOSITION | MF_DISABLED);
			p->EnableMenuItem(2, MF_BYPOSITION | MF_DISABLED);
			p->EnableMenuItem(3, MF_BYPOSITION | MF_DISABLED);
			p->EnableMenuItem(5, MF_BYPOSITION | MF_DISABLED);
		}
		if (pDlg->tree2.GetSelectedItem() == NULL)
		{
			p->EnableMenuItem(5, MF_BYPOSITION | MF_DISABLED);
		}
		ClientToScreen(&point);
		p->TrackPopupMenu(TPM_LEFTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, point.x + 20, point.y, GetParent());//
		menu.DestroyMenu();
	}
	CTreeCtrl::OnRButtonDown(nFlags, point);
}

下载本应用

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

h3974

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值