Изменение цвета фона пользовательского индикатора выполнения с меткой - PullRequest
0 голосов
/ 02 марта 2020

Создание пользовательского элемента управления, LabelProgressBar, с меткой в ​​верхней части индикатора выполнения, предназначенного для отображения либо его завершенного значения в процентах, либо пользовательского текста. Этот элемент управления получен из System.Windows.Forms.ProgressBar.

Ниже приведен код для пользовательского элемента управления:

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

namespace labelProgressBarControl
{ 
    public enum LabelProgressBarText
    { 
        PERCENTAGE, CUSTOM_TEXT
    }

    public partial class LabelProgressBar : System.Windows.Forms.ProgressBar
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);
        public void setState(int state)
        {
            SendMessage(this.Handle, 1040, (IntPtr)state, IntPtr.Zero);
        }

        // property to set whether to display percentage or custom text
        public LabelProgressBarText displayStyle {get; set;}

        // property to hold the custom text
        public string customText {get; set;}

        // property to hold the colour
        public Color colour {get; set;}

        // change colour and text
        public void changeColourAndText(Color colour, string text)
        {
             // set the properties
             this.colour = colour;
             this.customText = text;

             // change the display style to custom text
             this.displayStyle = LabelProgressBarText.CUSTOM_TEXT;

             // refresh the control, forcing a repaint
             this.Invalidate();
             this.Update();
        } 

        // ctor
        public LabelProgressBar()
        {
             SetStyle(System.Windows.Forms.ControlStyles.UserPaint | System.Windows.Forms.ControlStyles.AllPaintingInWmPaint, true);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            LinearGradientBrush brush = null;

            System.Drawing.Rectangle rect = ClientRectangle;
            System.Drawing.Graphics g = e.Graphics;

            ProgressBarRenderer.DrawHorizontalBar(g, rect);
            rect.Inflate(-3,3);

            brush = new LinearGradientBrush(rect, colour, colour, LinearGradientMode.Vertical);
            e.Graphics.FillRectangle(brush, 2, 2, rect.Width, rect.Height);

            if (Value > 0)
            {
                 System.Drawing.Rectangle clip = new System.Drawing.Rectangle(rect.X-3, rect.Y, (int)Math.Round(((float)Value / Maximum) * rect.Width)+6, rect.Height);
                 ProgressBarRenderer.DrawHorizontalChunks(g, clip);
            }

            // set the display text (either a percentage or custom text)
            string text = displayStyle == LabelProgressBarText.PERCENTAGE ? Value.ToString() + '%' : customText;

            System.Drawing.Font labelFont = new System.Drawing.Font(System.Drawing.FontFamily.GenericSansSerif, (float)8.25, System.Drawing.FontStyle.Regular);
            System.Drawing.SizeF len = g.MeasureString(text, System.Drawing.SystemFonts.MessageBoxFont);

            // calculate the location of the text (the middle of the progress bar)
            System.Drawing.Point location = new System.Drawing.Point(Convert.ToInt32((Width / 2) - len.Width / 2), System.Convert.ToInt32((Height/2) - len.Height / 2));

            // draw the custom text
            g.DrawString(text, System.Drawing.SystemFonts.MessageBoxFont, System.Drawing.Brushes.Black, location);

        }

        // prevent OnPaint being invoked repeatedly, to stop flickering
        [DllImport("uxtheme.dll")]
        private static extern int SetWindowTheme(IntPtr hWnd, string appname, string idlist);
        protected override void OnHandleCreated(EventArgs e)
        {
             SetWindowTheme(this.Handle, "", "");
             base.OnHandleCreated(e)
        }
    }
}

Ниже приведен частичный код для тестового приложения.

// the text is changing, but the colour always remains green
private void button_success_Click(object sender, EventArgs e)
{
    labelProgressBar1.changeColourAndText(Color.Green, "Success");
} 

private void button_fail_Click(object sender, EventArgs e)
{
    labelProgressBar1.changeColourAndText(Color.Red, "Fail");
}

Это приложение имеет «запуск» "кнопка, которая запускает BackgroundWorker, имитируя тяжелую работу, которая заканчивается через некоторое время. После завершения активируются две кнопки, предназначенные для имитации успеха или неудачи.

Текст меняется, но цвет остается зеленым. Как решить эту проблему?

Что было опробовано: this.Invalidate(), this.Update() и this.Refresh() в методе changeColourAndText в коде элемента управления, чтобы вызвать перерисовку элемента управления. Кроме того, отключение визуальных стилей, но это неподходящий вариант, так как элементы управления не должны выглядеть так.

...