Nicolas Mossmann
Nicolas Mossmann

Reputation: 75

C# Winforms - Owner-drawn listbox with multiple colors in the same line

I found an article that does exactly what I need. It draws multiple colors on the same line on a text box. But the problem is that it was written in VB.NET and I'm writing my program in C#. Any good soul can convert this to C# if it is possible and if it isn't can you give me other options? Thanks.

This is the article: http://www.vbrad.com/article.aspx?id=34.

Upvotes: 0

Views: 1441

Answers (3)

JMK
JMK

Reputation: 28059

First of all, they aren't using a Textbox in this article, they are using a Listbox but what follows is a conversion of the code from VB.Net to C# like you asked. It needs tidied up a bit but it does the job.

Just create a new Windows Form, place a Listbox called lstColor onto this form, change the DrawMode property to OwnerDrawFixed inside the properties window, then add event handlers for DrawItem and MeasureItem (you can add event handlers by clicking on the lightning bolt in the Properties window, and double clicking the whitespace beside these two words in the list).

In the DrawItem event handler, add the following:

private void lstColor_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
    var size = g.MeasureString(data[e.Index], oFont, 500, sf);
    var width = size.Width + 16;

    e.DrawBackground();
    e.DrawFocusRectangle();
    e.Graphics.DrawString(data[e.Index], oFont, new SolidBrush(color[e.Index]), e.Bounds.X, e.Bounds.Y);
    e.Graphics.DrawString(data[data.Length - 1 - e.Index], oFont, new SolidBrush(color[color.Length - 1 - e.Index]), width, e.Bounds.Y);
}

In the MeasureItem event handler, add this:

private void lstColor_MeasureItem(object sender, MeasureItemEventArgs e)
{
    var size = g.MeasureString(data[e.Index], oFont, 500, sf);
    var height = size.Height;

    e.ItemHeight = Convert.ToInt32(height);
}

Add five private fields outside the scope of any methods but inside your Form1 (or whatever you've called your form) class like so:

private string[] data;
private Color[] color;
private Font oFont;
private Graphics g;
private StringFormat sf;

Put the following three lines inside your Form1_Load event:

private void Form1_Load(object sender, EventArgs e)
{
    oFont = new Font("Arial", 10);

    data = new string[] { "This is Red", "This is Blue", "This is Green", "This is Yellow", "This is Black", "This is Aqua", "This is Brown", "This is Cyan", "This is Gray", "This is Pink" };
    color = new Color[] {Color.Red, Color.Blue, Color.Green, Color.Yellow, Color.Black, Color.Aqua, Color.Brown, Color.Cyan, Color.Gray,Color.Pink};
    lstColor.DataSource = data;
    g = Graphics.FromHwnd(lstColor.Handle);
    sf = new StringFormat(StringFormat.GenericTypographic);
}

And you are all set.

Hope this helps

Upvotes: 1

talbright
talbright

Reputation: 446

Check out http://converter.telerik.com/ It converts code from VB.NET to C# and C# to VB.NET. It wont work on complex code, but could prove useful to you.

Upvotes: 0

MethodMan
MethodMan

Reputation: 18843

here is the conversion of what you posted Nicolas

if you need to change / get anything else working you will need to test it on your end..

Happy coding

private void  MeasureItemHandler(object sender, MeasureItemEventArgs e)
{
    Graphics g = Graphics.FromHwnd(lstColor.Handle);
    StringFormat sf = new StringFormat(StringFormat.GenericTypographic);
    SizeF size = default(SizeF);
    float height = 0;
    Font oFont = new Font("Arial", 10);

    //measure the height of what you are about to draw
    //and let the listbox know this
    size = g.MeasureString(data(e.Index), oFont, 500, sf);
    height = size.Height + 5;
    e.ItemHeight = height;
}

private void  DrawItemHandler(object sender, DrawItemEventArgs e)
{

    Graphics g = Graphics.FromHwnd(lstColor.Handle);
    StringFormat sf = new StringFormat(StringFormat.GenericTypographic);
    SizeF size = default(SizeF);
    float width = 0;
    Font oFont = new Font("Arial", 10);


    //get the width of the string you are about to write
    //this info is needed so that we can offset the next 
    //string that will be drawn in a different color.
    size = g.MeasureString(data(e.Index), oFont, 500, sf);
    width = size.Width + 16;

    //prepare the list for drawing
    e.DrawBackground();
    e.DrawFocusRectangle();

    //draw the first string in a certain color
    e.Graphics.DrawString(data(e.Index), oFont, new SolidBrush(color(e.Index)), e.Bounds.X, e.Bounds.Y);

    //draw the second string in a different color
    e.Graphics.DrawString(data(data.Length - 1 - e.Index), oFont, new SolidBrush(color(color.Length - 1 - e.Index)), width, e.Bounds.Y);
}

Upvotes: 2

Related Questions