This article describes the methods used for development of the folder metadata editor.
Introduction
The need for a folder metadata editor arose when I wanted to manage a bunch of folders without organizing them in sub-directories. When searching online, I found that desktop.ini (and thus Windows Explorer) supports what I am looking for - just Microsoft did not provide a user interface for it. So this is where the folder metadata editor comes in. It provides a simple method to edit these metadata.
Background
Desktop.ini supports metadata for a folder if it contains the following:
[{F29F85E0-4FF9-1068-AB91-08002B27B3D9}]
Prop2=31,Title
Prop3=31,Subject
Prop4=31,Author
Prop5=31,Tag
Prop6=31,Comment
For reading and writing, the API functions GetPrivateProfileString
and WritePrivateProfileString
are used.
The folder metadata editor also supports simple argument parsing as well as localization.
Using the Code
The code is divided into these sub-name spaces:
- Configuration
- Argument parsing
- Localization
- Registration
- Dialogs
- Dialog forms
- Extended
ListBox
control - Form helper classes and icon extraction from resources
- Extensions
- Extension of
string
and StringCollection
classes
- Generic
- Loading/Writing of desktop.ini
- Generic helper classes
Configuration
Argument Parsing
Argument parsing is done by the ArgParser
class which makes use of the ParameterNames
class.
The ParameterNames.cs file contains the ParameterNames
class and the ParamConstants
enumeration.
The ParseParamConstants
function of the ParameterNames
class converts a command line argument like /dir into the proper ParamConstants
value ParamConstants.Dir
.
The actual argument parsing is done in the ArgParser
class. As this is a Windows.Forms
application, we do not have a string[] args
parameter in the main
function. So the ArgParser
class has a parameterless constructor and retrieves the command line arguments by using System.Environment.GetCommandLineArgs()
.
Registration
As the application is supposed to be used with folders, we need to register it in the Windows registry under HKEY_CLASSES_ROOT\Folder\shell. For this purpose, we create a new registry key FolderMetaData
. The default value of this key represents the text in the shortcut menu (when right-clicking a folder in Windows Explorer). Underneath this registry key, we create another registry key command
. The default value of the command
key then contains the full path to the application along with the path of the folder, e.g., C:\Program Files\FolderMetadata\FolderMetadata.exe /dir "%1".
To allow the application to be used when right-clicking the background of a folder, we create another registry entry under HKEY_CLASSES_ROOT\Directory\Background\shell. The procedure is identical to before. Only difference here is that we do not use %1
as parameter, but %V
.
When unregistering, the registry keys are identified by checking the default value of the command
registry key. This allows to remove the registry key even if has been created with a different language.
Registration and unregistration is done by the Registrator
class. You require administrative rights for these operations to succeed.
On the command line, use these commands to register or unregister:
- FolderMetadata.exe /register
- FolderMetadata.exe /unregister
Localization
Localization is handled by the LanguageConfigurator
class. In most cases, it will just use the language of the environment it is running on. You can, however, also change the language either by specifying the /lang command line parameter (e.g., /lang ja
for Japanese) or by selecting it by specifying command line parameter /lang select
. In order to allow the language selection dialog to display a list of all supported languages, the GetSupportedLanguages
function of the SupportedLanguages
class must include it.
Localization of a Windows.Forms
application is quite simple, if you deal with alphabetic languages. When dealing with non-alphabetic languages (e.g., Chinese and Japanese), this gets a little bit more of a challenge.
- Mnemonic support (the keyboard shortcut for a button, e.g.,
&Save
) would not be present - Handling simplified and traditional Chinese localization
As I wanted to keep the localization process simple, I leave most of it to the .NET Framework. So I set the Neutral language
property for the FolderMetadata
project to "English (United States)
". and created a separate resource file Strings.resx. This file contains all translations + the value ForceMnemonics
, which represents a bool
value and must be either true
or false
. The parsed result is accessible in the ForceShowMnemonics
property of the LanguageConfigurator
class.
For the Chinese localization, I created two resource files:
- Strings.zh.resx
- Strings.zh-TW.resx
This means that all users except those with a Taiwan Windows setting would see simplified Chinese characters. This, however, does not work for users from Hong Kong and Macao. So I added the function GetLanguageZH
that checks if it the language setting requires traditional Chinese display. If it does, it will change the language setting to zh-TW
. Now the user can also see traditional Chinese characters.
Dialogs
Translating Dialogs
When having complex forms, it may be a good method to set the Localizable
and Language
properties of the forms. This allows to re-arrange controls for each language for example. This however makes editing the dialogs more difficult if you have many languages. This is why I decided against that approach and use a more hands-on approach: The use of TableLayoutPanel
and the support class ButtonAdjustor
to make the buttons have the same width.
Each form has a WndProc
override. In this overridden function, we check if the ForceShowMnemonics
property of the LanguageConfigurator
class is true
. If it is, it will call the ShowMnemonics
method of the WndProcOverrides
class, which ensures that the mnemonics are visible.
Help
The form FrmHelp
contains help in HTML format. It is also translated into the various languages and opens when the user does one of these things:
- Start the application without specifying any supported parameters (e.g., by double-click in Windows Explorer)
- Specifies the
/?
command line parameter
Controls
The ListBoxEx control
inherits from the ListBox
of Windows.Forms
. It provides some functions for loading values (which is used on the FrmMain
form) and moving selected items (which is used on the FrmManage
form).
Extensions
If you have not used extensions before, you missed out a very helpful .NET feature. Extensions allow you to add your own functions to classes. There is just one downside: You can only add instance functions, but not static
functions à la string.IsNullOrEmpty
.
Definition
public static class String
{
public static bool IsEmpty(this string s)
{
return (s.Length == 0);
}
}
Usage
using HKS.FolderMetadata.Extensions;
string s = "Hello";
if (s.IsEmpty())
{
}
Generic
Reading and Writing Desktop.ini
The functionality for reading and writing desktop.ini is in the Metadata
class. As this program is intended for the Windows platform, we can use the API functions GetPrivateProfileString
and WritePrivateProfileString
for reading and writing.
In desktop.ini, all metadata properties are single line texts. As there may be more than one person who is the author (e.g., the Beatles songs were always written by John Lennon and Paul McCartney), or you want to set more than one tag, we have to convert a single line into a list and vice versa.
The constructor of the Metadata
class expects the full path to the directory you want to edit the metadata. It will then assemble the full path to desktop.ini. The class has properties which are filled by the Load
method and written to the file by the Save
method.
History
- 3rd January, 2021
- 15th July, 2021
- 24th February, 2024
- v 2.0.0
- Allow right-click on folder background to start application
- Added icon to shortcut menu