图片目录
根据修改日期自动编目图片
引言
如果您和我一样,那么您可能已经按照某些标准将您的图片库组织在文件夹中。很可能是按日期编目的。我个人更喜欢让我的库组织成类似下图的截图
我敢打赌,从相机传输文件是一项艰巨的任务。
背景
我选择使用 Total Commander 作为文件管理器。最近,我在他们的论坛上 询问 是否可以包含一个允许目录管理的插件。显然,您可以使用内置工具(有人建议使用脚本进行两步处理)。
总之,周五晚上我有一个空闲的几个小时,完成了一个项目,不想开始一个新项目。所以,我写了一个小工具,它根据文件的日期将文件从源文件夹复制到目标文件夹。
在使用第一个版本一周后,我决定对其进行一些改进。首先,我将文件复制功能移到了一个单独的线程。然后我添加了一些更有用的功能。
结果,这个程序诞生了
目标读者
本文的目标读者是刚开始使用 MFC 进行桌面开发的初学者。代码演示了如何使用这些 MFC 控件
CMFCEditBrowseCtrl
CProgressCtrl
CListCtrl
CImageList
CEdit
CComboBox
CStatic
本文还演示了如何使用 Windows 自动完成功能来实现基于文件系统的编辑框。我使用了我自己的帮助类 CAutoCompleteHelper
,您可能会在自己的项目中发现它很有用。
代码还演示了如何使用 CWinThread
类在单独的线程中执行操作。线程使用 CEvent
类进行同步(您可以通过单击“关闭”按钮来中断耗时的过程)。
您将学习如何在复制大文件时使用回调函数来显示复制过程并根据需要中断。
最棒的是,如果您不熟悉 MFC 编程,您仍然可以使用我随文章一起提供的工具。
请注意,最低操作系统要求是 Windows XP SP3。
程序功能
程序退出时会将所有输入参数保存到 INI 文件中。我还实现了一个智能功能(我希望我没有 过度 使用它),该功能会自动将“第一个图像文件”值重新初始化为上一会话中使用的“最后一个图像文件”之后的下一个文件。我使用它的方式,以及我认为它可能被使用的方式是,您只需要不时地从相机中弹出内存卡,打开程序,然后单击“目录图像”按钮。
在版本 1.1 中,我实现了一个功能,用于扫描输入文件夹中的新子文件夹。原因很简单——我有一台新相机。它是尼康的。出于某种原因,他们坚持每个文件夹最多只能有 200 张照片。现在,当您在一个子文件夹中选择一张照片时,程序将自动构建一个包含该子文件夹中的所有照片以及所有后续子文件夹的照片列表。
Using the Code
IDE
该程序是用 Visual Studio 2012 编写的。我决定使用 VS2012 来利用新的控件 CMFCEditBrowseCtrl
。结果发现该控件不如我预期的那样提供自动完成功能。您仍然需要使用 SHAutoComplete
API。
自动完成
我编写了一个特殊的帮助类来设置自动完成。您只需在对话框类中创建此类的实例,并为所需的控件设置自动完成。
m_autoComplHlpr.SetAutoComplete(&m_edFileFirst, CAutoCompleteHelper::AutoCompleteFileSys);
m_autoComplHlpr.SetAutoComplete(&m_edFileLast, CAutoCompleteHelper::AutoCompleteFileSys);
m_autoComplHlpr.SetAutoComplete(&m_edOutFolder, CAutoCompleteHelper::AutoCompleteFileSys);
线程间通信
众所周知,使用 Windows 消息进行线程间通信是一种好习惯。当然,我们都会通过将对话框类的指针作为参数传递给线程函数来采取捷径。然而,每一本手册都会告诉你,这不是一个好主意。这个程序就是考虑到这一点而编写的,并展示了一种好的实践。
线程使用以下两条消息与 GUI 通信
#define WM_MY_COPY_PROGRESS (WM_USER + 1)
#define WM_MY_COPY_FINISHED (WM_USER + 2)
前者是为每个复制的文件发送的消息,后者是指示过程完成的消息。
在主对话框类中,指定了这些消息处理程序。复制进度处理程序有三个状态
afx_msg LRESULT CImageCataloguerDlg::OnCopyProgress(WPARAM wParam, LPARAM lParam)
{
MyCopyProgressParm* pParm = (MyCopyProgressParm*) lParam;
if (wParam == MY_COPY_PROGRESS_PRE)
{
// before copying
}
else if(wParam == MY_COPY_PROGRESS_CHUNK)
{
// When a big file is being copied
}
else
{
// after copying. Error or Success
}
return 0;
}
过程完成处理程序用于向用户显示一些消息
afx_msg LRESULT CImageCataloguerDlg::OnCopyFinished(WPARAM wParam, LPARAM lParam)
{
}
线程同步
使用 CEvent
进行线程同步。我在主对话框类中创建了一个成员变量,声明为
CEvent *m_pStopEvent;
如果复制过程中在任何时候您发现输入/输出文件夹的掩码指定错误,该事件将用于停止复制过程。
参考文献
此程序使用了别人的工作。我想感谢他们的努力,并感谢他们出色的工作。
- 主对话框类派生自 Robert Python 的 CResizeDlg。
- 主应用程序图标以及列表控件中的错误/成功图标来自 Oxygen Team 团队的艺术家提供的 免费图标集。
关注点
在制作程序的过程中,我发现 FindFirstFile
/FindNextFile
API(及其 CFileFind
MFC 包装器)不支持多重掩码。我最终在循环中为每个单独的掩码搜索文件。您可以通过搜索所有文件(*.*)然后在代码中过滤文件来增强程序。
该程序可以通过多种方式得到增强。您可以使用 Davide Pizzolato 编写的一个漂亮的 Cexif 类来获取图像文件的“拍摄日期”,并将其用于目录管理。
您还可以使用几行代码在窗体上放置一个 图像预览器 控件。
历史
- 2012 年 10 月 8 日:发布版本 1.0
- 2013 年 2 月 12 日:版本 1.1。增强功能,可自动扫描新子文件夹中的图像(按名称顺序的下一个子文件夹)
- 2013 年 9 月 27 日:版本 1.1。使用 Visual Studio 2012 - Windows XP (v110_xp) 平台工具集重新构建了应用程序
- 2014 年 10 月 6 日:版本 1.2。添加了一个新功能:允许选择复制或移动操作,并能够覆盖现有文件。还添加了一个状态文本,指示在上一次操作中复制/移动了多少文件