Graphics.DrawString Highlights Specific Words

I am using Graphics.DrawString in an ObjectListView . I need to highlight some words in a line (make their background yellow). It can be done?

Before using Graphics.DrawString , I could use DefaultRenderer to highlight. But now it does not work.

I am using Graphics.DrawString as in the Task List example here

+5
source share
2 answers

If an ObjectListView supports it (normal ListView of course)), just use a TextRenderer to draw text:

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

As usual, only one style is supported for each call. Therefore, to highlight specific words, you will use more than one call, and also use the TextRenderer.MeasureText method to search for the following positions. It will be quite difficult to get this pixel perfect if you cannot set a fixed font.

Here is a quick and dirty example:

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

As you can see, there is additional space after the slots. Perhaps using a call to E.Graphics.MeasureString with StringFormat.GenericTypographic would be better, since it is configured to create dimensions without slack ..:

Update:

It looks better, making us both renderers:

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; 

To draw wrapped text, you need to take the available space into account and include the y coordinate in the calculation. To do this, you can either draw word by word, or use the RenderText overload, which takes a Rectangle . This one will get pretty tedious!

Update 2

enter image description here

Here is another example showing how to handle wrapping text:

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

It uses a small function:

 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); } 
+4
source

You can only use the Graphics.FillRectangle() method for this. We hope your ListView does not wrap text on the next line.

 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 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)) } 
+3
source

Source: https://habr.com/ru/post/1242093/


All Articles