|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis article presents a practical example of a Shell Extension that I've recently implemented. I was showing travel photos to friends, and I wanted to show only the best photos in my folders. One possible solution was to use one of the great photo managers around but I wanted to work directly with the standard Explorer interface. The idea is really simple, add a new Rating column to the Folder View of Explorer under Windows XP. This new column can be used to sort the files (photos, MP3s ...) by the user defined rating and it works with the Photo Preview of Explorer, so I can show first the best photos. The side effect of this approach is that it is possible to sort the results of a Search by the Rating thus obtaining the best photos in a folder tree. This is an example of the extended Explorer view:
and these are the new entries in the context menu:
Table Of Contents
Shell ExtensionsThe Windows Shell has a powerful extension mechanism that gives the possibility to provide new functionalities and interaction capabilities to the Shell. The implementation of these extensions in C++ and COM was quite difficult, but a lot has changed with the introduction of .NET. (In the References section, I've reported some links.) This is a schema that explains the possible Shell Extensions that can be created and what is used by this article.
DebuggingThe debugging of Shell Extension with .NET is the same as that of COM (see this). It's just necessary to specify the Explorer.exe as the executable for the debugging session and set to 1 the HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer
This value tells the Explorer to create a separate process for each window and one for the Taskbar, easing the debugging of the extension. RegistrationThe registration process has an extension type specific part and the general part. The general part is mostly performed by the regasm.exe utility (invoked by VS.NET) that addresses all the COM-.NET connection. If the extension is intended to be installed on non-administrator accounts, it's important to register it under the Approved set of extensions: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved
It's sufficient to add a new string value to this key with the name as the curly braced GUID of the class and an optional description. To inspect the installed extension, there is the Autoruns utility by SysInternals. The extension specific registration can be performed directly by managed code using two special attributes #region Registration
[System.Runtime.InteropServices.ComRegisterFunctionAttribute()]
static void RegisterServer(String str1)
{
try
{
string keyname = "File Rating";
string guid = "{"+typeof(RatingColumnHandler).GUID.ToString()+"}";
RegistryKey rk,rk2;
rk = Registry.ClassesRoot.OpenSubKey(@"*\shellex\ContextMenuHandlers", true);
...
}
catch(Exception e)
{
}
}
[System.Runtime.InteropServices.ComUnregisterFunctionAttribute()]
static void UnregisterServer(String str1)
{
try
{
string keyname = "File Rating";
string guid = "{"+typeof(RatingColumnHandler).GUID.ToString()+"}";
RegistryKey rk;
rk = Registry.ClassesRoot.OpenSubKey(@"*\shellex\ContextMenuHandlers", true);
rk.DeleteSubKey(keyname, false);
...
}
catch(Exception e)
{
}
}
#endregion
ImplementationThe File Rating extension uses a Column Handler to add a new column to the Detailed view of Explorer, the column is registered for in the folders ("Folder/shellex/ColumnHandlers" in the registry's Classes root) and implemented through the interface I've decided to store the rating information of each folder into a .rating file where, in each line, there is the rating, a tab, and then the file name. This is the simplest solution, but there are some issues that I'll discuss in the future work. This file is cached by the Column Handler, and each time, it can be checked against changes using a timestamp. The user can change the ratings by editing directly the .rating file or better by using a new entry in the Context Menu associated with every file ("*/shellex/ContextMenuHandlers" in the registry's Classes root). Two interfaces, IShellExtInitThe method IContextMenuThis interface is used to obtain the effective menu for the selection of files involved in the operation ( The int IContextMenu.QueryContextMenu(HMenu hMenu, int iMenu,
int idCmdFirst, int idCmdLast, CMF uFlags)
{
int id = 1;
if ( (uFlags & (CMF.CMF_VERBSONLY|CMF.CMF_DEFAULTONLY|CMF.CMF_NOVERBS)) == 0 ||
(uFlags & CMF.CMF_EXPLORE) != 0)
{
HMenu submenu = ShellLib.Helpers.CreatePopupMenu();
Helpers.AppendMenu(submenu, MFMENU.MF_STRING|MFMENU.MF_ENABLED,
new IntPtr(idCmdFirst + id++), "Rating ++");
Helpers.AppendMenu(submenu, MFMENU.MF_STRING|MFMENU.MF_ENABLED,
new IntPtr(idCmdFirst + id++), "Rating --");
Helpers.AppendMenu(submenu, MFMENU.MF_STRING|MFMENU.MF_ENABLED,
new IntPtr(idCmdFirst + id++), "Zero Rating");
Helpers.AppendMenu(submenu, MFMENU.MF_STRING|MFMENU.MF_ENABLED,
new IntPtr(idCmdFirst + id++), "About");
Helpers.InsertMenu(hMenu, 5,
MFMENU.MF_BYPOSITION|MFMENU.MF_POPUP|MFMENU.MF_ENABLED,
submenu.handle, "File Rating");
}
return id;
}
ImprovementsThere are some issues about this extension, but they don't really prevent its usage.
ConclusionsThis short article presents here a practical example of shell extension that can be used to rate files like photos or audio files. I hope that it will be useful to someone. References
|
||||||||||||||||||||||