抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

靖待的技术博客

小清新IT旅程 | 为中华之崛起而读书





  MFC,多线程+进度条+复制文件(夹)小程序。


  多线程:

  1. 做一个MFC对话框程序。
  2. 点击开始按钮,程序启动一个工作线程,复制指定的文件夹到目标位置。
  3. 同时在更新进度条,反映当前的复制进度(按文件数量计算进度)。
  4. 点击停止按钮时终止,但需要保证当前正在复制的文件得以复制完成。
  5. 工作线程访问主线程需要使用消息机制,不能直接访问。
  6. 主界面不能锁死,停止按钮需要随时可以响应点击。

整体思路:
在开始按钮里的响应函数中创建一个线程,在线程里复制,通过消息机制更新进度条,在消息机制的函数中和复制过程关联显示进度。

需要解决的问题:
1.怎么创建线程
2.怎么更新进度条
3.怎么将编辑框中输入的路径被copyfile函数读取到
4.怎么获取文件个数(遍历)
5.怎么把进度条和复制文件进度关联
(通过文件个数 进度条范围设置为0-文件数量长度 步长为1 完成一次复制加一次)
6.点击取消怎么保证当前正在复制的文件得以复制完成

获取个数:
递归遍历整个文件夹,然后递归复制文件到目的文件夹。
在递归遍历整个文件夹的时候,就可以拿到整个文件夹的大小以及文件数量。

传递进度数据,用postmessage到该进度条的窗口,在进度条窗口获取该消息 设置SetPos,updatedata该控件。
一个对话框里有个进度条控件,当线程接收到数据(文件的总大小和收到的大小)postmessage给对话框,对话框的PreTranslateMessage(MSG* pMsg)截取该消息设置进度条控件(范围和增量,setpos)。

我的方案:
关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//复制函数
void CopyDirectory(CString source, CString target, CCopyFoldersDlg * pDlg)
{

CreateDirectory(target,NULL);

CFileFind finder;
CString path;
path.Format(_T("%s\\*.*"),source);

BOOL bWorking = finder.FindFile(path);
while (bWorking)
{
bWorking = finder.FindNextFile();

if (finder.IsDirectory() && !finder.IsDots())
{
CopyDirectory(finder.GetFilePath(), target+_T("\\")+finder.GetFileName(), pDlg); //递归
}
else
{

WaitForSingleObject(pDlg->hEvent,INFINITE);

CopyFile(finder.GetFilePath(), target+_T("\\")+finder.GetFileName(), FALSE);
count++;
pDlg->PostMessage(WM_USER_PROCESS, count);


Sleep(50);
}
}
}

VOID GetInfo(CString csPath, long& FoldersNum, long& FilesNum)
{
SetCurrentDirectory(csPath);
CFileFind finder;
BOOL bWorking = finder.FindFile(_T("*.*"));
while(bWorking)
{
bWorking = finder.FindNextFile();

if(finder.IsDots())
{
continue;
}
else if(finder.IsDirectory())
{
++FoldersNum;
GetInfo(finder.GetFilePath(), FoldersNum, FilesNum);
}
else
{
++FilesNum;
}
}

}

//复制线程
DWORD WINAPI CCopyFoldersDlg::CopyFolders(LPVOID pParam)
{
CCopyFoldersDlg* pDlg = (CCopyFoldersDlg*)pParam;

if (!pDlg)
{
return 0;
}
ResetEvent(pDlg->hExit);

long FoldersNum = 0;
long FilesNum = 0;
GetInfo(pDlg->m_SrcPath,FoldersNum, FilesNum);
pDlg->m_Progress.SetRange(0, FilesNum);
pDlg->m_Progress.SetStep(1);
CopyDirectory(pDlg->m_SrcPath, pDlg->m_DesPath, pDlg);

SetEvent(pDlg->hExit);
return 0;
}

LRESULT CCopyFoldersDlg::Do_process(WPARAM wParam, LPARAM lParam)
{
wParam += 1;
m_Progress.SetPos(wParam);
return 0;
}




void CCopyFoldersDlg::OnStart()
{
UpdateData(true);

if ((m_SrcPath.IsEmpty() && m_DesPath.IsEmpty()))
{
MessageBox("路径不能为空!");
return;
}

else
{
//创建线程
hThread = CreateThread(NULL, 0, CopyFolders, this, 0, NULL);
hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
CloseHandle(hThread);
}
}


void CCopyFoldersDlg::OnStop()
{
m_iStatus++;

if (m_iStatus % 2 == 0)
{
SetEvent(hEvent);
}
else
{
ResetEvent(hEvent);
}
}

void CCopyFoldersDlg::OnTimer(UINT_PTR nIDEvent)
{
CDialog::OnTimer(nIDEvent);
}

完整代码:
.cpp文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
// CopyFoldersDlg.cpp : implementation file
//

#include "stdafx.h"
#include "CopyFolders.h"
#include "CopyFoldersDlg.h"
#include "windows.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static int count = 0;
#define WM_USER_PROCESS (WM_USER+101)

void CopyDirectory(CString source, CString target,CWnd * pWndMsg);
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
CAboutDlg();

// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL

// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCopyFoldersDlg dialog

CCopyFoldersDlg::CCopyFoldersDlg(CWnd* pParent /*=NULL*/)
: CDialog(CCopyFoldersDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CCopyFoldersDlg)
m_SrcPath = _T("");
m_DesPath = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CCopyFoldersDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCopyFoldersDlg)
DDX_Control(pDX, IDC_PROGRESS, m_Progress);
DDX_Text(pDX, IDC_EDIT1, m_SrcPath);
DDX_Text(pDX, IDC_EDIT2, m_DesPath);
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CCopyFoldersDlg, CDialog)
//{{AFX_MSG_MAP(CCopyFoldersDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_START, OnStart)
ON_BN_CLICKED(IDC_STOP, OnStop)
ON_MESSAGE(WM_USER_PROCESS, Do_process)
ON_WM_TIMER()

//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCopyFoldersDlg message handlers

BOOL CCopyFoldersDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here

return TRUE; // return TRUE unless you set the focus to a control
}

void CCopyFoldersDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

// 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 CCopyFoldersDlg::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();
}
}

// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CCopyFoldersDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}



//复制函数
void CopyDirectory(CString source, CString target, CCopyFoldersDlg * pDlg)
{

CreateDirectory(target,NULL);

CFileFind finder;
CString path;
path.Format(_T("%s\\*.*"),source);

BOOL bWorking = finder.FindFile(path);
while (bWorking)
{
bWorking = finder.FindNextFile();

if (finder.IsDirectory() && !finder.IsDots())
{
CopyDirectory(finder.GetFilePath(), target+_T("\\")+finder.GetFileName(), pDlg); //递归
}
else
{

WaitForSingleObject(pDlg->hEvent,INFINITE);

CopyFile(finder.GetFilePath(), target+_T("\\")+finder.GetFileName(), FALSE);
count++;
pDlg->PostMessage(WM_USER_PROCESS, count);


Sleep(50);
}
}
}

VOID GetInfo(CString csPath, long& FoldersNum, long& FilesNum)
{
SetCurrentDirectory(csPath);
CFileFind finder;
BOOL bWorking = finder.FindFile(_T("*.*"));
while(bWorking)
{
bWorking = finder.FindNextFile();

if(finder.IsDots())
{
continue;
}
else if(finder.IsDirectory())
{
++FoldersNum;
GetInfo(finder.GetFilePath(), FoldersNum, FilesNum);
}
else
{
++FilesNum;
}
}

}

//复制线程
DWORD WINAPI CCopyFoldersDlg::CopyFolders(LPVOID pParam)
{
CCopyFoldersDlg* pDlg = (CCopyFoldersDlg*)pParam;

if (!pDlg)
{
return 0;
}
ResetEvent(pDlg->hExit);

long FoldersNum = 0;
long FilesNum = 0;
GetInfo(pDlg->m_SrcPath,FoldersNum, FilesNum);
pDlg->m_Progress.SetRange(0, FilesNum);
pDlg->m_Progress.SetStep(1);
CopyDirectory(pDlg->m_SrcPath, pDlg->m_DesPath, pDlg);

SetEvent(pDlg->hExit);
return 0;
}

LRESULT CCopyFoldersDlg::Do_process(WPARAM wParam, LPARAM lParam)
{
wParam += 1;
m_Progress.SetPos(wParam);
return 0;
}




void CCopyFoldersDlg::OnStart()
{
UpdateData(true);

if ((m_SrcPath.IsEmpty() && m_DesPath.IsEmpty()))
{
MessageBox("路径不能为空!");
return;
}

else
{
//创建线程
hThread = CreateThread(NULL, 0, CopyFolders, this, 0, NULL);
hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
CloseHandle(hThread);
}
}


void CCopyFoldersDlg::OnStop()
{
m_iStatus++;

if (m_iStatus % 2 == 0)
{
SetEvent(hEvent);
}
else
{
ResetEvent(hEvent);
}
}

void CCopyFoldersDlg::OnTimer(UINT_PTR nIDEvent)
{
CDialog::OnTimer(nIDEvent);
}

.h文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// CopyFoldersDlg.h : header file
//

#if !defined(AFX_COPYFOLDERSDLG_H__BADF1BD0_296B_4FED_96F7_BCD2628D4B03__INCLUDED_)
#define AFX_COPYFOLDERSDLG_H__BADF1BD0_296B_4FED_96F7_BCD2628D4B03__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000



/////////////////////////////////////////////////////////////////////////////
// CCopyFoldersDlg dialog

class CCopyFoldersDlg : public CDialog
{
// Construction
public:
CCopyFoldersDlg(CWnd* pParent = NULL); // standard constructor

HANDLE hThread;
HANDLE hEvent;
HANDLE hExit;

static DWORD WINAPI CopyFolders(LPVOID pParam);
int m_iStatus;

// Dialog Data
//{{AFX_DATA(CCopyFoldersDlg)
enum { IDD = IDD_COPYFOLDERS_DIALOG };
CProgressCtrl m_Progress;
CString m_SrcPath;
CString m_DesPath;
//}}AFX_DATA

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CCopyFoldersDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL

// Implementation
protected:
HICON m_hIcon;





// Generated message map functions
//{{AFX_MSG(CCopyFoldersDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnStart();
afx_msg void OnStop();
afx_msg LRESULT CCopyFoldersDlg::Do_process(WPARAM wParam,LPARAM lParam);
afx_msg void OnTimer(UINT_PTR nIDEvent);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_COPYFOLDERSDLG_H__BADF1BD0_296B_4FED_96F7_BCD2628D4B03__INCLUDED_)

界面:
界面

另一种方案(大同小异):
.cpp文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
// FileCopyNumDlg.cpp : implementation file
//

#include "stdafx.h"
#include "FileCopyNum.h"
#include "FileCopyNumDlg.h"

#define WM_COPYFILE_NOTIFY_NUM WM_USER+1
#define WM_COPYFILE_NOTIFY_SUM WM_USER+8
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
CAboutDlg();

// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL

// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFileCopyNumDlg dialog

CFileCopyNumDlg::CFileCopyNumDlg(CWnd* pParent /*=NULL*/)
: CDialog(CFileCopyNumDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CFileCopyNumDlg)
m_sourcePath = _T("");
m_desPath = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CFileCopyNumDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFileCopyNumDlg)
DDX_Control(pDX, IDC_PROGRESS1, m_progress);
DDX_Text(pDX, IDC_EDIT1, m_sourcePath);
DDX_Text(pDX, IDC_EDIT2, m_desPath);
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CFileCopyNumDlg, CDialog)
//{{AFX_MSG_MAP(CFileCopyNumDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_CHOOSEFILE1, OnBtnChoosefile1)
ON_BN_CLICKED(IDC_BTN_CHOOSEFILE2, OnBtnChoosefile2)
ON_BN_CLICKED(IDC_BTN_PAUSE, OnBtnPause)
ON_BN_CLICKED(IDC_BTN_RESUME, OnBtnResume)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BTN_BEGIN, OnBtnBegin)

ON_MESSAGE(WM_COPYFILE_NOTIFY_NUM, OnCopyFileNotifyNum)
ON_MESSAGE(WM_COPYFILE_NOTIFY_SUM, OnCopyFileNotifySum)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFileCopyNumDlg message handlers

BOOL CFileCopyNumDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here
m_num = 0;
m_sum = 0;
m_progress.SetRange(0, 100);
m_progress.SetPos(0);

return TRUE; // return TRUE unless you set the focus to a control
}

void CFileCopyNumDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

// 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 CFileCopyNumDlg::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();
}
}

// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CFileCopyNumDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}

void CFileCopyNumDlg::OnBtnChoosefile1()
{
CFileDialog dlg(TRUE);
if(IDOK==dlg.DoModal())
{
strSourceFile=dlg.GetPathName();
}
SetDlgItemText(IDC_EDIT1,strSourceFile);
}

void CFileCopyNumDlg::OnBtnChoosefile2()
{
CFileDialog dlg(TRUE);
if(IDOK==dlg.DoModal())
{
strNewFile=dlg.GetPathName();
}
SetDlgItemText(IDC_EDIT2,strSourceFile);
}

void CFileCopyNumDlg::OnBtnBegin()
{
UpdateData(TRUE);

hThread = CreateThread(NULL, 0, ThreadProc_Copy, this, 0, NULL);
hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);


}

DWORD WINAPI CFileCopyNumDlg::ThreadProc_Copy(LPVOID lpParam)
{
double num = 0;
double sum = 0;

CString SourcePath = ((CFileCopyNumDlg*)lpParam)->m_sourcePath;
CString DesPath = ((CFileCopyNumDlg*)lpParam)->m_desPath + L"\\";

CFileFind findcount;
BOOL bRet = findcount.FindFile(((CFileCopyNumDlg*)lpParam)->m_sourcePath + CString("\\*.*"));

while (bRet)
{
bRet = findcount.FindNextFile();
if (findcount.IsDirectory())
{
continue;
}
else
{
((CFileCopyNumDlg*)lpParam)->PostMessage(WM_COPYFILE_NOTIFY_SUM);
}
}
findcount.Close();

CFileFind find;
bRet = find.FindFile(((CFileCopyNumDlg*)lpParam)->m_sourcePath + CString("\\*.*"));

while (bRet)
{
bRet = find.FindNextFile();
if (find.IsDirectory())
{
continue;
}
else
{
((CFileCopyNumDlg*)lpParam)->m_sourcePath = find.GetFilePath();
((CFileCopyNumDlg*)lpParam)->m_desPath = DesPath + find.GetFileName();

WaitForSingleObject(((CFileCopyNumDlg*)lpParam)->hEvent,INFINITE);

CopyFile(((CFileCopyNumDlg*)lpParam)->m_sourcePath, ((CFileCopyNumDlg*)lpParam)->m_desPath, FALSE);
((CFileCopyNumDlg*)lpParam)->PostMessage(WM_COPYFILE_NOTIFY_NUM);

}
}

AfxMessageBox("复制成功!");
return 0 ;
}


void CFileCopyNumDlg::OnBtnPause()
{
ResetEvent(hEvent);
}

void CFileCopyNumDlg::OnBtnResume()
{
SetEvent(hEvent);
}

void CFileCopyNumDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default

CDialog::OnTimer(nIDEvent);
}


afx_msg LRESULT CFileCopyNumDlg::OnCopyFileNotifyNum(WPARAM wParam, LPARAM lParam)
{
m_num++;
m_progress.SetPos(int(m_num / m_sum * 100));
return 0;
}


afx_msg LRESULT CFileCopyNumDlg::OnCopyFileNotifySum(WPARAM wParam, LPARAM lParam)
{
m_sum++;
return 0;
}

.h文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// FileCopyNumDlg.h : header file
//

#if !defined(AFX_FILECOPYNUMDLG_H__02EF2204_005C_4A21_A048_ED73C9CD1F34__INCLUDED_)
#define AFX_FILECOPYNUMDLG_H__02EF2204_005C_4A21_A048_ED73C9CD1F34__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////
// CFileCopyNumDlg dialog

class CFileCopyNumDlg : public CDialog
{
// Construction
public:
CFileCopyNumDlg(CWnd* pParent = NULL); // standard constructor

// Dialog Data
//{{AFX_DATA(CFileCopyNumDlg)
enum { IDD = IDD_FILECOPYNUM_DIALOG };
CProgressCtrl m_progress;
CString m_sourcePath;
CString m_desPath;
//}}AFX_DATA

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CFileCopyNumDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL

// Implementation
protected:
HICON m_hIcon;

// Generated message map functions
//{{AFX_MSG(CFileCopyNumDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnBtnChoosefile1();
afx_msg void OnBtnChoosefile2();
afx_msg void OnBtnPause();
afx_msg void OnBtnResume();
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnBtnBegin();

afx_msg LRESULT OnCopyFileNotifyNum(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnCopyFileNotifySum(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
// LPCTSTR lpExistingPathName; //源文件
//LPCTSTR lpNewPathName; //目标文件
HANDLE hThread; //线程句柄
HANDLE hEvent; //复制暂停事件

CString strSourceFile;
CString strNewFile;

double m_num;
double m_sum;
static DWORD WINAPI ThreadProc_Copy(LPVOID lpParam);//线程函数
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_FILECOPYNUMDLG_H__02EF2204_005C_4A21_A048_ED73C9CD1F34__INCLUDED_)

这里写图片描述

评论