2016-02-02 18 views
5

Używam Graphics.DrawString w ObjectListView. Muszę zaznaczyć niektóre słowa w ciągu (sprawić, że ich tło będzie żółte). Czy można to zrobić?Graphics.DrawString podświetl konkretne słowa

Przed użyciem Graphics.DrawString mogę użyć podświetlenia DefaultRenderer. Ale teraz to nie działa.

Używam Graphics.DrawString jak w Task List próbki here

Odpowiedz

3

można używać tylko Graphics.FillRectangle() sposób na to. Mam nadzieję, że Twój ListView nie zawinie tekstu do następnej linii.

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

Dzięki, ale tekst jest zawijany jak w exa w linku w moim pytaniu. – Jerry

4

Jeśli ObjectListView je obsługuje (normalny ListView na pewno nie)), wystarczy użyć TextRenderer rysować tekst:

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

Jak zwykle tylko jeden styl jest obsługiwany za rozmowę. Aby wyróżnić określone słowa, należy użyć więcej niż jednego połączenia, a także użyć metody TextRenderer.MeasureText, aby znaleźć kolejne pozycje. To będzie raczej trudne do uzyskania tego pixel-perfect, chyba że można godzić się na stałym czcionki ..

Oto szybki i brudny przykład:

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

jak można widzisz, po szczelinach jest trochę więcej miejsca. Może za pomocą wywołania wih StringFormat.GenericTypographicE.Graphics.MeasureString byłoby lepiej, jako że jest dostrojony do tworzenia rozmiary bez luzu ..:

Aktualizacja:

To wygląda lepiej, co czyni nas obu renderujących:

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; 

aby narysować owinięty tekst trzeba wziąć dostępną przestrzeń do acc ount i uwzględnij współrzędną y w obliczeniach. W tym celu możesz albo narysować słowo po słowie, albo użyć przeciążenia RenderText, które zajmuje Rectangle. To będzie dostać raczej nudny!

Aktualizacja 2

enter image description here

Oto kolejny szybki jeden pokazujący jak obsłużyć zawijanie tekstu:

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

Wykorzystuje małą funkcję:

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

Tak, jest obsługiwany.Ale chcę podkreślić konkretne słowa. Powiedz wszystkie wystąpienia słowa 1 i słowa 2. – Jerry

+1

Zobacz moją aktualizację dla przykładu. Obsługa tego jest raczej tygodniowa w WinForm, ale nadal możliwa do wykonania .. – TaW

+1

TextRenderer jest * zawsze * lepszym wyborem do renderowania tekstu. :-) –

Powiązane problemy