// TextDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Text.h"
#include "TextDlg.h"
#include "about.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTextDlg dialog
BOOL endlag=FALSE;//此全局变量是线程的出口标志,为TRUE表示要终止.
CTextDlg::CTextDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTextDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTextDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CTextDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTextDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTextDlg, CDialog)
//{{AFX_MSG_MAP(CTextDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_SELPATH, OnBtnSelpath)
ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
ON_BN_CLICKED(IDC_BTN_ABOUT, OnBtnAbout)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_PROC,OnProc)
ON_WM_DROPFILES()
ON_MESSAGE(WM_INITPROC,OnInitProc)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTextDlg message handlers
BOOL CTextDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
SetDlgItemText(IDC_EDIT_EXT,".txt");
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CTextDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CTextDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CTextDlg::OnBtnSelpath()
{
char name[MAX_PATH];//存放选择的文件夹名.
char path[MAX_PATH];//存放选择的文件夹全路径.
BROWSEINFO bi; //此结构用来设置即将打开的选择文件夹对话框.
bi.hwndOwner=m_hWnd;//在哪个窗口弹出,这是窗口的句柄.
bi.pidlRoot=NULL;//指向ITEMIDLIST结构指针,设置默认打开的文件夹.
bi.pszDisplayName=name;//接受关闭文件夹对话框时选择的文件夹名.
bi.lpszTitle="选择文件夹";//文件夹对话框标题.
bi.ulFlags=0; //文件夹对话框的一些设置.如是否有新建功能.
bi.lpfn=NULL; //回调函数地址,用来处理打开对话框后的一些消息.
bi.lParam=0;//回调函数参数.
ITEMIDLIST *it;//此结构包含选择的文件夹的信息.
it=SHBrowseForFolder(&bi);//SHBrowseForFolder函数用来打开一个选择文件夹的对话框.
if(it!=NULL)//如果点击取消那么返回值为NULL.
{
SHGetPathFromIDList(it,path);//从it结构中获取文件夹全路径.
SetDlgItemText(IDC_EDIT_PATH,path);
}
}
void CTextDlg::OnButton2() //起动按钮.
{
MAJIMING *ma=new MAJIMING; //此结构包含了传给新线程的所有参数.
ma->pathnum=1; //初始化目录为1,因为当前要搜索的目录也算.
ma->filenum=0; //初始化文件数.
ma->hwnd=m_hWnd;
GetDlgItemText(IDC_EDIT_PATH,ma->path);
GetDlgItemText(IDC_EDIT_EXT,ma->ext);
GetDlgItemText(IDC_EDIT_FIND,ma->findtext);
GetDlgItemText(IDC_EDIT_REPLACE,ma->placetext);
ma->overnum=0;
ma->huannum=0;
if(ma->path=="")
{
MessageBox("请选择要查找的目录!");
GetDlgItem(IDC_EDIT_PATH)->SetFocus();
return;
}
if(ma->ext=="")
{
MessageBox("请输入要查找的文件类型!");
GetDlgItem(IDC_EDIT_EXT)->SetFocus();
return;
}
if(ma->findtext=="")
{
MessageBox("请输入要查找的字符串!");
GetDlgItem(IDC_EDIT_FIND)->SetFocus();
return;
}
CString text;
if(GetDlgItemText(IDC_BUTTON2,text),text=="开始查找替换")
{
endlag=FALSE;
//创建新线程,传递结构变量,开始工作.这里要用两个新线程.
//第一个线程用来起动工作.然后等待第二个线程处理完毕,以把结果显示出来.
//如果用主线程等待会挂起应用程序.
HANDLE starthand=::CreateThread(NULL,0,StartThread,ma,0,NULL);
::CloseHandle(starthand);//别忘了关闭线程句柄.
CString str;
str.Format("文件总数: 0/%d",ma->filenum);
SetDlgItemText(IDC_LAB_NUM,str);
EnableFalse();
}
else
{
endlag=TRUE;
EnableTrue();
}
}
//返回符合条件的文件的个数和已经搜索了的文件夹个数.
void GetFileCount(CString path, CString ext, int *pathnum, int *filenum)
{
if(path.Right(1)!="\\")
{
path+="\\";
}
::CFileFind cf;
BOOL res = cf.FindFile(path+"*.*");
while(res)
{
if(endlag)//如果发出了停止消息.
{
return;
}
res=cf.FindNextFile();
if(cf.IsDots())//如果是"."或"..",这是两个目录.就跳过.
{
continue;
}
if(cf.IsDirectory()) //如果是目录.
{
(*pathnum)++;//记录共查找的目录数.
GetFileCount(path+cf.GetFileName(),ext,pathnum,filenum);//迭代.
}
else
{ //如果是文件.
int index=cf.GetFileName().GetLength()-cf.GetFileTitle().GetLength();
if(cf.GetFileName().Right(index)!=ext)//如果不是要查找的文件类型.
{
continue;
}
(*filenum)++;
}
}
}
//执行查找替换的线程.
DWORD WINAPI CTextDlg::ThreadProc(LPVOID lpParameter)
{
MAJIMING *ma=(MAJIMING*)lpParameter;//得到传来的结构.
CString path= ma->path;//要遍历的目录.
if(path.Right(1)!="\\")
{
path+="\\";
}
CFileFind cf;
BOOL res = cf.FindFile(path+"*.*");
while(res)
{
if(endlag)//如果发出了停止消息.
{
return 0;
}
res=cf.FindNextFile();
if(cf.IsDots())//如果是"."或"..",这是两个目录.就跳过.
{
continue;
}
else if(cf.IsDirectory()) //如果是目录.
{
ma->path=path+cf.GetFileName();
ThreadProc(ma);//迭代.
}
else
{ //如果是文件.
int index=cf.GetFileName().GetLength()-cf.GetFileTitle().GetLength();
if(cf.GetFileName().Right(index)!=ma->ext)//如果不是要查找的文件类型.
{
continue;
}
//把当前正在处理的文件名显示出来.
::SetDlgItemText(ma->hwnd,IDC_LAB_TEXT,cf.GetFilePath());
//开始处理文件.
CString rep=cf.GetFileName();
if(rep.Find(ma->findtext)!=-1)//如果在此文件中找到了要替换的文字.
{
rep.Replace(ma->findtext,ma->placetext);
DWORD shu=::GetFileAttributes(cf.GetFilePath());//获取文件属性.
SetFileAttributes(cf.GetFilePath(),FILE_ATTRIBUTE_NORMAL);//先把所有属性去掉,以防没有写权限.
if(GetFileAttributes(path+rep)!=-1)
{
::DeleteFile(path+rep);
}
CFile::Rename(cf.GetFilePath(),path+rep);
SetFileAttributes(cf.GetFilePath(), shu );//再把去掉的属性还原.
ma->huannum++;//实际修改的文件数递增.
}
ma->overnum++;
::PostMessage(ma->hwnd,WM_PROC,ma->filenum,ma->overnum);
}
}
return 0;
}
//起动线程.负责整个工作的调度.
DWORD WINAPI CTextDlg::StartThread(LPVOID lpParameter)
{
MAJIMING *ma=(MAJIMING*)lpParameter;
::SetDlgItemText(ma->hwnd,IDC_LAB_TEXT,"正在获取目录文件信息...");
//此函数用来返回指定目录下符合条件的文件数和子目录数.
//第一个参数是指定目录,第二个参数是要搜索的文件扩展名.
//第三个参数是输出值,返回子目录数,第四个返回文件数.
GetFileCount(ma->path,ma->ext,&ma->pathnum,&ma->filenum);
//发送消息以初始化进度条.显示.
::SendMessage(ma->hwnd,WM_INITPROC,1,ma->filenum);
HANDLE handle = ::CreateThread(NULL,0,ThreadProc,lpParameter,0,NULL);
::WaitForSingleObject(handle,INFINITE);//等待指定的线程工作完毕.
::CloseHandle(handle);
::SendMessage(ma->hwnd,WM_INITPROC,2,0);//把各个控件状态设为可用.
::SendMessage(ma->hwnd,WM_INITPROC,0,0);//隐藏进度条.
//查找替换完毕,开始进行统计工作.
CString filenum;
CString pathnum;
CString total;
filenum.Format("%d",ma->huannum);
pathnum.Form