向导生成的所有控件变量:
其它变量:
消息映射:
核心代码(FolderMonitorDlg.h):
(完)
<code class="lang-cpp">void CFolderMonitorDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_BTN_START, m_startbutton); DDX_Control(pDX, IDC_EDIT1, m_folderedit); DDX_Control(pDX, IDC_MFCSHELLTREE1, m_foldertree); DDX_Control(pDX, IDC_LIST1, m_resultlist); DDX_Control(pDX, IDC_CHECK1, m_flag_filename); DDX_Control(pDX, IDC_CHECK2, m_flag_dirname); DDX_Control(pDX, IDC_CHECK3, m_flag_attr); DDX_Control(pDX, IDC_CHECK4, m_flag_size); DDX_Control(pDX, IDC_CHECK5, m_flag_lastwrite); DDX_Control(pDX, IDC_CHECK6, m_flag_lastaccess); DDX_Control(pDX, IDC_CHECK7, m_flag_creation); DDX_Control(pDX, IDC_CHECK8, m_flag_security); }</code>
其它变量:
<code class="lang-cpp">CString m_getpath; CString m_getopr; CString m_gettime; CWinThread *m_monthread; HANDLE m_dirhandle; CMutex m_mutex;</code>
消息映射:
<code class="lang-cpp">#define WM_TRHEADMSG (WM_USER + 8) BEGIN_MESSAGE_MAP(CFolderMonitorDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_NOTIFY(TVN_SELCHANGED, IDC_MFCSHELLTREE1, &CFolderMonitorDlg::OnTvnSelchangedMfcshelltree1) ON_BN_CLICKED(IDC_BTN_START, &CFolderMonitorDlg::OnBnClickedBtnStart) ON_MESSAGE(WM_TRHEADMSG, &CFolderMonitorDlg::ThreadMsg) ON_WM_DESTROY() ON_COMMAND_RANGE(IDC_CHECK1, IDC_CHECK8, &CFolderMonitorDlg::OnCheckBox) END_MESSAGE_MAP()</code>
核心代码(FolderMonitorDlg.h):
<code class="lang-cpp">////////////////////////////////////////////////////////////////////////////////////// //BOOL CFolderMonitorDlg::OnInitDialog() //{ // ResetComponents(); //} void CFolderMonitorDlg::ResetComponents(void) { while (m_resultlist.DeleteColumn(0)); // 删除原有表列 m_resultlist.InsertColumn(0, _T("路径"), 0, 200); // 添加表列 m_resultlist.InsertColumn(1, _T("操作"), 0, 80); m_resultlist.InsertColumn(2, _T("时间"), 0, 80); m_resultlist.ModifyStyle(LVS_TYPEMASK, LVS_REPORT); // 设置为列表式 DWORD exstyle = m_resultlist.GetExtendedStyle(); // 设置为全行选择、有格线 m_resultlist.SetExtendedStyle(exstyle|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); m_flag_filename.SetCheck(true); // 设置默认监控项目 m_flag_creation.SetCheck(true); m_flag_lastwrite.SetCheck(true); OnCheckBox(IDC_CHECK1); // 更新m_monflag } void CFolderMonitorDlg::OnTvnSelchangedMfcshelltree1(NMHDR *pNMHDR, LRESULT *pResult) { LPNMTREEVIEW pNMTreeView = reinterpret_cast<lpnmtreeview>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 *pResult = 0; CString path; m_foldertree.GetItemPath(path); m_folderedit.SetWindowText(path); // 根据文件夹树所选项目,更新文本框 } UINT MonitorThread(LPVOID pvoid); void CFolderMonitorDlg::OnBnClickedBtnStart() { // TODO: 在此添加控件通知处理程序代码 CString btntext; m_startbutton.GetWindowText(btntext); if (btntext == _T("开始")) { CString path; m_folderedit.GetWindowText(path); // 获取文本框中的字符串 m_dirhandle = ::CreateFile( // 打开所选目录! path, // 目录名 FILE_LIST_DIRECTORY, // 以列出目录权限打开 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, // 允许其它程序读写删除 NULL, // 没有安全选项 OPEN_EXISTING, // 存在时打开 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, // 备份存取异步存取 NULL); // 没有文件模板 if (m_dirhandle == INVALID_HANDLE_VALUE) // 如果打开失败则退出 return; m_monthread = new CWinThread(MonitorThread, this); // 新建并启动工作线程 m_monthread->CreateThread(); m_startbutton.SetWindowText(_T("停止")); } else if (btntext == _T("停止")) { OnDestroy(); // 停止工作线程并清理资源 m_startbutton.SetWindowText(_T("清除")); } else if (btntext == _T("清除")) { m_resultlist.DeleteAllItems(); // 清空列表框 m_startbutton.SetWindowText(_T("开始")); } else { AfxMessageBox(_T("出现了不该出现的情况")); m_startbutton.SetWindowText(_T("停止")); } } void CFolderMonitorDlg::OnDestroy() { if (m_monthread != NULL) // 如果线程存在,则终止线程 { if (m_monthread->m_hThread != INVALID_HANDLE_VALUE) m_monthread->SuspendThread(); delete m_monthread; m_monthread = NULL; } if (m_dirhandle != INVALID_HANDLE_VALUE) // 如果目录已打开,则关闭目录 { CloseHandle(m_dirhandle); m_dirhandle = INVALID_HANDLE_VALUE; } } //BEGIN_MESSAGE_MAP(CFolderMonitorDlg, CDialogEx) // ON_COMMAND_RANGE(IDC_CHECK1, IDC_CHECK8, &CFolderMonitorDlg::OnCheckBox) //END_MESSAGE_MAP() void CFolderMonitorDlg::OnCheckBox(UINT nID) { m_mutex.Lock(); // 赋值时可能会被工作线程异步读取,所以要上锁 m_monflag = 0; if (m_flag_attr.GetCheck()) m_monflag |= FILE_NOTIFY_CHANGE_ATTRIBUTES; if (m_flag_creation.GetCheck()) m_monflag |= FILE_NOTIFY_CHANGE_CREATION; if (m_flag_dirname.GetCheck()) m_monflag |= FILE_NOTIFY_CHANGE_DIR_NAME; if (m_flag_filename.GetCheck()) m_monflag |= FILE_NOTIFY_CHANGE_FILE_NAME; if (m_flag_lastaccess.GetCheck()) m_monflag |= FILE_NOTIFY_CHANGE_LAST_ACCESS; if (m_flag_lastwrite.GetCheck()) m_monflag |= FILE_NOTIFY_CHANGE_LAST_WRITE; if (m_flag_security.GetCheck()) m_monflag |= FILE_NOTIFY_CHANGE_SECURITY; if (m_flag_size.GetCheck()) m_monflag |= FILE_NOTIFY_CHANGE_SIZE; m_mutex.Unlock(); } UINT MonitorThread(LPVOID pvoid) { CFolderMonitorDlg *pWnd = (CFolderMonitorDlg*)pvoid; char notify[65536]; // 储存FILE_NOTIFY_INFORMATION链表的缓冲区 DWORD dwBytes; // 返回字节数 FILE_NOTIFY_INFORMATION *pnotify; // FILE_NOTIFY_INFORMATION指针 if (pWnd->m_dirhandle == INVALID_HANDLE_VALUE) // 如果文件夹没打开则直接结束 return 1; while(true) // 监控循环 { memset(notify, 0, sizeof(notify)); // 清零缓冲区 pnotify = (FILE_NOTIFY_INFORMATION*)notify; // 指向缓冲区开头的链表第一项 pWnd->m_mutex.Lock(); // 因为可能会被主线程异步赋值,所以要进行锁定 DWORD monflag = pWnd->m_monflag; // 获取flag(见OnCheckBox) pWnd->m_mutex.Unlock(); if (::ReadDirectoryChangesW( pWnd->m_dirhandle, // 目录句柄(见OnBnClickedBtnStart) ¬ify, sizeof(notify), // 缓冲区及大小 TRUE, // 是否监控子项目 monflag, // 监控的内容(见OnCheckBox) &dwBytes, // 返回字节数 NULL, NULL)) // 异步调用相关,这里是同步调用,因此全填NULL { if (!dwBytes) // 如果缓冲区溢出 { pWnd->m_getpath = _T("[缓冲区溢出]"); pWnd->m_getopr = _T("未知"); SYSTEMTIME st; GetLocalTime(&st); pWnd->m_gettime = CTime(st).Format("%H:%M:%S"); // 获取系统时间 pWnd->SendMessage(WM_TRHEADMSG, 0, 0); // 通知主线程添加列表项 } else while(true) // 链表迭代循环 { LPWSTR wbuf = pWnd->m_getpath.GetBufferSetLength(pnotify->FileNameLength / 2); memcpy(wbuf, pnotify->FileName, pnotify->FileNameLength); pWnd->m_getpath.ReleaseBuffer(pnotify->FileNameLength / 2); // 获取文件名 pWnd->m_getopr = // 获取操作类型 pnotify->Action == FILE_ACTION_ADDED ? _T("新建") : pnotify->Action == FILE_ACTION_MODIFIED ? _T("更改") : pnotify->Action == FILE_ACTION_REMOVED ? _T("删除") : pnotify->Action == FILE_ACTION_RENAMED_OLD_NAME ? _T("重命名") : pnotify->Action == FILE_ACTION_RENAMED_NEW_NAME ? _T("新名称") : _T("未知"); SYSTEMTIME st; GetLocalTime(&st); pWnd->m_gettime = CTime(st).Format("%H:%M:%S"); // 获取系统时间 pWnd->SendMessage(WM_TRHEADMSG, 0, 0); // 通知主线程添加列表项 if (pnotify->NextEntryOffset) // 如果返回了另一个项目(通常是新文件名) { pnotify = (FILE_NOTIFY_INFORMATION *) ((char*)pnotify + pnotify->NextEntryOffset); // 迭代链表下一项 continue; // 继续 } break; // 退出 } } } } //#define WM_THREADMSG (WM_USER + 8) //BEGIN_MESSAGE_MAP(CFolderMonitorDlg, CDialogEx) // ON_MESSAGE(WM_TRHEADMSG, &CFolderMonitorDlg::ThreadMsg) //END_MESSAGE_MAP() LRESULT CFolderMonitorDlg::ThreadMsg(WPARAM wParam, LPARAM lParam) { // 工作线程调用此消息以插入列表项 m_resultlist.InsertItem(0, m_getpath); // 根据返回的字符串插入表项,设置其它列的值 m_resultlist.SetItemText(0, 1, m_getopr); m_resultlist.SetItemText(0, 2, m_gettime); return TRUE; }</lpnmtreeview></code>
(完)
200字以内,仅用于支线交流,主线讨论请采用回复功能。