Graphics.DrawString突出显示特定单词

时间:2016-02-02 13:59:59

标签: c# graphics highlight drawstring objectlistview

我在ObjectListView中使用Graphics.DrawString。我需要突出显示字符串中的一些单词(使其背景为黄色)。可以这样做吗?

在使用Graphics.DrawString之前,我可以使用DefaultRenderer进行突出显示。但现在它不起作用。

我在Graphics.DrawString示例here

中使用Task List

2 个答案:

答案 0 :(得分:4)

如果ObjectListView支持它(正常的ListView当然可以),只需使用TextRenderer绘制文本:

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

通常每次通话只支持一种风格。因此,要突出显示某些单词,您将使用多个调用,并使用TextRenderer.MeasureText方法查找下一个位置。除非你可以选择固定字体,否则很难让这个像素完美无缺。

这是一个快速而又肮脏的例子:

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

正如您所看到的,在缝隙之后有一些额外的空间。也许使用E.Graphics.MeasureString调用StringFormat.GenericTypographic会更好,因为它被调整为创建大小而没有松弛..:

<强>更新

这看起来更好,使我们成为两个渲染器:

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;

要绘制包裹文字,您需要考虑可用空间并在计算中包含y坐标。为此,您可以逐字绘制或使用RenderText需要Rectangle的重载。 变得相当繁琐!

更新2

enter image description here

这是另一个快速显示如何处理包装文本的内容:

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

它使用一个小功能:

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

答案 1 :(得分:3)

您只能使用Graphics.FillRectangle()方法。希望你的ListView不会将文本包装到下一行。

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



}