Click here to Skip to main content
15,881,588 members
Articles / Programming Languages / C++
Article

Change File Extension Context Menu

Rate me:
Please Sign up or sign in to vote.
4.63/5 (15 votes)
7 May 2008CPOL5 min read 83.4K   918   29   22
An easy and flexible way to change file extensions.

Introduction

This article will present a Windows shell extension designed to change file extensions in a flexible and easy way. Using this extension the user can manage filenames and extensions in a separate manner.

By default, Explorer hides file extensions from the user, which is OK until there comes a need to change a file's extension. In Windows OS, a file extension determines the file type and the application which opens the selected file, but sometimes we find a file with an extensions that does not match the actual file content. One of the most common examples are text files made in UNIX-like operating systems. UNIX-like systems usually use Line feed character (0xAh) as a new line delimiter, as opposed to Windows's Carriage Return+Line feed character pair (0xDh 0xAh). Viewed in Windows's Notepad, UNIX-made *.txt files usually appear as a blob of text without proper line endings. For huge files, this makes text difficult to read, and makes it almost impossible to correct all line endings by hand. A quick fix is to open it in Wordpad, or to rename file extension from *.txt to *.rtf. Personally, I use the second option. Another example is well-known to Manga fans: the famous *.cbz files which are simply zipped images with an archive's extension changed from *.zip to *.cbz. The bottom line is, it is not convenient to change extensions for many files by hand.

The idea for this code also originated from the way filenames are handled in Windows XP. In Windows XP, when a file is selected for renaming, assuming that extensions are not hidden, both filename and extension parts are selected, and a user must highlight only the extension part to change it. And, it only works for a single file. In Vista, when both parts are visible, by default the name part is highlighted.

The Code

One of the articles that sparked an inspiration for this code was Shell Renamer, and the code core was taken from the article How to Use Submenus in a Context Menu Shell Extension, so it is recommended to read it first, as this article is built on top of it.

This code is compiled using Visual C++ 2005 Express edition, Platform SDK 2003 R2, WTL 8.0 and ResEdit, so anybody should be able to build the project.

Since this is a shell extension, the code uses a simple exception handling to prevent any undesired events that would crash the Windows Explorer. The renaming is done through the Win32 SHFileOperation function, and files are operated one at a time, so that Explorer can provide an "Undo" step for each an every of the processed files. To enable the "Undo" action in Explorer, the fFlags member is set to FOF_ALLOWUNDO. To format SHFILEOPSTRUCT properly, an extra terminating null '\0' must to be added to the filename buffer's end.

C++
SHFILEOPSTRUCT lpFileOp;
memset(&lpFileOp,0,sizeof(lpFileOp));

lpFileOp.hwnd=NULL;
lpFileOp.fFlags=FOF_ALLOWUNDO;
lpFileOp.wFunc=FO_RENAME;

fname+='\0';//add buffer-terminating null to old name
lpFileOp.pFrom=fname;

toname=splitter.drive+splitter.dir+splitter.filename+_T(".")+newext;
lpFileOp.pTo=toname;

if (0!=SHFileOperation(&lpFileOp)) {/*MSGBOX0("SHFileOperation failed");
    */return false;}

As a consequence of using SHFileOperation, an attempt to change the extension of a shortcut results in target path resolving, and the rename operation is made on the target. Another strange thing in that case is that dialog is not modal in respect to the Explorer owner window.

By default, the file extension of the first right-clicked file is selected as a new extension. Extensions are displayed in the shell menu entry in the uppercase, however, the actual string case is left for the user to decide, since there are some programs where the user can choose between an upper and lowercase extension when saving files (eg. mp3 and MP3).

New extensions are checked for invalid characters, and default Windows Explorer behaviour is simulated:

If you don't see any balloon tip, look under registry key HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced and set the DWORD value EnableBalloonTips to 1 to enable system-wide balloon tips.

The position of menu entry in the shell context menu depends solely on the alphabetic order of string value in the *.rgs file. For this shell extension, a project's CLSID (A5096FA1-32DC-4392-A829-445558F0F4B5) was used to position the menu entry somewhere in the middle of the shell context menu:

If the string value on the right side was, for example, AAAAAAAAAA_go_to_the_top__, the menu entry would be positioned at the top of the shell context menu:

C++
NoRemove *
{
    NoRemove ShellEx
    {
        NoRemove ContextMenuHandlers
        {
            {A5096FA1-32DC-4392-A829-445558F0F4B5} = s '{AAAAAAAAAA_go_to_the_top__}'
        }
    }
}

You also need to match the CLSID-entry in the *.rgs file:

C++
NoRemove CLSID
{
    ForceRemove { AAAAAAAAAA_go_to_the_top__} = s 'ChangeExtMenuExt Class'
    {
        InprocServer32 = s '%MODULE%'
        {
            val ThreadingModel = s 'Apartment'
        }
    }
}

GUI Layout and XP Style Awareness

The menu entry has an easy-to-spot menu bitmap inserted, to provide a quick visual landmark.

Another important issue with this shell extension, since it is dialog-based, is enabling the WinXP theme for visual consistency. In order to have a dialog which has the XP theme enabled, it was necessary to set the following values in stdafx.h before any of the #includes:

C++
#define VC_EXTRALEAN //necessary
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x501
#endif
#define _ATL_APARTMENT_THREADED

#define ISOLATION_AWARE_ENABLED 1 //XP style awareness

These snapshots demonstrate the difference in appearance:

Theme-aware:Not theme-aware:

The XP theme awareness topic is further discussed in articles The Complete Idiot's Guide to Writing Shell Extensions - Part II, Applying Windows XP Visual Styles to Applications and Using Windows XP Visual Styles on MSDN.

To provide a user with some nice and interactive GUI, instead of a "Help" button, I used the WTL CBitmapHyperLink class.

BEWARE! — if you don't put any HTML help file (*.chm) in the debug version DLL's directory (where hlppath variable points to), you will get a nasty Explorer crash in one of the CBitmapHyperlink's ASSERTs. In the release version this doesn't happen.

Instead of an "About" button, I decided to put a nice clickable icon. I leave it as a reader's excercise to implement a more fancy owner-drawn button.

Recommended Reading

The Complete Idiot's Guide to Writing Shell Extensions by Michael Dunn.
New Graphical Interface: Enhance Your Programs with New Windows XP Shell Features by Dino Esposito (MSDN, URL may change).

Bugs and Issues

Please report any issues and bugs you find in this article's message board.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Croatia Croatia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionNoob Trying to Compile Pin
Member 1388856331-Dec-18 22:51
Member 1388856331-Dec-18 22:51 
Questioncode cann't compile under vs2010 Pin
jiazhiqiang23-Jul-14 22:51
jiazhiqiang23-Jul-14 22:51 
AnswerRe: code cann't compile under vs2010 Pin
T800G15-Sep-14 10:42
T800G15-Sep-14 10:42 
QuestionDoesnt work Pin
ravaldhruv00716-Jan-14 8:51
ravaldhruv00716-Jan-14 8:51 
AnswerRe: Doesnt work Pin
T800G20-Jan-14 5:14
T800G20-Jan-14 5:14 
BugInstall not fully proper for Win64 Pin
Kelly Brookman12-May-13 11:47
Kelly Brookman12-May-13 11:47 
GeneralRe: Install not fully proper for Win64 Pin
T800G13-May-13 5:00
T800G13-May-13 5:00 
GeneralRe: Install not fully proper for Win64 Pin
Kelly Brookman13-May-13 8:30
Kelly Brookman13-May-13 8:30 
QuestionLatest version Pin
Pat Kujawa20-Jun-12 12:15
Pat Kujawa20-Jun-12 12:15 
AnswerRe: Latest version Pin
T800G21-Jun-12 6:25
T800G21-Jun-12 6:25 
GeneralRe: Latest version Pin
Pat Kujawa28-Jun-12 10:32
Pat Kujawa28-Jun-12 10:32 
QuestionChange File Extension Install Pin
patara087-Jul-11 20:48
patara087-Jul-11 20:48 
GeneralAbout: Change File Extension Shell Menu Pin
ifiult16-Jan-10 10:05
ifiult16-Jan-10 10:05 
GeneralWorks with Windows7 x64 [modified] Pin
T800G21-Jan-09 7:39
T800G21-Jan-09 7:39 
QuestionNoob question--how do I install? Pin
sti311-Sep-08 8:50
sti311-Sep-08 8:50 
AnswerRe: Noob question--how do I install? [modified] Pin
T800G12-Sep-08 6:43
T800G12-Sep-08 6:43 
GeneralRe: Noob question--how do I install? Pin
bambi9413-Jan-09 7:13
bambi9413-Jan-09 7:13 
GeneralRe: Noob question--how do I install? Pin
T800G13-Jan-09 8:17
T800G13-Jan-09 8:17 
GeneralRe: Noob question--how do I install? Pin
bambi9413-Jan-09 8:22
bambi9413-Jan-09 8:22 
GeneralRe: Noob question--how do I install? Pin
T800G13-Jan-09 13:30
T800G13-Jan-09 13:30 
You need ATL (and some mfc) headers and libraries from the Platform SDK 2003 R2 or from the Windows DDK(for XP). These are the only ways to get ATL (older version 3, but works with WTL just fine) without spitting $$$$$ for VC Pro, so get it all while you still can.
Someone in M$ probably realized that using these sources ,apart from MFC, you can make anything as with VC Pro but for 0$, so they removed ATL and MFC from newer SDKs.
You can try to install on some other machine and just copy the neccesary folders to avoid all those installation messing stuff.

You can follow instructions here and here how to setup this combo. If you are using VC2008 express you need to before setting up WTL (get it at wtl.sourceforge.net), open setup80x.js in notepad and change all lines from ...\\VCExpress\\8.0\\Setup... to ...\\VCExpress\\9.0\\Setup... so it can "install" wtl wizard into VC correctly.
For resource editing I use ResEdit and for toolbar bitmaps ToolbarEditor (or on CodeProject).
I haven't used VC2008 to build since everything works fine for me with VC2005 (even though it's a bit laggy IDE), so all I can advise is googleing and reading first so you get fully informed how to make it all work correctly (but get that SDK and DDK now, nobody knows for how long they'll be available). It can take some time to carefully set up everything, but it's worth it.
GeneralEdit control validation Pin
yarp8-May-08 2:29
yarp8-May-08 2:29 
GeneralRe: Edit control validation [modified] Pin
T800G8-May-08 8:36
T800G8-May-08 8:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.