How to display abbreviated path names in .NET

.net, filenames, path

Solution

Display Abbreviated Paths using `TextRenderer`.`MeasureText`

I had the same dilemma as the OP in that I needed a solution for showing an abbreviated path without too much hassle so that my UI could easily show the main parts of a path. The final solution: Use `TextRenderer`'s `MeasureText` method like so:

public static string GetCompactedString(
   string stringToCompact, Font font, int maxWidth)
{
   // Copy the string passed in since this string will be
   // modified in the TextRenderer's MeasureText method
   string compactedString = string.Copy(stringToCompact);
   var maxSize = new Size(maxWidth, 0);
   var formattingOptions = TextFormatFlags.PathEllipsis 
                         | TextFormatFlags.ModifyString;
   TextRenderer.MeasureText(compactedString, font, maxSize, formattingOptions);
   return compactedString;
}

Important: Passing in a formatting option of `TextFormatFlags.ModifyString` actually causes the `MeasureText` method to alter the string argument (`compactedString`) to be a compacted string. This seems very weird since no explicit `ref` or `out` method parameter keyword is specified and strings are immutable. However, its definitely the case. I assume the string's pointer was updated via unsafe code to the new compacted string.

As another lessor note, since I want the compacted string to compact a path, I also used the `TextFormatFlags.PathEllipsis` formatting option.

I found it handy to make a small extension method on control so that any control (like TextBox's and Label's) can set their text to a compacted path:

public static void SetTextAsCompactedPath(this Control control, string path)
{
   control.Text = GetCompactedString(path, control.Font, control.Width);
}

Alternative Ways to Compact a Path:

There are home grown solutions to compact paths as well as some WinApi calls one can use.

PathCompactPathEx - Compacting a String Based on Desired String Length in Characters

You can use pinvoke to call `PathCompactPathEx` to compact a string based on the number of characters you wish to restrict it to. Note that this does not take into account font and how wide the string will appear on a screen.

Code Source PInvoke: http://www.pinvoke.net/default.aspx/shlwapi.pathcompactpathex

[DllImport("shlwapi.dll", CharSet=CharSet.Auto)]
static extern bool PathCompactPathEx(
   [Out] StringBuilder pszOut, string szPath, int cchMax, int dwFlags);

public static string CompactPath(string longPathName, int wantedLength)
{
   // NOTE: You need to create the builder with the 
   //       required capacity before calling function.
   // See http://msdn.microsoft.com/en-us/library/aa446536.aspx
   StringBuilder sb = new StringBuilder(wantedLength + 1);
   PathCompactPathEx(sb, longPathName, wantedLength + 1, 0);
   return sb.ToString();
}

Other Solutions

There are more solutions out there as well that involve regular expressions and smart parsing of paths to determine where to put ellipsis. These are a few I saw:

- Coding Horror: - Shortening Long File Paths

- CodeProject: - Auto Ellipsis

Problem

I have a fixed-length field I'd like to display path information in. I thought in .NET there is a method that will abbreviate long path names to fit in fixed length fields by inserting ellipsis, for example "......\myfile.txt". I can't for the life of me find this method.

Original source