<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Truncate File Path with Ellipsis</title>
	<atom:link href="http://www.csharp411.com/truncate-file-path-with-ellipsis/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/</link>
	<description>C# Information, Code, Tips and News</description>
	<lastBuildDate>Sat, 24 Jul 2010 01:26:51 -0400</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: P Mills</title>
		<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/comment-page-1/#comment-5479</link>
		<dc:creator>P Mills</dc:creator>
		<pubDate>Tue, 11 May 2010 05:14:03 +0000</pubDate>
		<guid isPermaLink="false">http://www.mini-tools.com/at2/csharp/wordpress/truncate-file-path-with-ellipsis/#comment-5479</guid>
		<description>Just found these comments while trying to figure out a way to get the actual characters of the string that gets drawn when using the DrawString method and a StringFormat specifying the EllipsisPath trimming option.

I&#039;m doing some owner-draw logic for a listview that is looping through a list of strings and identifying matches for a regular expression search, and then drawing the strings a piece at a time, highlighting the search matches.

The original draw logic used DrawString and the EllipsisPath trimming option, and I needed to get the actual text of the string being drawn so I could do the regex match on the ellipsified string, since that is the string I will be drawing (the ellipsis might hide some of the matches, which requires some special handling of the displayed output).

In any case, I found this thread and couldn&#039;t wait to try the code, since it seemed the exact answer I was looking for.

I discovered that, in VB.Net, the results of modifying the first argument string to the TextRenderer.MeasureText method resulted in the new, shorter string being terminated with a a null embedded in the string.  I used the following code in VB.Net to extract the new string:

&#039; First get the ellipsified string in strTrunc

Dim strTrunc As New String(strOutput)

TextRenderer.MeasureText(strTrunc, Font, New Size(Bounds.Width, Bounds.Height), TextFormatFlags.ModifyString Or TextFormatFlags.PathEllipsis)

&#039;Now split out the result to make it usable in VB.Net

strTrunc = strTrunc.Split(Chr(0))(0)

This is working pretty well in my code, but I have discovered that there are slight differences in the actual resulting character-strings between these two methods:

1) DrawString with EllipsisPath flag:

sf.Trimming = System.Drawing.StringTrimming.EllipsisPath

Graphics.DrawString(strOut, Font, Brush, Bounds, sf)

2) TextRenderer method:

TextRenderer.MeasureText(strTrunc, fFont, New Size(rBounds.Width, rBounds.Height), TextFormatFlags.ModifyString Or TextFormatFlags.PathEllipsis)

The results are quite similar, but not identical.  

Here is an example of a string in my test data, with the resulting ellipsified text from both methods above:

Original string:

&quot;     A       2,991,428 E:\Users\plmills\Music\iTunes\iTunes Music\Al Petteway\Midsummer Moon1 The Red Haired Boy.mp3&quot;

Ellipsified text using DrawString &amp; EllipsisPath (for a specific font and bounding rectangle):

&quot;     A       2,991,428 E:\Users\plmills\Music\iTunes\iTunes Music\Al...1 The Red Haired Boy.mp3&quot;

Ellipsified text using TextRenderer &amp; PathEllipsis flag (with the same font and bounding rectangle):

&quot;     A       2,991,428 E:\Users\plmills\Music\iTunes\iTunes Mus...1 The Red Haired Boy.mp3&quot;

Slightly different, and not even the same number of characters in the result, which is odd since I&#039;m using a mono-spaced font for the measuring.

Just thought you might find these results of interest.  Thanks for the code in this thread - very helpful for getting me over a tough spot.</description>
		<content:encoded><![CDATA[<p>Just found these comments while trying to figure out a way to get the actual characters of the string that gets drawn when using the DrawString method and a StringFormat specifying the EllipsisPath trimming option.</p>
<p>I'm doing some owner-draw logic for a listview that is looping through a list of strings and identifying matches for a regular expression search, and then drawing the strings a piece at a time, highlighting the search matches.</p>
<p>The original draw logic used DrawString and the EllipsisPath trimming option, and I needed to get the actual text of the string being drawn so I could do the regex match on the ellipsified string, since that is the string I will be drawing (the ellipsis might hide some of the matches, which requires some special handling of the displayed output).</p>
<p>In any case, I found this thread and couldn't wait to try the code, since it seemed the exact answer I was looking for.</p>
<p>I discovered that, in VB.Net, the results of modifying the first argument string to the TextRenderer.MeasureText method resulted in the new, shorter string being terminated with a a null embedded in the string.  I used the following code in VB.Net to extract the new string:</p>
<p>' First get the ellipsified string in strTrunc</p>
<p>Dim strTrunc As New String(strOutput)</p>
<p>TextRenderer.MeasureText(strTrunc, Font, New Size(Bounds.Width, Bounds.Height), TextFormatFlags.ModifyString Or TextFormatFlags.PathEllipsis)</p>
<p>'Now split out the result to make it usable in VB.Net</p>
<p>strTrunc = strTrunc.Split(Chr(0))(0)</p>
<p>This is working pretty well in my code, but I have discovered that there are slight differences in the actual resulting character-strings between these two methods:</p>
<p>1) DrawString with EllipsisPath flag:</p>
<p>sf.Trimming = System.Drawing.StringTrimming.EllipsisPath</p>
<p>Graphics.DrawString(strOut, Font, Brush, Bounds, sf)</p>
<p>2) TextRenderer method:</p>
<p>TextRenderer.MeasureText(strTrunc, fFont, New Size(rBounds.Width, rBounds.Height), TextFormatFlags.ModifyString Or TextFormatFlags.PathEllipsis)</p>
<p>The results are quite similar, but not identical.  </p>
<p>Here is an example of a string in my test data, with the resulting ellipsified text from both methods above:</p>
<p>Original string:</p>
<p>"     A       2,991,428 E:\Users\plmills\Music\iTunes\iTunes Music\Al Petteway\Midsummer Moon1 The Red Haired Boy.mp3&#8243;</p>
<p>Ellipsified text using DrawString &amp; EllipsisPath (for a specific font and bounding rectangle):</p>
<p>"     A       2,991,428 E:\Users\plmills\Music\iTunes\iTunes Music\Al&#8230;1 The Red Haired Boy.mp3&#8243;</p>
<p>Ellipsified text using TextRenderer &amp; PathEllipsis flag (with the same font and bounding rectangle):</p>
<p>"     A       2,991,428 E:\Users\plmills\Music\iTunes\iTunes Mus&#8230;1 The Red Haired Boy.mp3&#8243;</p>
<p>Slightly different, and not even the same number of characters in the result, which is odd since I'm using a mono-spaced font for the measuring.</p>
<p>Just thought you might find these results of interest.  Thanks for the code in this thread &#8211; very helpful for getting me over a tough spot.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gary Montante</title>
		<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/comment-page-1/#comment-5461</link>
		<dc:creator>Gary Montante</dc:creator>
		<pubDate>Thu, 29 Apr 2010 23:41:12 +0000</pubDate>
		<guid isPermaLink="false">http://www.mini-tools.com/at2/csharp/wordpress/truncate-file-path-with-ellipsis/#comment-5461</guid>
		<description>Hi, Simon,

Thanks for your info.  Interesting url.

Did you experiment doing the example with and without using String.Copy?  Your comment &quot;Calling f.FullName.Trim() or MeasureText() or whatever will not modify the original f.FullName string&quot; suggests that you didn&#039;t.

When you do, you&#039;ll see that .MeasureText() appears to be a case of &quot;unmanaged code that deals with the memory locations directly and can mutate the string.&quot;  The circumstantial evidence looks like .MeasureText() did not allocate a new string and return a reference to it, but instead put a &quot;null&quot; into the original input string (&quot;argument exception, illegal characters path, null&quot;).

My conclusion is that this is screwy stuff and works in an unexpected, un-.Net manner.

But, ultimately the point was to fix some code that gave an exception.  

To do this, I re-read the .MeasureText() documentation, which didn&#039;t show me what I did wrong (I always assume that it was something I did wrong or didn&#039;t understand).  That didn&#039;t work.  

If I were still a professional programmer, I would try to examine the library code to see what it was actually doing, not what some documentation says it should be doing.  &quot;Go to disassembly&quot; didn&#039;t work (incidentally, I have found compiler bugs and library code bugs this way...) and I didn&#039;t want to take the time to use the excellent tool described at
http://en.csharp-online.net/Visual_Studio_Hacks%E2%80%94Hack_64:_Examine_the_Innards_of_Assemblies .

I guessed the problem was modification of the original string by .MeasureText() so I tried to create a second copy.  To do this, I &quot;played monkey&quot; by trying whatever I could think of (I originally used .Trim() which created a new copy only if it did something, otherwise it didn&#039;t; then forced .Trim() to do something, which worked but was unsatisfying; then played with StringBuilder, which worked; then liked and used the info about String.Copy).  Problem solved, work on something else.

I feel that whoever worked on the .MeasureText() did not take the time to create a function that played nicely with .Net strings, which could have easily been avoided by creating a separate playground for the underlying code, and would have saved us all a bunch of time.  

I&#039;m guessing the wrapper passes memory addresses to the underlying &quot;C++&quot; code, which uses the pointer to change memory directly.  Since there is no garbage collection in C++, this was a legimate way to use a character array and avoid a memory leak.

Sincerely,
Gary</description>
		<content:encoded><![CDATA[<p>Hi, Simon,</p>
<p>Thanks for your info.  Interesting url.</p>
<p>Did you experiment doing the example with and without using String.Copy?  Your comment "Calling f.FullName.Trim() or MeasureText() or whatever will not modify the original f.FullName string" suggests that you didn't.</p>
<p>When you do, you'll see that .MeasureText() appears to be a case of "unmanaged code that deals with the memory locations directly and can mutate the string."  The circumstantial evidence looks like .MeasureText() did not allocate a new string and return a reference to it, but instead put a "null" into the original input string ("argument exception, illegal characters path, null").</p>
<p>My conclusion is that this is screwy stuff and works in an unexpected, un-.Net manner.</p>
<p>But, ultimately the point was to fix some code that gave an exception.  </p>
<p>To do this, I re-read the .MeasureText() documentation, which didn't show me what I did wrong (I always assume that it was something I did wrong or didn't understand).  That didn't work.  </p>
<p>If I were still a professional programmer, I would try to examine the library code to see what it was actually doing, not what some documentation says it should be doing.  "Go to disassembly" didn't work (incidentally, I have found compiler bugs and library code bugs this way&#8230;) and I didn't want to take the time to use the excellent tool described at<br />
<a href="http://en.csharp-online.net/Visual_Studio_Hacks%E2%80%94Hack_64:_Examine_the_Innards_of_Assemblies" rel="nofollow">http://en.csharp-online.net/Visual_Studio_Hacks%E2%80%94Hack_64:_Examine_the_Innards_of_Assemblies</a> .</p>
<p>I guessed the problem was modification of the original string by .MeasureText() so I tried to create a second copy.  To do this, I "played monkey" by trying whatever I could think of (I originally used .Trim() which created a new copy only if it did something, otherwise it didn't; then forced .Trim() to do something, which worked but was unsatisfying; then played with StringBuilder, which worked; then liked and used the info about String.Copy).  Problem solved, work on something else.</p>
<p>I feel that whoever worked on the .MeasureText() did not take the time to create a function that played nicely with .Net strings, which could have easily been avoided by creating a separate playground for the underlying code, and would have saved us all a bunch of time.  </p>
<p>I'm guessing the wrapper passes memory addresses to the underlying "C++" code, which uses the pointer to change memory directly.  Since there is no garbage collection in C++, this was a legimate way to use a character array and avoid a memory leak.</p>
<p>Sincerely,<br />
Gary</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Simon</title>
		<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/comment-page-1/#comment-5460</link>
		<dc:creator>Simon</dc:creator>
		<pubDate>Thu, 29 Apr 2010 15:41:30 +0000</pubDate>
		<guid isPermaLink="false">http://www.mini-tools.com/at2/csharp/wordpress/truncate-file-path-with-ellipsis/#comment-5460</guid>
		<description>Re: Subsequently, .MeasureText() shortens f.FullName creating an &quot;illegal&quot; name for FileInfo.

Perhaps I am misunderstanding what you mean, but strings are immutable.  Calling f.FullName.Trim() or MeasureText() or whatever will not modify the original f.FullName string.  The only way to change f.FullName string is to assign it to a different string, but the original string remains unchanged.

The only time you need to use String.Copy in .NET is &quot;with unmanaged code that deals with the memory locations directly and can mutate the string.&quot;

http://stackoverflow.com/questions/520895/whats-the-use-of-system-string-copy-in-net</description>
		<content:encoded><![CDATA[<p>Re: Subsequently, .MeasureText() shortens f.FullName creating an "illegal" name for FileInfo.</p>
<p>Perhaps I am misunderstanding what you mean, but strings are immutable.  Calling f.FullName.Trim() or MeasureText() or whatever will not modify the original f.FullName string.  The only way to change f.FullName string is to assign it to a different string, but the original string remains unchanged.</p>
<p>The only time you need to use String.Copy in .NET is "with unmanaged code that deals with the memory locations directly and can mutate the string."</p>
<p><a href="http://stackoverflow.com/questions/520895/whats-the-use-of-system-string-copy-in-net" rel="nofollow">http://stackoverflow.com/questions/520895/whats-the-use-of-system-string-copy-in-net</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gary Montante</title>
		<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/comment-page-1/#comment-5456</link>
		<dc:creator>Gary Montante</dc:creator>
		<pubDate>Wed, 28 Apr 2010 05:28:41 +0000</pubDate>
		<guid isPermaLink="false">http://www.mini-tools.com/at2/csharp/wordpress/truncate-file-path-with-ellipsis/#comment-5456</guid>
		<description>You need to use

string truncatedPath = String.Copy(f.FullName.Trim());

You experienced the same error I did which I described extensively in my sample class.

In your case, .Trim() did not allocate a new string. Instead, it just returned a reference to the string f.FullName.  Subsequently, .MeasureText() shortens f.FullName creating an &quot;illegal&quot; name for FileInfo.

Brian Tyler&#039;s use of String.Copy() fixes the problem (thanks, Brian).  It creates a new string independent of FileInfo, which can be changed anyway you wish without messing up FileInfo.</description>
		<content:encoded><![CDATA[<p>You need to use</p>
<p>string truncatedPath = String.Copy(f.FullName.Trim());</p>
<p>You experienced the same error I did which I described extensively in my sample class.</p>
<p>In your case, .Trim() did not allocate a new string. Instead, it just returned a reference to the string f.FullName.  Subsequently, .MeasureText() shortens f.FullName creating an "illegal" name for FileInfo.</p>
<p>Brian Tyler's use of String.Copy() fixes the problem (thanks, Brian).  It creates a new string independent of FileInfo, which can be changed anyway you wish without messing up FileInfo.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Greg</title>
		<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/comment-page-1/#comment-5452</link>
		<dc:creator>Greg</dc:creator>
		<pubDate>Mon, 26 Apr 2010 15:05:53 +0000</pubDate>
		<guid isPermaLink="false">http://www.mini-tools.com/at2/csharp/wordpress/truncate-file-path-with-ellipsis/#comment-5452</guid>
		<description>In the above post, the formatting left out a null character &lt;code&gt;&lt;/code&gt; between the trucated file name and My Documents, so if html tags can be placed here it should read

&lt;code&gt;C:\\Documents an…\\Daffy_Duck.xml\My Documents\\testing\\Daffy_Duck.xml&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>In the above post, the formatting left out a null character <code></code> between the trucated file name and My Documents, so if html tags can be placed here it should read</p>
<p><code>C:\\Documents an…\\Daffy_Duck.xml\My Documents\\testing\\Daffy_Duck.xml</code></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Greg</title>
		<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/comment-page-1/#comment-5451</link>
		<dc:creator>Greg</dc:creator>
		<pubDate>Mon, 26 Apr 2010 15:02:40 +0000</pubDate>
		<guid isPermaLink="false">http://www.mini-tools.com/at2/csharp/wordpress/truncate-file-path-with-ellipsis/#comment-5451</guid>
		<description>Replying in reference to &quot;another mike&quot;&#039;s comment above converning the strange string when using the Measuretext method to truncate a string, I created the following extension method for the FileIno class to return the truncated path:

public static string TruncatedFullName(this FileInfo f, System.Drawing.Font font, int width)
        {
        string truncatedPath = (String)f.FullName.Trim();
        System.Windows.Forms.TextRenderer.MeasureText(truncatedPath, font, new System.Drawing.Size(Convert.ToInt32(width), Convert.ToInt32(font.GetHeight())), System.Windows.Forms.TextFormatFlags.ModifyString &#124; System.Windows.Forms.TextFormatFlags.PathEllipsis);
        return truncatedPath;
        }

Before the MeasureText method is called, both the f.FullName and truncatedPath variables are correctly displaying the path to the file, as verified by the watch window

C:\Documents and Settings\myname\My Documents\testing\Daffy_Duck.xml

After the MeasureText method is called, I receive the error

&#039;f.FullName&#039; threw an exception of type &#039;System.ArgumentException&#039;

and the trucatedPath variable reads

C:\\Documents an...\\Daffy_Duck.xml\\My Documents\\testing\\Daffy_Duck.xml

which is strange, because when I view the reported value of truncatedPath, it reads

C:\\Documents an...\\Daffy_Duck.xml

as expected. I am assuming the nullcharacter in the string is what is doing the truncating of the value in this instance. What also surpriss me is the the value of the f.FullName property of the FileInfo object is also changing. 

I have no solution for this problem, and any help would be appreciated. Thanks</description>
		<content:encoded><![CDATA[<p>Replying in reference to "another mike"'s comment above converning the strange string when using the Measuretext method to truncate a string, I created the following extension method for the FileIno class to return the truncated path:</p>
<p>public static string TruncatedFullName(this FileInfo f, System.Drawing.Font font, int width)<br />
        {<br />
        string truncatedPath = (String)f.FullName.Trim();<br />
        System.Windows.Forms.TextRenderer.MeasureText(truncatedPath, font, new System.Drawing.Size(Convert.ToInt32(width), Convert.ToInt32(font.GetHeight())), System.Windows.Forms.TextFormatFlags.ModifyString | System.Windows.Forms.TextFormatFlags.PathEllipsis);<br />
        return truncatedPath;<br />
        }</p>
<p>Before the MeasureText method is called, both the f.FullName and truncatedPath variables are correctly displaying the path to the file, as verified by the watch window</p>
<p>C:\Documents and Settings\myname\My Documents\testing\Daffy_Duck.xml</p>
<p>After the MeasureText method is called, I receive the error</p>
<p>'f.FullName' threw an exception of type 'System.ArgumentException'</p>
<p>and the trucatedPath variable reads</p>
<p>C:\\Documents an&#8230;\\Daffy_Duck.xml\\My Documents\\testing\\Daffy_Duck.xml</p>
<p>which is strange, because when I view the reported value of truncatedPath, it reads</p>
<p>C:\\Documents an&#8230;\\Daffy_Duck.xml</p>
<p>as expected. I am assuming the nullcharacter in the string is what is doing the truncating of the value in this instance. What also surpriss me is the the value of the f.FullName property of the FileInfo object is also changing. </p>
<p>I have no solution for this problem, and any help would be appreciated. Thanks</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Brian Tyler</title>
		<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/comment-page-1/#comment-5371</link>
		<dc:creator>Brian Tyler</dc:creator>
		<pubDate>Fri, 29 Jan 2010 15:36:17 +0000</pubDate>
		<guid isPermaLink="false">http://www.mini-tools.com/at2/csharp/wordpress/truncate-file-path-with-ellipsis/#comment-5371</guid>
		<description>@Gary Montante Thanks; here is the functionized version:

using System.Drawing;
using System.Windows.Forms;

public string TruncateFileName( string fileName, TextBox textBox )
    {
      string truncName = String.Copy(fileName);

      TextRenderer.MeasureText(
        truncName,
        textBox.Font,
        new Size(textBox.Width, textBox.Height),
        TextFormatFlags.ModifyString &#124; TextFormatFlags.PathEllipsis);

      return truncName;
    }</description>
		<content:encoded><![CDATA[<p>@Gary Montante Thanks; here is the functionized version:</p>
<p>using System.Drawing;<br />
using System.Windows.Forms;</p>
<p>public string TruncateFileName( string fileName, TextBox textBox )<br />
    {<br />
      string truncName = String.Copy(fileName);</p>
<p>      TextRenderer.MeasureText(<br />
        truncName,<br />
        textBox.Font,<br />
        new Size(textBox.Width, textBox.Height),<br />
        TextFormatFlags.ModifyString | TextFormatFlags.PathEllipsis);</p>
<p>      return truncName;<br />
    }</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gary Montante</title>
		<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/comment-page-1/#comment-4566</link>
		<dc:creator>Gary Montante</dc:creator>
		<pubDate>Thu, 30 Apr 2009 10:04:39 +0000</pubDate>
		<guid isPermaLink="false">http://www.mini-tools.com/at2/csharp/wordpress/truncate-file-path-with-ellipsis/#comment-4566</guid>
		<description>Here is a sample class that encapsulates an ellipsis textbox.

Sample usage:

EllipsisTextBox txtBox = new EllipsisTextBox();
txtBox.EllipsisType =
    EllipsisTextBox.EllipsisLocation.Path;
txtBox.Text = 
    @&quot;C:\directory\subdirectory\filename.ext&quot;;
Depending on the width of the textbox, it will display something like &quot;C:\di...\filename.ext&quot;.

However,
string boo = txtBox.Text;       yields
  boo == @&quot;C:\directory\subdirectory\filename.ext&quot;, the original string, NOT the truncated string.

The sample textbox can be dragged onto a form, and assigned EllipsisType in the Properties window.

The sample also demonstrates a &quot;bug&quot; with String.Trim().
=================================================

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace MyProject
{
    /// 
    /// Creates a TextBox with built-in ellipsis control.
    /// (1) Specify EllipsisTextBox.EllipsisType
    ///       (e.g., = EllipsisLocation.Path)
    /// (2) Put text into the textbox (e.g., EllipsisTextBox.Text = @&quot;c:\directory\file.txt&quot;)
    /// The displayed text is the original text modified by the EllipsisType.
    ///     (e.g., &quot;...\file.txt&quot; if that&#039;s what fills the small textbox)
    /// The string returned by EllipsisTextBox.Text is the original text,
    ///    which may differ from what is showing in the textbox.
    /// 
    public partial class EllipsisTextBox : System.Windows.Forms.TextBox
    {
        private string fullText;
        private string ellipsisText;
        private EllipsisLocation ellipsisLocation =  EllipsisLocation.None;
        private TextFormatFlags ellipsisTextFormatFlag = 0;

        public enum EllipsisLocation { Path, Word, End, None };

        /// 
        ///   Define where ellipsis appears 
        /// 
        /// TextFormatFlags.PathEllipsis,TextFormatFlags.EndEllipsis,TextFormatFlags.WordEllipsis
        /// 
        [System.ComponentModel.Description(&quot;Define where ellipsis appears in the string&quot;)]
        [System.ComponentModel.DefaultValue(EllipsisLocation.None)]
        public EllipsisLocation EllipsisType
        {
            get { return ellipsisLocation; }
            set {
                ellipsisLocation = value;
                switch (value)
                {
                    case EllipsisLocation.End:
                        ellipsisTextFormatFlag = TextFormatFlags.EndEllipsis; break;
                    case EllipsisLocation.None:
                        ellipsisTextFormatFlag = 0; break;
                    case EllipsisLocation.Path:
                        ellipsisTextFormatFlag = TextFormatFlags.PathEllipsis; break;
                    case EllipsisLocation.Word:
                        ellipsisTextFormatFlag = TextFormatFlags.WordEllipsis; break;
                    default:
                        ellipsisTextFormatFlag = 0;
                        ellipsisLocation = EllipsisLocation.None;
                        break;
                }
            }
        }

        /// 
        /// Modify/Get text of an EllipseTextBox.
        /// Get: returns the original, unmodified assigned text.
        /// Set: saves a copy of the new text, but displays
        ///    the new text as modified by EllipsisType.
        /// 
        public new string Text 
        {
            get
            {
                return fullText;
            }
            set
            {
                // Ensure we get a trimmed copy of the original string,
                //   NOT a reference to the original string.
                // NOTE: seems to be a &quot;bug&quot; in .Trim() - returns a reference
                //       to the original string if .Trim() does not need to modify
                //       the original string, otherwise, it returns a reference to a new string.
                //       We could use...
                //         string truncText = (new StringBuilder(value)).ToString();
                //       but drop the  below to see the .Trim() anomaly!
                fullText = (value + &quot; &quot;).Trim();    //want a new copy, not a reference to value!

                // Change copy of fullText to ellipsis truncated form
                //truncText = (new StringBuilder(value)).ToString();
                ellipsisText = (fullText + &quot; &quot;).Trim();  //want a new copy to modify, else fullText would be modified, too!
                TextRenderer.MeasureText(ellipsisText, this.Font, new Size(this.Width, this.Height), TextFormatFlags.ModifyString &#124; ellipsisTextFormatFlag);
                base.Text = ellipsisText;
            }
        }

        public EllipsisTextBox() : base()
        {
            fullText = &quot;&quot;;
            base.Text = &quot;&quot;;
        }
    }
}</description>
		<content:encoded><![CDATA[<p>Here is a sample class that encapsulates an ellipsis textbox.</p>
<p>Sample usage:</p>
<p>EllipsisTextBox txtBox = new EllipsisTextBox();<br />
txtBox.EllipsisType =<br />
    EllipsisTextBox.EllipsisLocation.Path;<br />
txtBox.Text =<br />
    @"C:\directory\subdirectory\filename.ext";<br />
Depending on the width of the textbox, it will display something like "C:\di&#8230;\filename.ext".</p>
<p>However,<br />
string boo = txtBox.Text;       yields<br />
  boo == @"C:\directory\subdirectory\filename.ext", the original string, NOT the truncated string.</p>
<p>The sample textbox can be dragged onto a form, and assigned EllipsisType in the Properties window.</p>
<p>The sample also demonstrates a "bug" with String.Trim().<br />
=================================================</p>
<p>using System;<br />
using System.ComponentModel;<br />
using System.Drawing;<br />
using System.Windows.Forms;</p>
<p>namespace MyProject<br />
{<br />
    ///<br />
    /// Creates a TextBox with built-in ellipsis control.<br />
    /// (1) Specify EllipsisTextBox.EllipsisType<br />
    ///       (e.g., = EllipsisLocation.Path)<br />
    /// (2) Put text into the textbox (e.g., EllipsisTextBox.Text = @"c:\directory\file.txt")<br />
    /// The displayed text is the original text modified by the EllipsisType.<br />
    ///     (e.g., "&#8230;\file.txt" if that's what fills the small textbox)<br />
    /// The string returned by EllipsisTextBox.Text is the original text,<br />
    ///    which may differ from what is showing in the textbox.<br />
    ///<br />
    public partial class EllipsisTextBox : System.Windows.Forms.TextBox<br />
    {<br />
        private string fullText;<br />
        private string ellipsisText;<br />
        private EllipsisLocation ellipsisLocation =  EllipsisLocation.None;<br />
        private TextFormatFlags ellipsisTextFormatFlag = 0;</p>
<p>        public enum EllipsisLocation { Path, Word, End, None };</p>
<p>        ///<br />
        ///   Define where ellipsis appears<br />
        ///<br />
        /// TextFormatFlags.PathEllipsis,TextFormatFlags.EndEllipsis,TextFormatFlags.WordEllipsis<br />
        ///<br />
        [System.ComponentModel.Description("Define where ellipsis appears in the string")]<br />
        [System.ComponentModel.DefaultValue(EllipsisLocation.None)]<br />
        public EllipsisLocation EllipsisType<br />
        {<br />
            get { return ellipsisLocation; }<br />
            set {<br />
                ellipsisLocation = value;<br />
                switch (value)<br />
                {<br />
                    case EllipsisLocation.End:<br />
                        ellipsisTextFormatFlag = TextFormatFlags.EndEllipsis; break;<br />
                    case EllipsisLocation.None:<br />
                        ellipsisTextFormatFlag = 0; break;<br />
                    case EllipsisLocation.Path:<br />
                        ellipsisTextFormatFlag = TextFormatFlags.PathEllipsis; break;<br />
                    case EllipsisLocation.Word:<br />
                        ellipsisTextFormatFlag = TextFormatFlags.WordEllipsis; break;<br />
                    default:<br />
                        ellipsisTextFormatFlag = 0;<br />
                        ellipsisLocation = EllipsisLocation.None;<br />
                        break;<br />
                }<br />
            }<br />
        }</p>
<p>        ///<br />
        /// Modify/Get text of an EllipseTextBox.<br />
        /// Get: returns the original, unmodified assigned text.<br />
        /// Set: saves a copy of the new text, but displays<br />
        ///    the new text as modified by EllipsisType.<br />
        ///<br />
        public new string Text<br />
        {<br />
            get<br />
            {<br />
                return fullText;<br />
            }<br />
            set<br />
            {<br />
                // Ensure we get a trimmed copy of the original string,<br />
                //   NOT a reference to the original string.<br />
                // NOTE: seems to be a "bug" in .Trim() &#8211; returns a reference<br />
                //       to the original string if .Trim() does not need to modify<br />
                //       the original string, otherwise, it returns a reference to a new string.<br />
                //       We could use&#8230;<br />
                //         string truncText = (new StringBuilder(value)).ToString();<br />
                //       but drop the  below to see the .Trim() anomaly!<br />
                fullText = (value + " ").Trim();    //want a new copy, not a reference to value!</p>
<p>                // Change copy of fullText to ellipsis truncated form<br />
                //truncText = (new StringBuilder(value)).ToString();<br />
                ellipsisText = (fullText + " ").Trim();  //want a new copy to modify, else fullText would be modified, too!<br />
                TextRenderer.MeasureText(ellipsisText, this.Font, new Size(this.Width, this.Height), TextFormatFlags.ModifyString | ellipsisTextFormatFlag);<br />
                base.Text = ellipsisText;<br />
            }<br />
        }</p>
<p>        public EllipsisTextBox() : base()<br />
        {<br />
            fullText = "";<br />
            base.Text = "";<br />
        }<br />
    }<br />
}</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Another Mike</title>
		<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/comment-page-1/#comment-4564</link>
		<dc:creator>Another Mike</dc:creator>
		<pubDate>Wed, 29 Apr 2009 22:26:27 +0000</pubDate>
		<guid isPermaLink="false">http://www.mini-tools.com/at2/csharp/wordpress/truncate-file-path-with-ellipsis/#comment-4564</guid>
		<description>Gary,

Thanks.  I think that codeproject link is about as explicit as it gets about the behavior of MeasureText.  As it says, &quot;it&#039;s relatively undocumented&quot;.  

I found a suggestion by a Craig Murphy similar to yours at http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/1acc1d42-416e-4a10-9112-11018e611d95/.  

And thanks for the comments on learning C#.  I kind of spent the 90&#039;s avoiding C++, so I am long overdue for a rollover in my knowledge base.

Relative to our offline e-mail exchange, and perhaps for the comment and benefit of others, I had adapted this approach to work with a filename obtained via openFileDialog.Filename.  Being a noob, I think I have misunderstood how strings are handled in C#.  For it appears that the transformation to the truncated path appears not only in truncString but in openFileDialog.Filename.  The sign of trouble was an obscure (to me) exception after calling MeasureText.  The VS2008 debugger shows &#039;((System.Windows.Forms.FileDialog)(openFileDialogBMP)).FileName&#039; threw an exception of type &#039;System.ArgumentException&#039; for the Filename value in the watch window.  My working theory, though I&#039;ve not proved it yet, is that the ellipsis gets into the Filename field (due to my misunderstanding of string references) and that is illegal in a filename.

Anyway, I hope to figure this out fully and will report the result here.

Mike</description>
		<content:encoded><![CDATA[<p>Gary,</p>
<p>Thanks.  I think that codeproject link is about as explicit as it gets about the behavior of MeasureText.  As it says, "it's relatively undocumented".  </p>
<p>I found a suggestion by a Craig Murphy similar to yours at <a href="http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/1acc1d42-416e-4a10-9112-11018e611d95/" rel="nofollow">http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/1acc1d42-416e-4a10-9112-11018e611d95/</a>.  </p>
<p>And thanks for the comments on learning C#.  I kind of spent the 90's avoiding C++, so I am long overdue for a rollover in my knowledge base.</p>
<p>Relative to our offline e-mail exchange, and perhaps for the comment and benefit of others, I had adapted this approach to work with a filename obtained via openFileDialog.Filename.  Being a noob, I think I have misunderstood how strings are handled in C#.  For it appears that the transformation to the truncated path appears not only in truncString but in openFileDialog.Filename.  The sign of trouble was an obscure (to me) exception after calling MeasureText.  The VS2008 debugger shows '((System.Windows.Forms.FileDialog)(openFileDialogBMP)).FileName' threw an exception of type 'System.ArgumentException' for the Filename value in the watch window.  My working theory, though I've not proved it yet, is that the ellipsis gets into the Filename field (due to my misunderstanding of string references) and that is illegal in a filename.</p>
<p>Anyway, I hope to figure this out fully and will report the result here.</p>
<p>Mike</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gary Montante</title>
		<link>http://www.csharp411.com/truncate-file-path-with-ellipsis/comment-page-1/#comment-4561</link>
		<dc:creator>Gary Montante</dc:creator>
		<pubDate>Wed, 29 Apr 2009 21:06:57 +0000</pubDate>
		<guid isPermaLink="false">http://www.mini-tools.com/at2/csharp/wordpress/truncate-file-path-with-ellipsis/#comment-4561</guid>
		<description>Hi, Mike,

Take a look at

http://www.codeproject.com/KB/vb/NewPathCompactPath.aspx

which has some explanation of TextFormatFlags.ModifyString.

Sorry, but I don&#039;t remember exactly how/where I stumbled onto the solution.  My usual fact finding mode is to Google suggestive words, read some, search some more, and experiment with code when/if I see something that seems relevant.

I, too, was an old Fortran, Assembler, C/C++ programmer (since the late 1970s) and high school/community college instructor until a friend introduced me to C#.  Well, better late than never!  At least I got to see what heaven could be like while I&#039;m still alive!

Gary

P.S. I recommend learning C# in a guided manner.  The C# language has changed since I formally learned it, so I&#039;m not the best source for a recommendation on new textbooks.  But, in the past, I found the Microsoft C# Language document (e.g., http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/csharp%20language%20specification.doc) quite good for the language specifics.  However, for creating Forms programs, a textbook like &quot;Murach&#039;s C#&quot;; &quot;Windows Forms Programming in C#&quot; (Chris Sells), or &quot;Microsoft Visual C#.NET Step by Step&quot; (John Sharp, Jon Jagger) to be very useful.  Once you got the hang of it, you might like a guide to find quicky info like Microsoft&#039;s &quot;C# Programmer&#039;s Cookbook&quot;.  Happy programming...</description>
		<content:encoded><![CDATA[<p>Hi, Mike,</p>
<p>Take a look at</p>
<p><a href="http://www.codeproject.com/KB/vb/NewPathCompactPath.aspx" rel="nofollow">http://www.codeproject.com/KB/vb/NewPathCompactPath.aspx</a></p>
<p>which has some explanation of TextFormatFlags.ModifyString.</p>
<p>Sorry, but I don't remember exactly how/where I stumbled onto the solution.  My usual fact finding mode is to Google suggestive words, read some, search some more, and experiment with code when/if I see something that seems relevant.</p>
<p>I, too, was an old Fortran, Assembler, C/C++ programmer (since the late 1970s) and high school/community college instructor until a friend introduced me to C#.  Well, better late than never!  At least I got to see what heaven could be like while I'm still alive!</p>
<p>Gary</p>
<p>P.S. I recommend learning C# in a guided manner.  The C# language has changed since I formally learned it, so I'm not the best source for a recommendation on new textbooks.  But, in the past, I found the Microsoft C# Language document (e.g., <a href="http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/csharp%20language%20specification.doc)" rel="nofollow">http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/csharp%20language%20specification.doc)</a> quite good for the language specifics.  However, for creating Forms programs, a textbook like "Murach's C#"; "Windows Forms Programming in C#" (Chris Sells), or "Microsoft Visual C#.NET Step by Step" (John Sharp, Jon Jagger) to be very useful.  Once you got the hang of it, you might like a guide to find quicky info like Microsoft's "C# Programmer's Cookbook".  Happy programming&#8230;</p>
]]></content:encoded>
	</item>
</channel>
</rss>
