2010-04-14 35 views
5

Tôi đang tìm kiếm một cách để chèn một dấu chấm lửng trong một đường dẫn C#, và tìm thấy một câu trả lời ở đây trên stackoverflow: C# Path Ellipsis without Win32 API callThêm Ellipsis đến một con đường trong một chương trình WinForms mà không cuộc gọi Win32 API (revisited)

Sử dụng RTM Phiên bản của VS2010 và .Net 4.0, tôi không thể có được phương pháp được đề xuất để hoạt động. Tôi đã tìm kiếm 'Mã ví dụ thuần và tìm thấy có sử dụng cùng một phương pháp, nhưng nó không thành công theo cùng một cách.

Bạn có thể thấy chuỗi tôi đang cố gắng rút ngắn mã của mình bên dưới.

Sau khi gọi phương thức MeasureText, cả hai chuỗi đầu vào (OriginalName) và chuỗi đầu ra (ellipsisedName) trông như thế này:

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

Hai vấn đề:

1) chuỗi kết quả được narfed (con đường được cắt ngắn như mong đợi, nhưng sau đó là những gì vẻ giống như một kiểu C kết thúc null và một đoạn của đường dẫn gốc).

2) My chuỗi gốc được thay đổi giống hệt với chuỗi đầu ra.

Tôi có làm gì sai không?

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

Tôi không thấy cách gọi của bạn đến MeasureText() có thể có thể sửa đổi OriginalPath. Nếu điều đó thực sự xảy ra, phương thức MeasureText() đang làm một điều gì đó thực sự sôi nổi. –

Trả lời

4

Moly thánh, bạn đã tìm thấy một kẻ lừa đảo. P/Invoke được sử dụng bên trong lớp TextRenderer gọi DrawTextEx() được borked. Hàm API đó viết lại vào chuỗi, nó được phép làm vì đối số cchText là một LPTSTR, không phải là LPCTSTR. Điều đó phá hủy nội dung chuỗi .NET cho cả hai biến số vì chuỗi được thực thi.

Lỗi này không cụ thể đối với .NET 4.0, tôi thấy nó sai trong ReferenceSource cho .NET 3.5 SP1 và có thể repro nó trên VS2008. Sự cố là trong hàm WindowsGraphics.MeasureText bên trong. Bạn có thể báo cáo lỗi tại connect.microsoft.com.

Một cách giải quyết có thể là để thay đổi chuỗi để nó được sao chép và không thể ảnh hưởng đến bản gốc:

string ellipsisedPath = OriginalPath + '\0'; 

Nhưng cách giải quyết tốt hơn trong trường hợp này chỉ đơn giản là không vượt qua được lựa chọn ModifyString, nó phục vụ không mục đích. Đó là an toàn hơn quá, vẫn còn một khả năng phá hủy đống rác thu thập với các workaround đầu tiên. Việc sửa chữa cho Microsoft là tương tự đơn giản, nó chỉ nên che giấu tùy chọn ModifyString. Nó được ghi nhận là không có hiệu lực.

+0

Thật tuyệt vời. –

+1

Bạn có thể sử dụng 'string.Copy' để rõ ràng về việc sao chép từ chuỗi ký tự vào một bộ đệm mới. –

+0

Cảm ơn bạn đã giải thích. Công việc ban đầu của bạn (và của Ron) cả hai giải quyết vấn đề chuỗi ghi đè ban đầu, nhưng không làm cho MeasureText hoạt động như tôi muốn, vì chuỗi đầu ra vẫn không được bỏ qua đúng cách. Nếu tôi không chỉ định ModifyString chuỗi đầu ra không được bỏ qua (như mong đợi), mà đánh bại mục đích của tôi (đó là để có được một chuỗi đường dẫn elip). Những gì tôi đang cố gắng làm có lẽ là lạm dụng của ModifyString. Tôi đã sử dụng kỹ thuật này vì nó đã được đề xuất như là cách để làm điều này ở đây: http://tinyurl.com/y6rmdfr – casterle

2

Chuỗi gốc của tôi được thay đổi giống với chuỗi đầu ra.

Bạn đã yêu cầu điều này xảy ra bằng cách xác định TextFormatFlags.ModifyString, mà các tài liệu nói

Sửa đổi chuỗi định để phù hợp với văn bản được hiển thị. Giá trị này không có hiệu lực trừ khi EndEllipsis hoặc PathEllipsis cũng được chỉ định.

Đây là (theo ý của tôi) một cách khác thường để gọi .NET Framework hoạt động, nhưng rõ ràng là nó sẽ làm điều này. Cả hai chuỗi 'gốc' và 'đầu ra' chuỗi kết thúc được sửa đổi, bởi vì string là một loại tài liệu tham khảo (mặc dù thường với ngữ nghĩa giá trị bất biến) - khi bạn nói

string ellipsisedPath = OriginalPath; 

bạn đang thực sự chỉ làm ellipsisedPath tham khảo cùng một thể hiện chuỗi như OriginalPath. Khi cá thể này được sửa đổi bởi lệnh gọi API, cả hai tham chiếu đến nó sẽ thấy sửa đổi.

Đối với

con đường được cắt ngắn như mong đợi, nhưng sau đó là những gì trông giống như một C-phong cách chấm dứt vô một đoạn của con đường ban đầu

đoán của tôi sẽ là trừu tượng này quản lý wrapper cung cấp xung quanh cuộc gọi API Win32 đang được phần nào bị rò rỉ, như abstractions dễ bị - nó không che chắn cho bạn từ thực tế là cuộc gọi cơ bản làm việc với các chuỗi C-style. Nó có thể là bạn sẽ phải đối phó với chính mình.

+0

"khi bạn nói chuỗi ellipsisedPath = OriginalPath; bạn thực sự chỉ làm cho ellipsisedPath tham chiếu đến cùng một cá thể chuỗi như OriginalPath. [...]" Đây là ** sai **. Gán string1 thành string2 tạo một bản sao giá trị của chuỗi1. Mọi thay đổi đối với chuỗi 1 sẽ có ** không ** hiệu lực trên chuỗi2. Và mặc dù chuỗi là một lớp, nó là bất biến và hoạt động như một loại giá trị. Các chuỗi không bao giờ * thay đổi *, chúng luôn được * sao chép * thành chuỗi mới có sửa đổi. –

+0

I * DO * chỉ định PathEllipsis. – casterle

+0

@Hans: Nó có thể mô tả những gì đã xảy ra do lỗi, nhưng nó cũng cung cấp thông tin sai lệch về việc gán một chuỗi cho chuỗi khác trong bất kỳ tình huống bình thường nào và không chỉ ra rằng điều này chỉ xảy ra do lỗi chính trong TextRenderer. Xin vui lòng ít nhất cũng thừa nhận rằng, như một người với đại diện của bạn không nên đóng góp cho một sự hiểu lầm như vậy. –

Các vấn đề liên quan