2009-06-16 8 views
38

Sto usando pixel come unità per il mio carattere. In un punto, eseguo un hit test per verificare se l'utente ha fatto clic all'interno del rettangolo di delimitazione di un testo sullo schermo. Ho bisogno di usare qualcosa come MeasureString per questo. Sfortunatamente, il codice che esegue l'hit test è all'interno di una libreria che non ha accesso ad un oggetto Graphics o anche a Control.Misurare una stringa senza utilizzare un oggetto grafico?

Come faccio ad avere il riquadro di delimitazione di una stringa dato il carattere senza utilizzare la classe Graphics? Perché ho anche bisogno di un oggetto Graphics quando il mio font è in pixel?

+0

Cosa hai se non hai il controllo? Sto assumendo Font e la stringa, ma c'è qualcos'altro? – micahtan

+0

Nient'altro. La mia biblioteca è una specie di Scenegraph. Sto cercando di evitare dipendenze su System.Drawing e System.Windows.Forms –

risposta

44

Se si dispone di un riferimento a System.Windows.Forms, provare a utilizzare la classe TextRenderer. Esiste un metodo statico (MeasureText) che accetta la stringa e il carattere e restituisce la dimensione. MSDN Link

+2

Leggero problema con TextRenderer è che utilizza numeri interi per il valore restituito, che può causare problemi se è necessaria la precisione sub-pixel. Altrimenti, è una buona alternativa. –

+0

Come è questa la soluzione? L'esempio nel link mostra 'TextRenderer.DrawText (e.Graphics,' – jp2code

+0

@ jp2code - Hai letto anche la mia risposta? Ha chiesto come misurare una stringa senza usare la classe Graphics. Ho suggerito il metodo MeasureText sulla classe TextRenderer. Risponde alla sua domanda e ho persino fornito il link alla documentazione MSDN per questa classe. Dai un altro sguardo. – Jarrod

23

Non è necessario utilizzare l'oggetto Graphics che si sta utilizzando per il rendering di fare la misura. Si potrebbe creare una classe di utilità statica:

public static class GraphicsHelper 
{ 
    public static SizeF MeasureString(string s, Font font) 
    { 
     SizeF result; 
     using (var image = new Bitmap(1, 1)) 
     { 
      using (var g = Graphics.FromImage(image)) 
      { 
       result = g.MeasureString(s, font); 
      } 
     } 

     return result; 
    } 
} 

potrebbe essere worthwile, a seconda della situazione per impostare il dpi della bitmap pure.

+0

Sembra buono, ma non penso che la nuova Bitmap (0, 0) sia consentita, forse (1,1) –

+0

@AlexanderN Ho appena confermato che Bitmap (0, 0) non è valido. La tua soluzione di Bitmap (1, 1) è corretta. L'oggetto immagine –

+0

potrebbe essere statico per evitare di ricreare l'oggetto ogni volta – dlopezgonzalez

10

MeasureString metodo nella risposta @NerdFury fornirà una larghezza di stringa superiore a quella prevista.Informazioni aggiuntive è possibile trovare here. Se si vuole misurare solo la lunghezza fisica Aggiungi questa due linee:

g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; 
result = 
    g.MeasureString(measuredString, font, int.MaxValue, StringFormat.GenericTypographic); 
1

Questo esempio fa grande lavoro di illustrare l'uso di FormattedText. FormattedText fornisce un controllo a basso livello per il disegno di testo nelle applicazioni Windows Presentation Foundation (WPF). Puoi usarlo per misurare la larghezza di una stringa con un particolare carattere senza usare un oggetto grafico.

public static float Measure(string text, string fontFamily, float emSize) 
{ 
    FormattedText formatted = new FormattedText(
     item, 
     CultureInfo.CurrentCulture, 
     System.Windows.FlowDirection.LeftToRight, 
     new Typeface(fontFamily), 
     emSize, 
     Brushes.Black); 

    return formatted.Width; 
} 

Include librerie WindowsBase e PresentationCore.

0

Questo potrebbe non essere altro che una ripetizione di altri, ma il mio problema era anche l'oggetto grafico indesiderato. Dopo aver ascoltato le frustrazioni di cui sopra ho semplicemente provato:

Size proposedSize = new Size(int.MaxValue, int.MaxValue); 
TextFormatFlags flags = TextFormatFlags.NoPadding; 
Size ressize = TextRenderer.MeasureText(content, cardfont, proposedSize, flags); 

(dove 'contenuto' è la stringa di misurare e cardfont il tipo di carattere è in)

... ed è stato fortunato. Potrei usare il risultato per impostare la larghezza della mia colonna in VSTO.

Problemi correlati