If you are like me, then you probably have your picture library organised in folders based on some criteria. It will be most likely catalogued by date. Personally, I prefer to have my library organised similar to the screenshot below:
I bet that it is quite a task to transfer the files from your camera.
I am using Total Commander as a file manager of my choice. Recently, I asked on their forum if they could include an add-on that will allow cataloguing. Apparently, you can do it using a built-in tool (someone suggested a two-step process using some scripts).
Anyway, I had a spare couple hours on Friday night when I finished a project and did not want to start a new project. So, I wrote a small tool that takes the files from a source folder and copies them to a target folder based on the files' dates.
After a week of using the first version, I decided to enhance it a little bit. First of all, I moved the file copy function to a separate thread. Then I added some more useful features.
As a result, this program has been created:
This article targets beginners that are just making their first steps in Desktop Development using MFC. The code demonstrates how to use these MFC controls:
The article also demonstrates how to use Windows Auto-Complete feature for the file-system based edit boxes. I am using my own helper class
CAutoCompleteHelper that you may find useful in your own projects.
The code also demonstrates how to use
CWinThread class to perform operations in a separate thread. The thread is synchronised using a
CEvent class (you can interrupt the lengthy process by clicking on Close button).
You will learn how to use a callback function when copying big files to display the copy process and to interrupt if required.
Best of all, if you are not into MFC programming, you can just use the tool, that I have also included with the article.
Please note that the minimum Operating System required is Windows XP SP3.
The program saves all the input parameters to an INI file on exit. I have also implemented a smart feature (I hope I did not overdo it) that automatically re-initialise the First Image File value to the next file followed after the Last Image File used in the previous session. The way I use it and I can see it being used is that you will just pop a memory card from your camera in from time to time, open the program and click on Catalog Images button.
In version 1.1, I have implemented a feature to scan for the new subfolders in the input folder. The reason for this is simple - I have a new camera. It is a Nikon. For some reason, they insist on having a maximum of 200 photos in each folder. Now when you select a photo in one subfolder, the program will automatically build a list with all the photos from this subfolder, and all subsequent subfolders.
Using the Code
The program is written in Visual Studio 2012. I have decided to use VS2012 to take advantage of the new control
CMFCEditBrowseCtrl. It turned out that the control does not provide the auto-complete functionality, as I expected. You still need to use
I have written a special helper class for setting up the auto-complete. All you need is to create an instance of this class in the dialog class and setup the auto-complete for the required controls.
Communication Between Threads
Everyone knows that it is a good practice to use Windows Messages for inter-thread communication. Of course, we all take shortcuts by passing a pointer of the dialog class to the thread function as a parameter. However, every single manual will tell you that it is not a very good idea. This program is written with this in mind and shows a good practice.
The thread communicates with the GUI using these two messages:
#define WM_MY_COPY_PROGRESS (WM_USER + 1)
#define WM_MY_COPY_FINISHED (WM_USER + 2)
The former is the message that is sent for each copied file, and the latter is the message to indicate that the process is finished.
In the main dialog class, these message handlers are specified. The handler for the copy progress has three states:
afx_msg LRESULT CImageCataloguerDlg::OnCopyProgress(WPARAM wParam, LPARAM lParam)
MyCopyProgressParm* pParm = (MyCopyProgressParm*) lParam;
if (wParam == MY_COPY_PROGRESS_PRE)
else if(wParam == MY_COPY_PROGRESS_CHUNK)
The handler for the process finish is used to display some messages to the user:
afx_msg LRESULT CImageCataloguerDlg::OnCopyFinished(WPARAM wParam, LPARAM lParam)
CEvent is used for thread synchronisation. I have created a member variable in the main dialog class that is declared as:
The event is used to stop the copy process if at any time during the copy process you have realised that you have specified wrong mask of input/output folders.
This program uses other people's work. I would like to acknowledge their efforts and thank them for their fantastic work.
- The main dialog class is derived from CResizeDlg by Robert Python.
- The main application icon and error/success icons in the list control are from the free iconset by the team of artists called Oxygen Team.
Points of Interest
While making the program, I discovered that
FindNextFile APIs (and their
CFileFind MFC wrapper) do not support multiple masks. I ended up searching for the files in the loop for each individual mask. You may enhance the program by searching for all files (*.*) and then filtering the files in the code.
The program can be enhanced in many ways. You may use a nice Cexif class written by Davide Pizzolato to get the Date Taken from the image file and use it for cataloguing.
You can also put a Image Previewer control on the form with a few lines of code.
- 8 Oct 2012: Version 1.0 posted
- 12 Feb 2013: Version 1.1. Enhanced to automatically scan for the images in new subfolders (next subfolders by name)
- 27 Sep 2013: Version 1.1. Rebuilt the application using Visual Studio 2012 - Windows XP (v110_xp) platform toolset
- 6 Oct 2014: Version 1.2. Added a new feature: Allow to select Copy or Move operation with an ability to overwrite existing files. Also added a status text indicating how many files were copied/moved during the last opration
Andrew has written his first program on a Z80 in Basic when he was only 13. It was long before first Windows was born. And when Windows 95 came into being Andrew loved the technology straight away. He taught himself C and C++ and became a devoted Windows Software Developer.