progressbar - show progress bar c#




Come inserisco il testo su ProgressBar? (5)

Ho usato ProgressBar Control nella mia applicazione desktop c #. L'ho usato in una discussione diversa dal thread in cui è stato dichiarato il controllo. Funziona correttamente. Ora mi chiedo come posso mostrare del testo all'interno del controllo della barra di avanzamento come "Iniziare la registrazione" ecc. Inoltre, voglio usarlo come barra di avanzamento del Marquee. Per favore aiutatemi.


EVITARE IL TESTO DI FLICKING

La solution fornita da Barry sopra è eccellente, ma c'è il "problema di sfarfallio".

Non appena il valore è superiore allo zero, OnPaint verrà invocato ripetutamente e il testo lampeggerà.

C'è una soluzione a questo. Non abbiamo bisogno di VisualStyles per l'oggetto poiché lo disegneremo con il nostro codice.

Aggiungi il seguente codice all'oggetto personalizzato che Barry ha scritto ed eviterai lo sfarfallio:

    [DllImportAttribute("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);
    }

Non l'ho scritto io stesso Lo ha trovato qui: https://.com/a/299983/1163954

L'ho testato e funziona.


Allitterativamente puoi provare a posizionare un controllo Label e posizionarlo sopra il controllo della barra di avanzamento. Quindi puoi impostare qualunque sia il testo che desideri sull'etichetta. Non l'ho fatto da solo. Se funziona dovrebbe essere una soluzione più semplice che ignorare onpaint.


Ho creato un controllo InfoProgressBar che utilizza un controllo TransparentLabel. Provando su un modulo con un Timer, ottengo alcuni piccoli difetti che visualizzano il testo ogni 30-40 cambiamenti di valore se si utilizza un intervallo del timer inferiore a 250 millisecondi (probabilmente a causa del tempo necessario per aggiornare lo schermo è maggiore dell'intervallo del timer) .

Sarebbe possibile modificare il metodo UpdateText per inserire tutti i valori calcolati in CustomText, ma non è qualcosa che ho ancora bisogno. Ciò eliminerebbe la necessità per la proprietà DisplayType e l'enumerazione.

La classe TransparentLabel è stata creata aggiungendo un nuovo UserControl e modificandolo per ereditare da Label con la seguente implementazione:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Utils.GUI
{
    public partial class TransparentLabel : Label
    {
        // hide the BackColor attribute as much as possible.
        // setting the base value has no effect as drawing the
        // background is disabled
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override Color BackColor
        {
            get
            {
                return Color.Transparent;
            }
            set
            {
            }
        }

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x20; //  WS_EX_TRANSPARENT
                return cp;
            }
        }

        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
                base.Text = value;
                if(Parent != null) Parent.Invalidate(Bounds, false);
            }
        }

        public override ContentAlignment TextAlign
        {
            get
            {
                return base.TextAlign;
            }
            set
            {
                base.TextAlign = value;
                if(Parent != null) Parent.Invalidate(Bounds, false);
            }
        }

        public TransparentLabel()
        {
            InitializeComponent();

            SetStyle(ControlStyles.Opaque, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, false);

            base.BackColor = Color.Transparent;
        }

        protected override void OnMove(EventArgs e)
        {
            base.OnMove(e);
            RecreateHandle();
        }

        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            // do nothing
        }
    }
}

Non ho apportato alcuna modifica al codice del designer correlato, ma qui è per completezza.

namespace Utils.GUI
{
    partial class TransparentLabel
    {
        /// <summary> 
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if(disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code

        /// <summary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
        }

        #endregion
    }
}

Ho quindi creato un altro nuovo UserControl e l'ho modificato per derivare da ProgressBar con la seguente implementazione:

using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;

namespace Utils.GUI
{
    [Designer(typeof(InfoProgressBarDesigner))]
    public partial class InfoProgressBar : ProgressBar
    {
        // designer class to add font baseline snapline by copying it from the label
        private class InfoProgressBarDesigner : ControlDesigner
        {
            public override IList SnapLines
            {
                get
                {
                    IList snapLines = base.SnapLines;

                    InfoProgressBar control = Control as InfoProgressBar;

                    if(control != null)
                    {
                        using(IDesigner designer = TypeDescriptor.CreateDesigner(control.lblText, typeof(IDesigner)))
                        {
                            if(designer != null)
                            {
                                designer.Initialize(control.lblText);

                                ControlDesigner boxDesigner = designer as ControlDesigner;

                                if(boxDesigner != null)
                                {
                                    foreach(SnapLine line in boxDesigner.SnapLines)
                                    {
                                        if(line.SnapLineType == SnapLineType.Baseline)
                                        {
                                            snapLines.Add(new SnapLine(SnapLineType.Baseline, line.Offset, line.Filter, line.Priority));
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    return snapLines;
                }
            }
        }

        // enum to select the type of displayed value
        public enum ProgressBarDisplayType
        {
            Custom = 0,
            Percent = 1,
            Progress = 2,
            Remain = 3,
            Value = 4,
        }

        private string _customText;
        private ProgressBarDisplayType _displayType;
        private int _range;

        [Bindable(false)]
        [Browsable(true)]
        [DefaultValue("{0}")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        // {0} is replaced with the result of the selected calculation
        public string CustomText
        {
            get
            {
                return _customText;
            }
            set
            {
                _customText = value;
                UpdateText();
            }
        }

        [Bindable(false)]
        [Browsable(true)]
        [DefaultValue(ProgressBarDisplayType.Percent)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        public ProgressBarDisplayType DisplayType
        {
            get
            {
                return _displayType;
            }
            set
            {
                _displayType = value;
                UpdateText();
            }
        }

        [Bindable(false)]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        // don't use the lblText font as if it is null, it checks the parent font (i.e. this property) and gives an infinite loop
        public override Font Font
        {
            get
            {
                return base.Font;
            }
            set
            {
                base.Font = value; 
            }
        }

        [Bindable(false)]
        [Browsable(true)]
        [DefaultValue(100)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        public new int Maximum
        {
            get
            {
                return base.Maximum;
            }
            set
            {
                base.Maximum = value;
                _range = base.Maximum - base.Minimum;
                UpdateText();
            }
        }

        [Bindable(false)]
        [Browsable(true)]
        [DefaultValue(0)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        public new int Minimum
        {
            get
            {
                return base.Minimum;
            }
            set
            {
                base.Minimum = value;
                _range = base.Maximum - base.Minimum;
                UpdateText();
            }
        }

        [Bindable(false)]
        [Browsable(true)]
        [DefaultValue(ContentAlignment.MiddleLeft)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        public ContentAlignment TextAlign 
        {
            get
            {
                return lblText.TextAlign;
            }
            set
            {
                lblText.TextAlign = value;
            }
        }

        [Bindable(false)]
        [Browsable(true)]
        [DefaultValue(typeof(Color), "0x000000")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        public Color TextColor
        {
            get
            {
                return lblText.ForeColor;
            }
            set
            {
                lblText.ForeColor = value;
            }
        }

        [Bindable(false)]
        [Browsable(true)]
        [DefaultValue(0)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        public new int Value
        {
            get
            {
                return base.Value;
            }
            set
            {
                base.Value = value;
                UpdateText();
            }
        }

        public InfoProgressBar()
        {
            InitializeComponent();

            CustomText = "{0}";
            DisplayType = ProgressBarDisplayType.Percent;
            Maximum = 100;
            Minimum = 0;
            TextAlign = ContentAlignment.MiddleLeft;
            TextColor = Color.Black;
            Value = 0;

            // means the label gets drawn in front of the progress bar
            lblText.Parent = this;

            _range = base.Maximum - base.Minimum;
        }

        protected void UpdateText()
        {
            switch(DisplayType)
            {
                case ProgressBarDisplayType.Custom:
                {
                    lblText.Text = _customText;
                    break;
                }
                case ProgressBarDisplayType.Percent:
                {
                    if(_range > 0)
                    {
                        lblText.Text = string.Format(_customText, string.Format("{0}%", (int)((Value * 100) / _range)));
                    }
                    else
                    {
                        lblText.Text = "100%";
                    }
                    break;
                }
                case ProgressBarDisplayType.Progress:
                {
                    lblText.Text = string.Format(_customText, (Value - Minimum));
                    break;
                }
                case ProgressBarDisplayType.Remain:
                {
                    lblText.Text = string.Format(_customText, (Maximum - Value));
                    break;
                }
                case ProgressBarDisplayType.Value:
                {
                    lblText.Text = string.Format(_customText, Value);
                    break;
                }
            }
        }

        public new void Increment(int value)
        {
            base.Increment(value);
            UpdateText();
        }

        public new void PerformStep()
        {
            base.PerformStep();
            UpdateText();
        }
    }
}

E il codice del designer:

namespace Utils.GUI
{
    partial class InfoProgressBar
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if(disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.lblText = new Utils.GUI.TransparentLabel();
            this.SuspendLayout();
            // 
            // lblText
            // 
            this.lblText.BackColor = System.Drawing.Color.Transparent;
            this.lblText.Dock = System.Windows.Forms.DockStyle.Fill;
            this.lblText.Location = new System.Drawing.Point(0, 0);
            this.lblText.Name = "lblText";
            this.lblText.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
            this.lblText.Size = new System.Drawing.Size(100, 23);
            this.lblText.TabIndex = 0;
            this.lblText.Text = "transparentLabel1";
            this.ResumeLayout(false);

        }

        #endregion

        private TransparentLabel lblText;

    }
}

Ho provato a posizionare un'etichetta con sfondo trasparente su una barra di avanzamento, ma non ho mai funzionato correttamente. Quindi ho trovato la soluzione di Barry molto utile, anche se mi mancava la bellissima barra di progresso in stile Vista. Quindi ho unito la soluzione di Barry con http://www.dreamincode.net/forums/topic/243621-percent-into-progress-bar/ e sono riuscito a mantenere la barra di avanzamento nativa, visualizzando la percentuale di testo o il testo personalizzato su di essa. Neanche io vedo uno sfarfallio in questa soluzione. Mi dispiace scovare e vecchio thread ma ne avevo bisogno oggi e quindi anche altri potrebbero averne bisogno.

public enum ProgressBarDisplayText
{
    Percentage,
    CustomText
}

class ProgressBarWithCaption : ProgressBar
{
    //Property to set to decide whether to print a % or Text
    private ProgressBarDisplayText m_DisplayStyle;
    public ProgressBarDisplayText DisplayStyle {
        get { return m_DisplayStyle; }
        set { m_DisplayStyle = value; }
    }

    //Property to hold the custom text
    private string m_CustomText;
    public string CustomText {
        get { return m_CustomText; }
        set {
            m_CustomText = value;
            this.Invalidate();
        }
    }

    private const int WM_PAINT = 0x000F;
    protected override void WndProc(ref Message m)
    {
        base.WndProc(m);

        switch (m.Msg) {
            case WM_PAINT:
                int m_Percent = Convert.ToInt32((Convert.ToDouble(Value) / Convert.ToDouble(Maximum)) * 100);
                dynamic flags = TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter | TextFormatFlags.SingleLine | TextFormatFlags.WordEllipsis;

                using (Graphics g = Graphics.FromHwnd(Handle)) {
                    using (Brush textBrush = new SolidBrush(ForeColor)) {

                        switch (DisplayStyle) {
                            case ProgressBarDisplayText.CustomText:
                                TextRenderer.DrawText(g, CustomText, new Font("Arial", Convert.ToSingle(8.25), FontStyle.Regular), new Rectangle(0, 0, this.Width, this.Height), Color.Black, flags);
                                break;
                            case ProgressBarDisplayText.Percentage:
                                TextRenderer.DrawText(g, string.Format("{0}%", m_Percent), new Font("Arial", Convert.ToSingle(8.25), FontStyle.Regular), new Rectangle(0, 0, this.Width, this.Height), Color.Black, flags);
                                break;
                        }

                    }
                }

                break;
        }

    }

}

Wold creo un controllo chiamato ad esempio InfoProgresBar, che fornisce questa funzionalità con un'etichetta o due (Main Job, Current Job) e ProgressBar e la usa al posto di quella ProgressBar.





progress-bar