2010-04-14 25 views
5

我正在尋找一種方法來插入一個C#路徑省略號在一個WinForms程序的路徑,在這裏找到了答案#2:C# Path Ellipsis without Win32 API call添加省略號,而不Win32 API調用(重新)

使用RTM VS2010和.Net 4.0版本,我無法得到建議的方法工作。我搜索了'Net和找到的使用相同方法的示例代碼,但它以相同的方式失敗。

你可以在下面的代碼中看到我想縮短的字符串。

調用MeasureText方法後,無論是輸入字符串(ORIGINALNAME)和輸出字符串(ellipsisedName)是這樣的:

d:\ ABCD \ EFGH \ IJKL \ MNOP \ QRST \ ... \測試.TXT \ 0F \ GHIJ \ KLMN \使用opqr \ STIV \ WXYZ \ test.txt的

兩個問題:

1)生成的字符串narfed(如預期的路徑被截斷,但隨之而來的什麼樣子就像C風格終止空和原始路徑的塊)。

2)我的原始字符串被更改爲以與輸出字符串相同。

我做錯了什麼?

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); 
     } 
    } 
} 
+0

我看不到如何調用MeasureText()可能會修改OriginalPath。如果真的發生了這種情況,MeasureText()方法會做一些非常奇怪的事情。 – 2010-04-14 20:22:02

回答

4

神聖莫里,你發現了一個臭蟲。在調用DrawTextEx()的TextRenderer類中使用的P/Invoke是borked。該API函數正在寫回到字符串中,因爲cchText參數是LPTSTR而不是LPCTSTR,所以它被允許執行。這會破壞.NET字符串內容這兩個變量,因爲該字符串是interned。

該錯誤不是特定於.NET 4.0的,我也在.NET 3.5 SP1的ReferenceSource中看到它錯誤,並且可以在VS2008上重新生成它。麻煩在於WindowsGraphics.MeasureText內部函數。您可以在connect.microsoft.com上報告該錯誤。

可能的解決方法是改變字符串,因此它被複制,並且不能影響原有:

string ellipsisedPath = OriginalPath + '\0'; 

但在這種情況下,更好的解決方法是根本無法通過的ModifyString選項,也是沒有目的。更安全的是,第一種解決方法仍然有可能摧毀垃圾收集堆。微軟的修復方法同樣很簡單,它應該掩蓋ModifyString選項。它被記錄爲沒有效果。

+0

哇,這很酷。 – 2010-04-14 20:28:34

+1

您可以使用'string.Copy'來清除從interned字符串到新緩衝區的拷貝。 – 2010-04-14 20:37:18

+0

謝謝你的解釋。你原來的解決方法(和羅恩的)都解決了被覆蓋的原始字符串問題,但都沒有讓我們想要的MeasureText工作,因爲輸出字符串仍然沒有正確地被橢圓化。 如果我沒有指定ModifyString,輸出字符串不是橢圓化(如預期的那樣),這違背了我的目的(即獲得一個橢圓路徑字符串)。 我想要做的可能是濫用ModifyString無論如何。我正在使用這種技術,因爲它建議這樣做的方式:http://tinyurl.com/y6rmdfr – casterle 2010-04-14 21:16:15

2

我原來的字符串被改變爲相同的輸出字符串。

你問這個通過指定TextFormatFlags.ModifyString,該文件說

修改指定字符串到顯示的文本匹配的發生。除非指定了EndEllipsis或PathEllipsis,否則此值不起作用。

這是(在我看來)一個.NET框架調用操作的不尋常的方式,但它明確表示它會這樣做。無論是「原始」字符串和「輸出」字符串最終被修改,因爲string是引用類型(雖然通常以不變值語義) - 當你說

string ellipsisedPath = OriginalPath; 

你實際上只是讓ellipsisedPath參考與OriginalPath相同的字符串實例。當這個實例被API調用修改後,它的引用都會看到修改。

至於

路徑如預期被截斷,但隨之而來的是一種看上去C風格終止空和原始路徑的一大塊

我的猜測是,在Win32 API調用周圍提供的這個託管包裝的抽象有些泄漏,因爲抽象很容易出現 - 它不會阻止您使用C風格字符串進行底層調用。這可能是你必須處理自己。

+0

「當你說字符串ellipsisedPath = OriginalPath;你實際上只是在使用ellipsisedPath引用與OriginalPath相同的字符串實例。[...]」這是錯誤的**。將string1分配給string2會生成string1的值副本。對string1的任何更改都會對string2產生** no **效果。儘管字符串是一個類,它是不可變的,並且像一個值類型。字符串從不*改變*,它們總是*複製*到修改後的新字符串。 – 2010-04-14 20:23:29

+0

I * DO *指定PathEllipsis。 – casterle 2010-04-14 20:24:58

+0

@Hans:它可能描述了由於錯誤而發生了什麼,但它也給出了在任何正常情況下將一個字符串分配給另一個字符串的錯誤信息,並且沒有指出這僅僅是因爲TextRenderer中的一個主要錯誤而發生的。請至少承認,因爲你的代表有人不應該造成這樣的誤解。 – 2010-04-14 22:55:53