2016-02-02 22 views
5

Ich verwende Graphics.DrawString in einem ObjectListView. Ich muss einige Wörter in der Zeichenfolge markieren (Hintergrund gelb). Kann das gemacht werden?Graphics.DrawString markieren bestimmte Wörter

Bevor Sie Graphics.DrawString verwenden, könnte ich DefaultRenderer zum Hervorheben verwenden. Aber jetzt funktioniert es nicht.

I Graphics.DrawString wie in der Task List Probe here

Antwort

3

Sie können nur Graphics.FillRectangle() Methode dafür verwenden verwenden. Hoffen, dass Ihre ListView nicht den Text zur nächsten Zeile umbrochen.

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

Danke, aber der Text ist wie in der EXA verpackt mple im Link in meiner Frage. – Jerry

4

Wenn Object unterstützt (die normale Listview sicherlich der Fall ist)), verwenden Sie einfach den TextRenderer Text zu zeichnen:

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

Wie üblich nur einen Stil pro Anruf unterstützt wird. So bestimmte Worte zu markieren Sie verwenden mehr als einen Anruf und auch verwenden, um die TextRenderer.MeasureText Methode zu finden, um die nächsten Positionen haben. Es wird ziemlich schwierig sein, diese pixelgenau zu bekommen, es sei denn, Sie für einen Fest Schriftart absetzen können ..

Hier ist ein schnelles und schmutziges Beispiel ist:

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; 
    } 
} 

Wie Sie können sehen Sie, es gibt etwas zusätzlichen Platz nach den Ritzen. Vielleicht besser mit dem E.Graphics.MeasureString Anruf wih die StringFormat.GenericTypographic wäre, wie es um die Schaffung Größen ohne Spiel abgestimmt ist ..:

Update:

Das sieht besser aus, uns beiden Renderer machen:

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; 

zeichnen Text eingewickelt Sie müssen den verfügbaren Platz in acc nehmen ount und umfassen die y bei der Berechnung koordinieren .. Dazu Sie entweder Wort für Wort ziehen kann oder verwenden Sie die RenderText Überlastung, die eine Rectangle nimmt. Diese wird bekommen ziemlich langweilig!

aktualisieren 2

enter image description here

Hier ist eine weitere schnelle man zeigt, wie Einwickeln Text zu handhaben:

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; 
     } 
    } 
} 

Es verwendet eine kleine Funktion:

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

Ja, es unterstützt.Aber ich möchte bestimmte Wörter hervorheben. Sage alle Vorkommen von Wort1 und Wort2. – Jerry

+1

Siehe mein Update für ein Beispiel. Die Unterstützung dafür ist in Winforms eher eine Woche, aber immer noch machbar. – TaW

+1

TextRenderer ist * immer * eine bessere Wahl für das Rendern von Text. :-) –