2016-02-02 68 views
5

Sto usando Graphics.DrawString in un ObjectListView. Ho bisogno di evidenziare alcune parole nella stringa (rendere il loro sfondo giallo). Può essere fatto?Graphics.DrawString evidenzia parole specifiche

Prima di utilizzare Graphics.DrawString, è possibile utilizzare DefaultRenderer per l'evidenziazione. Ma ora non funziona.

sto usando Graphics.DrawString come nel Task List campione here

risposta

3

È possibile utilizzare solo Graphics.FillRectangle() metodo per questo. Spero che il tuo ListView non sposti il ​​testo sulla riga successiva.

using (Graphics g = Graphics.FromImage(yourImage.Image)) 
{ 
    Font drawFont = new Font("Arial", 12); 
    SolidBrush drawBrush = new SolidBrush(Color.Black); 

    //your text starting position 
    double textX = 350.0,textY=340.0; 

    //Get length of one character for your font style 
    float CharWidth = g.MeasureString("A", drawFont).Width; 

    //Take the words before the word that has to be highlighted and get it's length 
    float widthTotal = "First text strip that doesn't need highlighting".Length() * CharWidth 


    //Create and draw a rectangle here offsetting this widthTotal from the starting position for the desired Length 
    var size = g.MeasureString("Text to be highlighted", drawFont); 
    var rectangle = new RectangleF(textX+widthTotal , textY, size.Width, size.Height); 

    //Filling a rectangle before drawing the string. 
    g.FillRectangle(Brushes.Yellow, rectangle); 
    //Repeat above process for all required words 

    //Finally draw your string over it 
    g.DrawString("your complete text",drawFont,drawBrush,new Point(textX,textY)) 



} 
+0

Grazie, ma il testo è avvolto come nell'exa mple nel link nella mia domanda. – Jerry

4

Se ObjectListView lo supporta (ListView normale fa certamente)), è sufficiente utilizzare il TextRenderer per disegnare il testo:

enter image description here

private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e) 
{ 
    TextFormatFlags flags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter; 
    TextRenderer.DrawText(e.Graphics, e.Item.Text, Font, e.Bounds, 
          Color.Blue, Color.LightSteelBlue, flags); 
} 

Come al solito un solo stile è supportato per ogni chiamata. Quindi per evidenziare certe parole dovrai usare più di una chiamata e usare anche il metodo TextRenderer.MeasureText per trovare le posizioni successive. Sarà piuttosto difficile ottenere questo pixel-perfect, a meno che non si può accontentare di un-font fisso ..

Ecco un esempio veloce e sporco:

enter image description here

private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e) 
{ 
    TextFormatFlags flags = TextFormatFlags.Left; 

    int leftPadding = 3; 
    int x = leftPadding; 
    var words = e.Item.Text.Split('#'); 
    for (int i = 0; i < words.Count(); i++) 
    { 
     Point pt = new Point(x, e.Bounds.Top); 
     Size sz = TextRenderer.MeasureText(words[i], Font); 
     if (i % 2 == 0) 
      TextRenderer.DrawText(e.Graphics, words[i], Font, pt, 
            Color.Black, flags); 
     else 
      TextRenderer.DrawText(e.Graphics, words[i], Font, pt, 
            Color.Blue, Color.LightSteelBlue, flags); 
     x += sz.Width; 
    } 
} 

come si può vedi, c'è qualche spazio in più dopo le fessure. Forse con il E.Graphics.MeasureString chiamata wih il StringFormat.GenericTypographic sarebbe meglio, come si è sintonizzato per la creazione di formati senza allentamento ..:

Aggiornamento:

Questo sembra migliore, rendendoci di entrambi i renderer:

enter image description here

Point pt = new Point(x, e.Bounds.Top); 
Size sz1 = TextRenderer.MeasureText(words[i], Font); 
SizeF sz2 = e.Graphics.MeasureString(words[i],Font, 9999, StringFormat.GenericTypographic); 

if (i % 2 == 0) 
    TextRenderer.DrawText(e.Graphics, words[i], Font, pt, Color.Black); 
else 
    TextRenderer.DrawText(e.Graphics, words[i], Font, pt, 
          Color.Blue, Color.LightSteelBlue); 
x += (int)(sz1.Width + sz2.Width)/2; 

per disegnare avvolto testo è necessario prendere lo spazio disponibile in acc Si consiglia di includere la coordinata y nel calcolo. Per questo è possibile disegnare parola per parola o utilizzare il sovraccarico RenderText che prende uno Rectangle. Questo sarà diventare piuttosto noioso!

Aggiornamento 2

enter image description here

Ecco un altro rapido uno che mostra come gestire il testo da imballaggio:

private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e) 
{ 
    int maxW = e.Bounds.Width; 
    int leftPadding = 3; 
    int leading = 1; 
    int x = leftPadding; 
    int y = e.Bounds.Y; 
    var chunks = e.Item.Text.Split('#'); 

    SizeF s0 = e.Graphics.MeasureString("_|", Font); 
    Size s1 = e.Bounds.Size; 

    for (int i = 0; i < chunks.Count(); i++) 
    { 
     Point pt = new Point(x, e.Bounds.Top); 
     var words = chunks[i].Split(' '); 

     for (int j = 0; j < words.Count(); j++) 
     { 
      Size sz1 = TextRenderer.MeasureText(words[j], Font); 
      SizeF sz2 = e.Graphics.MeasureString(words[j], Font, 9999, 
               StringFormat.GenericTypographic); 
      int w = (int)(sz1.Width + sz2.Width)/2; 
      if (x + w > maxW) 
      { 
       y += sz1.Height + leading; 
       x = leftPadding; 
      } 
      DrawWords(e.Graphics, words[j], Font, new Point(x, y), 
         Color.Blue, Color.LightSteelBlue, i % 2 != 1); 
      x += w; 
     } 
    } 
} 

Esso utilizza una piccola funzione:

void DrawWords(Graphics g, string text, Font font, Point pt, 
       Color fCol, Color Bcol, bool highlite) 
{ 
     if (highlite) 
      TextRenderer.DrawText(g, text, font, pt, Color.Black); 
     else 
      TextRenderer.DrawText(g, text, font, pt, Color.Blue, Color.LightSteelBlue); 
} 
+0

Sì, è supportato.Ma voglio evidenziare parole specifiche. Dì tutte le occorrenze di word1 e word2. – Jerry

+1

Vedere il mio aggiornamento per un esempio. Il supporto per questo è piuttosto una settimana in Winforms ma ancora fattibile .. – TaW

+1

TextRenderer è * sempre * una scelta migliore per il rendering del testo. :-) –

Problemi correlati