2010-04-14 4 views
5

ero alla ricerca di un modo per inserire i puntini di sospensione in un C# percorso, e ha trovato una risposta qui su StackOverflow: C# Path Ellipsis without Win32 API callAggiungi Ellipsis ad un percorso in un programma WinForms senza chiamata API Win32 (rivisitato)

Utilizzando la RTM versioni di VS2010 e .Net 4.0, non sono riuscito a far funzionare il metodo suggerito. Ho cercato il codice di esempio "Net and found" che utilizza lo stesso metodo, ma non ha funzionato allo stesso modo.

È possibile visualizzare la stringa che sto cercando di abbreviare nel mio codice qui sotto.

Dopo aver chiamato il metodo MeasureText, sia la stringa di input (OriginalName) e la stringa di uscita (ellipsisedName) simile a questa:

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

due problemi:

1) la stringa risultante viene narfed (il percorso viene troncato come previsto, ma è seguito da quello che sembra come uno stile C che termina con null e un pezzo del percorso originale).

2) La stringa originale è stata modificata in per essere identica alla stringa di output.

Sto facendo qualcosa di sbagliato?

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

Non vedo come la chiamata a MeasureText() possa eventualmente modificare OriginalPath. Se ciò accade davvero, il metodo MeasureText() sta facendo qualcosa di veramente originale. –

risposta

4

Holy moly, hai trovato un whopper di un bug. Il P/Invoke utilizzato all'interno della classe TextRenderer che chiama DrawTextEx() è borked. Quella funzione API sta scrivendo di nuovo nella stringa, che è consentita a fare poiché l'argomento cchText è un LPTSTR, non un LPCTSTR. Ciò distrugge il contenuto delle stringhe .NET per entrambe le variabili perché la stringa è internata.

Il bug non è specifico di .NET 4.0, lo vedo errato anche in ReferenceSource per .NET 3.5 SP1 e lo posso riproporre su VS2008. Il problema è nella funzione interna di WindowsGraphics.MeasureText. È possibile segnalare il bug all'indirizzo connect.microsoft.com.

Una possibile soluzione è quella di modificare la stringa in modo che viene copiato e non può pregiudicare l'originale:

string ellipsisedPath = OriginalPath + '\0'; 

Ma la soluzione migliore in questo caso è quello di semplicemente non passare l'opzione ModifyString, non serve a nulla scopo. Che è anche più sicuro, c'è ancora la possibilità di distruggere l'heap della garbage collection con la prima soluzione. La correzione per Microsoft è similmente semplice, dovrebbe solo mascherare l'opzione ModifyString. È documentato che non ha alcun effetto.

+0

Wow, è fantastico. –

+1

È possibile usare 'string.Copy' per essere chiari sulla copia dalla stringa internata a un nuovo buffer. –

+0

Grazie per la spiegazione. Il work-around originale (e quello di Ron) risolvono entrambi il problema della stringa originale sovrascritta, ma nessuno dei due fa sì che MeasureText funzioni come volevo, in quanto la stringa di output non è ancora correttamente ellittica. Se non si specifica ModifyString, la stringa di output non è ellittica (come previsto), che annulla il mio scopo (che era quello di ottenere una stringa di percorso ellisse). Quello che sto cercando di fare è probabilmente un uso improprio di ModifyString comunque. Stavo usando questa tecnica come è stato suggerito come il modo per farlo qui: http://tinyurl.com/y6rmdfr – casterle

2

mio stringa originale viene modificato per essere identica alla stringa di output.

Hai chiesto perché questo avvenga specificando TextFormatFlags.ModifyString, che i documenti dicono

modifica la stringa specificata per abbinare il testo visualizzato. Questo valore non ha alcun effetto a meno che non sia specificato anche EndEllipsis o PathEllipsis.

Questo è (a mio avviso) un modo insolito per il funzionamento di una chiamata a .NET Framework, ma indica chiaramente che lo farà. Sia la stringa 'originale' e la stringa 'uscita' finiscono per essere modificate, perché string è un tipo di riferimento (anche se di solito con semantica di valore immutabili) - quando dici

string ellipsisedPath = OriginalPath; 

realtà si sta solo facendo ellipsisedPath riferiscono la stessa istanza di stringa di OriginalPath. Quando questa istanza viene modificata dalla chiamata API, entrambi i riferimenti a essa vedranno la modifica.

Per quanto riguarda

il percorso viene troncato come previsto, ma è seguito da quello che sembra un C-stile di terminazione nullo e un pezzo del percorso originale

la mia ipotesi è che l'astrazione che questo wrapper gestito fornisce attorno alla chiamata all'API Win32 è in qualche modo dispersiva, poiché le astrazioni sono inclini ad essere - non ti protegge dal fatto che la chiamata sottostante funzioni con stringhe in stile C. Potrebbe essere che dovrai affrontare te stesso.

+0

"quando dici stringa ellipsisedPath = OriginalPath, in realtà stai solo facendo ellissiPath per fare riferimento alla stessa istanza di stringa di OriginalPath. [...]" Questo è ** sbagliato **. L'assegnazione di stringa1 a stringa2 crea una copia di valore di stringa1. Qualsiasi modifica a string1 avrà l'effetto ** no ** su stringa2. E sebbene la stringa sia una classe, è immutabile e si comporta come un tipo di valore. Le stringhe non sono mai * cambiate *, sono sempre * copiate * in una nuova stringa con la modifica. –

+0

I * DO * specificare PathEllipsis. – casterle

+0

@Hans: Può descrivere ciò che è accaduto a causa del bug, ma fornisce anche informazioni palesemente false sull'assegnazione di una stringa a un'altra in qualsiasi situazione normale, e non riesce a far notare che ciò è accaduto solo a causa di un grosso bug in TextRenderer. Per favore, almeno riconosci che, come qualcuno con il tuo rappresentante non dovrebbe contribuire a un tale malinteso. –

Problemi correlati