Jer*_*rry 5 c# graphics drawstring highlight objectlistview
我Graphics.DrawString在ObjectListView中使用.我需要突出显示字符串中的一些单词(使其背景为黄色).可以这样做吗?
在使用之前Graphics.DrawString,我可以使用DefaultRenderer突出显示.但现在它不起作用.
我Graphics.DrawString在这里使用Task List样本
如果 ObjectListView 支持(普通的 ListView 当然支持)),只需使用TextRenderer来绘制文本:
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);
}
Run Code Online (Sandbox Code Playgroud)
与往常一样,每次调用仅支持一种样式。因此,要突出显示某些单词,您将需要使用多个调用,并使用该TextRenderer.MeasureText方法来查找下一个位置。除非你能满足于固定字体,否则要获得完美的像素将是相当困难的。
这是一个快速而肮脏的例子:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,缝隙后面有一些额外的空间。也许使用E.Graphics.MeasureString与 the 的调用StringFormat.GenericTypographic会更好,因为它被调整为创建没有松弛的尺寸......:
更新:
这看起来更好,使我们可以使用两个渲染器:
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;
Run Code Online (Sandbox Code Playgroud)
要绘制换行文本,您需要考虑可用空间并在计算中包含 y 坐标。为此,您可以逐字绘制或使用RenderText采用Rectangle. 这会变得相当乏味!
更新2
这是另一个快速演示如何处理换行文本的示例:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
它使用了一个小函数:
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);
}
Run Code Online (Sandbox Code Playgroud)
You can only use Graphics.FillRectangle() method for this. Hope your ListView doesn't wrap the text to 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'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))
}
Run Code Online (Sandbox Code Playgroud)