1
votes

I need to change the color of the ProgressBar depending on the value I assign it. If the value is above 50, it should be green, if it's between 20 and 50, it should be yellow and if it's below 20, it should be red.

I found a great answer here on how to change the color of the ProgressBar. I tested it and it works. However it's written as an extension method.

public static class ModifyProgressBarColor
{
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);
    public static void SetState(this ProgressBar pBar, int state)
    {
        SendMessage(pBar.Handle, 1040, (IntPtr)state, IntPtr.Zero);
    }
}

I want the color to change when you set the value for the Value property of the ProgressBar instead of having to manually assign it.

So I subclassed the ProgressBar class. Here's what I did.

using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace MyApp
{
    class MyProgressBar: ProgressBar
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);

        public int Value
        {
            set
            {
                if (value > 50)
                {
                    SendMessage(this.Handle, 1040, (IntPtr)1, IntPtr.Zero);
                }
                else if (value < 50 && value > 20)
                {
                    SendMessage(this.Handle, 1040, (IntPtr)2, IntPtr.Zero);
                }
                else if (value < 20)
                {
                    SendMessage(this.Handle, 1040, (IntPtr)3, IntPtr.Zero);
                }
            }
        }
    }
}

The control shows up in the Toolbox.

enter image description here

But when I set the Value in code, nothing shows up in the ProgressBar!

Any idea what I'm missing here?

2
Your public int Value should give you a Warning about hiding a base class member. Therein lies your answer.Henk Holterman
Ohh I get it. Sorry I'm kinda new to C#. So since I want to override the property, I changed the signature to this public override int Value but now I get the error Cannot override inherited member because it is not marked virtual abstract or override. I guess at this point, there's nothing that can be done?Isuru
Look around in the class (F12) , there probably is a virtual OnvalueChanged method.Henk Holterman
This answer posted below solved the issue. You can actually assign a value to the base class. I didn't know that. Thank you for your help.Isuru
Since that is not virtual in any way I would prefer to name the new property something else than Value. Makes it much clearer what's going on.Henk Holterman

2 Answers

1
votes

Don't forget to pass the value through to the base class, otherwise the underlying ProgressBar will have no idea the value changed.

public new int Value
{
    set
    {
        base.Value = value;

        if (value > 50)
        {
            SendMessage(this.Handle, 1040, (IntPtr)1, IntPtr.Zero);
        }
        else if (value < 50 && value > 20)
        {
            SendMessage(this.Handle, 1040, (IntPtr)2, IntPtr.Zero);
        }
        else if (value < 20)
        {
            SendMessage(this.Handle, 1040, (IntPtr)3, IntPtr.Zero);
        }
    }
}
1
votes

The Value property should be implemented as follows:

    public new int Value
    {
        set
        {
            // other things you do here...

            base.Value = value; // this was missing
        }
    }