Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add Ellipsis to a Path in a WinForms Program without Win32 API call (revisited)

Tags:

c#

.net-4.0

I was searching for a way to insert an ellipsis in a C# path, and found an answer here on stackoverflow: C# Path Ellipsis without Win32 API call

Using the RTM versions of VS2010 and .Net 4.0, I was unable to get the suggested method to work. I searched the 'Net and found example code that uses the same method, but it failed in the same way.

You can see the string I'm trying to shorten in my code below.

After calling the MeasureText method, both the input string (OriginalName) and the output string (ellipsisedName) look like this:

d:\abcd\efgh\ijkl\mnop\qrst\...\test.txt\0F\GHIJ\KLMN\OPQR\STIV\WXYZ\test.txt

Two problems:

1) The resulting string is narfed (the path is truncated as expected, but is followed by what looks like a C-style terminating null and a chunk of the original path).

2) My original string is changed to be identical to the output string.

Am I doing something wrong?

namespace WindowsFormsApplication2 {
   public partial class Form1 : Form {
      public Form1()
      {
         InitializeComponent();

         string OriginalPath = @"d:\abcd\efgh\ijkl\mnop\qrst\uvwx\yzAB\CDEF\GHIJ\KLMN\OPQR\STIV\WXYZ\test.txt";
         string ellipsisedPath = OriginalPath;

         Size proposedSize = new Size(label1.Width, label1.Height);

         TextRenderer.MeasureText(ellipsisedPath, label1.Font, proposedSize, TextFormatFlags.ModifyString | TextFormatFlags.PathEllipsis);
      }
   }
}
like image 565
casterle Avatar asked Apr 14 '10 19:04

casterle


1 Answers

Holy moly, you've found a whopper of a bug. The P/Invoke used inside the TextRenderer class that calls DrawTextEx() is borked. That API function is writing back into the string, which it is allowed to do since the cchText argument is a LPTSTR, not a LPCTSTR. That destroys the .NET string content for both variables because the string is interned.

The bug isn't specific to .NET 4.0, I see it wrong in the ReferenceSource for .NET 3.5 SP1 as well and can repro it on VS2008. The trouble is in the internal WindowsGraphics.MeasureText function. You can report the bug at connect.microsoft.com.

A possible workaround is to alter the string so it gets copied and can't affect the original:

  string ellipsisedPath = OriginalPath + '\0';

But the better workaround in this case is to simply not pass the ModifyString option, it serves no purpose. Which is safer too, there is still a possibility of destroying the garbage collected heap with the first workaround. The fix for Microsoft is similarly simple, it should just mask out the ModifyString option. It is documented to have no effect.

like image 108
Hans Passant Avatar answered Sep 23 '22 00:09

Hans Passant