ShellCtrls2 v1.03
One of the many GUI classes I have developed and published on my web site is
CFileTreeCtrl. This is a
implementation from first principles of a tree control similar to the left hand
side of Windows Explorer. Because it was implemented with custom code, it has diverged
from the tree control shown in Windows Explorer in recent versions of Windows.
In addition, some
features in CFileTreeCtrl such as network enumeration no longer work in recent versions
of Windows. In addition It would be nice to have a list control implementation
similar to the right hand side of Windows Explorer. As of Visual Studio 2008 Service
Pack 1, two classes became available which implemented this functionality using
MFC. They are called CMFCShellTreeCtrl and CMFCShellListCtrl. I've recently taken
a look at these two classes, but I wanted to bring forward all the functionality
of CFileTreeCtrl in an implementation which provides better integration with the
shell. I also took inspiration and ideas from the following codeproject articles:
https://www.codeproject.com/Articles/1073213/Extending-MFC-shell-controls-functionality
and https://www.codeproject.com/Articles/2271/ShellFolderTree.
The result of all this work is ShellCtrls2.
The classes provided are:
CPIDL which provides a RAII class wrapper for a LPITEMIDLIST aka PIDLs.
PIDLs are identifiers which the Windows shell uses to identify all objects which
make up the Shell namespace. This class is based on the PIDL class provided by Oz
Solomon with WndTabs extension for Visual C++
6.0 but reimplemented using modern C++ 11 idioms.
CShellItemInfo2 This class is what
is stored in the item data for each item in the tree control or list control
CShellTreeCtrl2 This class is an improved version of the built-in MFC class
CMFCShellTreeCtrl
CShellListCtrl2 This class is an improved version of
the built-in MFC class CMFCShellListCtrl
The demo application included in the download exercises all the functionality
of each of the classes. A screen capture of the sample app running is as follows:

Features
- CShellTreeCtrl2 by default derives from CTreeCtrl and can be created using
the same mechanisms.
- CShellListCtrl2 by default derives from CMFCListCtrl and uses that class
to provide sorting functionality and custom header functionality when the control is in details
mode.
- Both CShellTreeCtrl2 and CShellListCtrl2 uses the system image list for
the icons for folders and files.
- Can have multiple instances of each control active at one time.
- CShellTreeCtrl2 can optionally allows files to be displayed as well as folders.
- CShellListCtrl2 by default allows files to be displayed but can be changed
at runtime to only display folders.
- Integrates with the shell to allow any item's default shell verb or properties
page to be displayed.
- The tree control preserves selection state of items across refreshes and
optionally allows files to be displayed.
- The tree control can optionally show the root item or not. In the screen
capture above, this would correspond to showing or hiding the "Desktop"
node in the tree control.
- The tree control can optionally show only items below a specific root folder.
- The tree control maintains a back forward item stack which client code can
take advantage of.
- Both the tree and list controls can show different icons for shared folders
and linked items, different colors for encrypted and compressed items, can customize
the drives, folders and file types to be displayed and supports multiple filename
masks.
- Both the tree and list controls support the shell context menu for items
and the list control supports opening a folder in the control itself.
- Similar to the "Extending MFC shell controls functionality" CodeProject
article, both controls support storing item data and the tree control supports
keeping items on node collapse and expansion and contraction of all nodes.
- Provides a full set of keyboard accelerators similar to Windows Explorer.
- Almost all of the functionality of both controls are implemented in virtual
functions making it easy to customize the behavior at runtime. In particular
the shell enumeration logic implemented by both controls has been carefully
arranged into easy to replace virtual functions.
- Similar to the built-in MFC classes, both controls can be tied together
so that changing folder in one will auto update in the other. The sample program
include in the download implements this concept using a simple MFC splitter
window.
- Unlike the MFC classes, ShellCtrls2 uses built in MFC, ATL and custom RAII
classes such as CPIDL, CMenu and CComPtr to avoid resource and memory leaks.
In fact the author detected a number of code paths in the built in MFC classes
which could cause resource and memory leaks.
- Both the tree and list controls support an "Auto Refresh" feature
where any file system changes are detected for the current folder and automatically refreshed.
- Unicode enabled and all code compiles cleanly at warning level 4.
- The code is /analyze clean and has been compiled using Clang-Tidy.
Usage
- To use CShellTreeCtrl2, include "ShellTreeCtrl2.cpp / h" in your
project and #include "ShellTreeCtrl2.h" in the module you want to
instantiate it in. You can use the usual MFC ways of hooking up the class. You
can also create the control dynamically by calling its parent classes CTreeCtrl::Create
method.
- To use CShellListCtrl2, include "ShellListCtrl2.cpp / h" in your
project and #include "ShellListCtrl2.h" in the module you want to
instantiate it in. You can use the usual MFC ways of hooking up the class. You
can also create the control dynamically by calling its parent classes CMFCListCtrl::Create
method.
- You will also need to copy the IDR_SHELLCTRLS2_POPUP_NOTHING_SELECTED menu
resource, associated ID_SHELLCTRLS2_* identifiers and IDS_SHELLCTRLS2* string
resources from the sample app's rc file into your applications rc file.
- Note that the code has been developed using Visual Studio 2019 and probably
will not compile on earlier versions of Visual Studio.
Copyright
- You are allowed to include the source code in any product (commercial, shareware,
freeware or otherwise) when your product is released in binary form.
- You are allowed to modify the source code in any way you want except you
cannot modify the copyright details at the top of each module.
- If you want to distribute source code with your application, then you are
only allowed to distribute versions released by the author. This is to maintain
a single distribution point for the source code.
History
v1.03 (4 June 2023)
- Updated copyright details.
- Reworked CShellListCtrl2::OnGetItemText to use IShellItem2.
- Reworked CShellListCtrl2::OnCompareItems to use IShellItem2.
- Reworked the logic in CShellListCtrl2::OnCompareItems to behave more
similar to how Windows Explorer behaves.
v1.02 (23 April 2022)
- Updated copyright details
- Updated the code to use C++ uniform initialization for all variable
declarations.
v1.01 (17 December 2021)
- Updated copyright details
- Fixed more static code analysis warnings in the code.
v1.0 (25 July 2020)
Contacting the Author
PJ Naughter
Email: pjna@naughter.com
Web: http://www.naughter.com
4 June
2023