A Generic Bar of Rectangular LED

A simple LEDBar

A string of rectangular LED

Based upon the 12 off 4 colour rectangular LED in a row, a LED Bar is created. The reading is shown both as a percentage and colour bar. There is an override LED that is set to illuminate red at 120%. The value text can be overwritten to a more meaningfull value (See VU meter).

The LED are refered to a numbers 0 to 12 to represent the number of LED to be illuminated. With 0 all LED are grey. With 12 all LED are red and OVER flashed as the value. There is a middle threshold and upper threshold. Below the middle threshold the LED are green, above the middle threshold but below the upper threshold the LED are yellow and above the upper threshold red. The ovverange is always red.

    [Description("LedBar")]
    [Designer(typeof(LedBarDesigner))]
    public partial class LedBar : UserControl
        {
            private UInt32 middle_threshold = 12;
            private UInt32 upper_threshold = 12;
            private Boolean bOverload = true;
            private Boolean bTextOverride = false;
            private UInt32 led_number = 0;
            private Int32 led_width = 15;
            private Int32 led_height = 10;
            private Int32 led_x_location = 7;
            private Int32 led_y_location = 20;
            private Int32 ledover_width = 10;
            private Int32 ledover_height = 20;
            private Int32 ledover_space = 3;

            private const Int32 base_led_width = 15;
            private const Int32 base_led_height = 10;
            private const Int32 base_led_space = 1;
            private const Int32 base_led_x_location = 7;
            private const Int32 base_led_y_location = 20;
            private const Int32 base_overled_x_location = 186;
            private const Int32 base_overled_y_location = 13;
            private const Int32 base_level_label_x_location = 135;
            private const Int32 base_level_label_y_location = 10;
            private const Int32 base_group_width = 200;
            private const Int32 base_group_height = 35;
            private const Int32 base_border = 2;

            private String sCurrentText = ";
            private String sNewText = ";

            public LedBar()
            {
                InitializeComponent();

                locate_led();
                LevelLabel.ForeColor = LedGroup.ForeColor;
            }


            private void locate_led()
            {
                //  Set up led locations and size as per values given width of group box. Base 192 and increments of 11
                Led1.Location = new Point(led_x_location, led_y_location);
                Led1.SizeOfLed = new Size((Int32)led_width, (Int32)led_height);
                UInt32 spacing = (UInt32)(led_width + base_led_space);
                Led2.Location = new Point((Int32)(led_x_location + spacing), (Int32)led_y_location);
                Led2.SizeOfLed = new Size((Int32)led_width, (Int32)led_height);
                Led3.Location = new Point((Int32)(led_x_location + (2 * spacing)), (Int32)led_y_location);
                Led3.SizeOfLed = new Size((Int32)led_width, (Int32)led_height);
                Led4.Location = new Point((Int32)(led_x_location + (3 * spacing)), (Int32)led_y_location);
                Led4.SizeOfLed = new Size((Int32)led_width, (Int32)led_height);
                Led5.Location = new Point((Int32)(led_x_location + (4 * spacing)), (Int32)led_y_location);
                Led5.SizeOfLed = new Size((Int32)led_width, (Int32)led_height);
                Led6.Location = new Point((Int32)(led_x_location + (5 * spacing)), (Int32)led_y_location);
                Led6.SizeOfLed = new Size((Int32)led_width, (Int32)led_height);
                Led7.Location = new Point((Int32)(led_x_location + (6 * spacing)), (Int32)led_y_location);
                Led7.SizeOfLed = new Size((Int32)led_width, (Int32)led_height);
                Led8.Location = new Point((Int32)(led_x_location + (7 * spacing)), (Int32)led_y_location);
                Led8.SizeOfLed = new Size((Int32)led_width, (Int32)led_height);
                Led9.Location = new Point((Int32)(led_x_location + (8 * spacing)), (Int32)led_y_location);
                Led9.SizeOfLed = new Size((Int32)led_width, (Int32)led_height);
                Led10.Location = new Point((Int32)(led_x_location + (9 * spacing)), (Int32)led_y_location);
                Led10.SizeOfLed = new Size((Int32)led_width, (Int32)led_height);
                Led11.Location = new Point((Int32)(led_x_location + (10 * spacing)), (Int32)led_y_location);
                Led11.SizeOfLed = new Size(led_width, led_height);
                LedOver.Location = new Point((Int32)(led_x_location + (11 * spacing) + ledover_space), base_overled_y_location);
                LedOver.SizeOfLed = new Size(ledover_width, ledover_height + (led_height - base_led_height));
                LedOver.Visible = bOverload;
                LevelLabel.Location = new Point(Led9.Location.X, (Int32)base_level_label_y_location);
            }

            [Description("LedBar middle threshold")]
            [Category("Threshold")]
            public UInt32 Middle
            {
                get { return middle_threshold; }
                set
                {
                    if (value > 12) value = 12;
                    middle_threshold = value;
                    if (middle_threshold > upper_threshold) upper_threshold = middle_threshold;
                }
            }

            [Description("LedBar upper threshold")]
            [Category("Threshold")]
            public UInt32 Upper
            {
                get { return upper_threshold; }
                set
                {
                    if (value > 12) value = 12;
                    upper_threshold = value;
                    if (upper_threshold < middle_threshold) upper_threshold = middle_threshold;
                }
            }

            [Description("LedBar overload")]
            [Category("Threshold")]
            public Boolean Overload
            {
                get { return bOverload; }
                set
                {
                    bOverload = value;
                    LedOver.Visible = value;
                }
            }

            [Description("LedBar led number")]
            [Category("Threshold")]
            public UInt32 Value
            {
                get { return led_number; }
                set
                {
                    //  Sets the bar value 0 to 12 along with threshold detection
                    UInt32 led_set = value;
                    if (led_set > 12) led_set = 12;
                    if (led_set > 0)
                    {
                        if (middle_threshold > 1) Led1.State = "GREEN";
                        else if (middle_threshold <= 1) Led1.State = "YELLOW";
                    }
                    else Led1.State = "GREY";
                    if (led_set > 1)
                    {
                        if (middle_threshold > 2) Led2.State = "GREEN";
                        else if ((middle_threshold <= 2) && (upper_threshold > 2)) Led2.State = "YELLOW";
                        else Led2.State = "RED";
                    }
                    else Led2.State = "GREY";
                    if (led_set > 2)
                    {
                        if (middle_threshold > 3) Led3.State = "GREEN";
                        else if ((middle_threshold <= 3) && (upper_threshold > 3)) Led3.State = "YELLOW";
                        else Led3.State = "RED";
                    }
                    else Led3.State = "GREY";
                    if (led_set > 3)
                    {
                        if (middle_threshold > 4) Led4.State = "GREEN";
                        else if ((middle_threshold <= 4) && (upper_threshold > 4)) Led4.State = "YELLOW";
                        else Led4.State = "RED";
                    }
                    else Led4.State = "GREY";
                    if (led_set > 4)
                    {
                        if (middle_threshold > 5) Led5.State = "GREEN";
                        else if ((middle_threshold <= 5) && (upper_threshold > 5)) Led5.State = "YELLOW";
                        else Led5.State = "RED";
                    }
                    else Led5.State = "GREY";
                    if (led_set > 5)
                    {
                        if (middle_threshold > 6) Led6.State = "GREEN";
                        else if ((middle_threshold <= 6) && (upper_threshold > 6)) Led6.State = "YELLOW";
                        else Led6.State = "RED";
                    }
                    else Led6.State = "GREY";
                    if (led_set > 6)
                    {
                        if (middle_threshold > 7) Led7.State = "GREEN";
                        else if ((middle_threshold <= 7) && (upper_threshold > 7)) Led7.State = "YELLOW";
                        else Led7.State = "RED";
                    }
                    else Led7.State = "GREY";
                    if (led_set > 7)
                    {
                        if (middle_threshold > 8) Led8.State = "GREEN";
                        else if ((middle_threshold <= 8) && (upper_threshold > 8)) Led8.State = "YELLOW";
                        else Led8.State = "RED";
                    }
                    else Led8.State = "GREY";
                    if (led_set > 8)
                    {
                        if (middle_threshold > 9) Led9.State = "GREEN";
                        else if ((middle_threshold <= 9) && (upper_threshold > 9)) Led9.State = "YELLOW";
                        else Led9.State = "RED";
                    }
                    else Led9.State = "GREY";
                    if (led_set > 9)
                    {
                        if (middle_threshold > 10) Led10.State = "GREEN";
                        else if ((middle_threshold <= 10) && (upper_threshold > 10)) Led10.State = "YELLOW";
                        else Led10.State = "RED";
                    }
                    else Led10.State = "GREY";
                    if (led_set > 10)
                    {
                        if (middle_threshold > 11) Led11.State = "GREEN";
                        else if ((middle_threshold <= 11) && (upper_threshold > 11)) Led11.State = "YELLOW";
                        else Led11.State = "RED";
                    }
                    else Led11.State = "GREY";
                    if ((led_set > 11) && bOverload)
                    {
                        LedOver.State = "RED";
                    }
                    else if (bOverload) LedOver.State = "GREY";
                    led_number = led_set;
                    if (led_number == 0) sCurrentText = "0%";
                    else if (led_number == 1) sCurrentText = "10%";
                    else if (led_number == 2) sCurrentText = "20%";
                    else if (led_number == 3) sCurrentText = "30%";
                    else if (led_number == 4) sCurrentText = "40%";
                    else if (led_number == 5) sCurrentText = "50%";
                    else if (led_number == 6) sCurrentText = "60%";
                    else if (led_number == 7) sCurrentText = "70%";
                    else if (led_number == 8) sCurrentText = "80%";
                    else if (led_number == 9) sCurrentText = "90%";
                    else if (led_number == 10) sCurrentText = "100%";
                    else if (led_number == 11) sCurrentText = "110%";
                    else if (led_number >= 12) sCurrentText = "OVER";
                    if (bTextOverride == false)
                    {
                        LevelLabel.Text = sCurrentText;
                        if (led_number >= 12)
                        {
                            LevelLabel.ForeColor = Color.Red;
                            Led1.State = "RED";
                            Led2.State = "RED";
                            Led3.State = "RED";
                            Led4.State = "RED";
                            Led5.State = "RED";
                            Led6.State = "RED";
                            Led7.State = "RED";
                            Led8.State = "RED";
                            Led9.State = "RED";
                            Led10.State = "RED";
                            Led11.State = "RED";
                        }
                        else LevelLabel.ForeColor = LedGroup.ForeColor;
                    }
                    else
                    {
                        LevelLabel.Text = sNewText;
                        if (led_number >= 12) LevelLabel.ForeColor = Color.Red;
                        else LevelLabel.ForeColor = LedGroup.ForeColor;
                    }
                }
            }

            public void Level_Text(ref String _sCurrentText, String _sNewText, Boolean _bTextOverride)
            {
                _sCurrentText = sCurrentText;
                sNewText = _sNewText;
                bTextOverride = _bTextOverride;
                if (bTextOverride) LevelLabel.Text = sNewText;
                return;
            }

            [Description("LedBar background colour")]
            [Category("Appearance")]
            public Color BackColour
            {
                get { return LedGroup.BackColor; }
                set
                {
                    LedGroup.BackColor = value;
                    this.BackColor = value;
                }
            }

            [Description("LedBar title")]
            [Category("Appearance")]
            public String Title { get { return LedGroup.Text; } set { LedGroup.Text = value; } }

            [Description("LedBar size")]
            [Category("Layout")]
            public Size BarSize
            {
                get { return LedGroup.Size; }
                set
                {
                    if (value.Width < base_group_width) value.Width = base_group_width;
                    if (value.Height < base_group_height) value.Height = base_group_height;
                    LedGroup.Size = value;
                    this.Size = new Size((value.Width + base_border), (value.Height + base_border));
                    //  re-order led positions and led sizes. Led size must move right and down only.
                    //  The led width increments 1 for jumps of 11 of group width
                    //  For fractions of 11 the whole led array is displace right by 1 for each increment of 2
                    Int32 group_width_increase = value.Width - base_group_width;
                    Int32 led_width_increase = group_width_increase / 11;
                    Int32 led_width_fraction = group_width_increase - (11 * led_width_increase);
                    led_width = base_led_width + led_width_increase;
                    Int32 led_bar_displacement = led_width_fraction / 2;
                    led_width = base_led_width + led_width_increase;
                    led_x_location = base_led_x_location + led_bar_displacement;
                    //  In the vertical the led height increases by 1 for every increment of 2
                    Int32 group_height_increase = value.Height - base_group_height;
                    led_height = base_led_height + group_height_increase;
                    //  Re-locate Led
                    locate_led();
                }
            }
        }

The sizing of the container and group box containing the LED array uses the BarSize property to override the default stretching. If a width stretch is used the result is uneven LED width since the change in width has to be distributed across all the 11 rectangular LED. This looks off skew so the change in size is done in two steps. There are 11 rectangular and 10 spaces, thus on increase of width an 11 modulus is used to calculate the distribution of the change between a change in LED width and movement of the LED bar location.

As an example of a width change of 27 pixels. Taking the 11 modulus this is a change of 2 units with a fraction of 5. So each LED width is increase by 2, maintaining the same spacing the new locations are calculated for the rectangular LED and the overrride LED. The fraction is taken to modulus 2 giving an integer fraction of 2 and ignoring the left over. The whole LED group is then moved 2 pixels to the right. In this way a constant LED width is maintained.

Regarding changes in height the LED vertical location is held and the LED height changed ie: fattened.

The function Level_Text is used to overwrite the value reading of % for something more usefull.

        private void InitializeComponent()
        {
            this.LedGroup = new System.Windows.Forms.GroupBox();
            this.LevelLabel = new System.Windows.Forms.Label();
            this.LedOver = new ComponentLibrary.RectLed();
            this.Led11 = new ComponentLibrary.RectLed();
            this.Led10 = new ComponentLibrary.RectLed();
            this.Led9 = new ComponentLibrary.RectLed();
            this.Led8 = new ComponentLibrary.RectLed();
            this.Led7 = new ComponentLibrary.RectLed();
            this.Led6 = new ComponentLibrary.RectLed();
            this.Led5 = new ComponentLibrary.RectLed();
            this.Led4 = new ComponentLibrary.RectLed();
            this.Led3 = new ComponentLibrary.RectLed();
            this.Led2 = new ComponentLibrary.RectLed();
            this.Led1 = new ComponentLibrary.RectLed();
            this.LedGroup.SuspendLayout();
            this.SuspendLayout();
            // 
            // LedGroup
            // 
            this.LedGroup.BackColor = System.Drawing.Color.Bisque;
            this.LedGroup.Controls.Add(this.LevelLabel);
            this.LedGroup.Controls.Add(this.LedOver);
            this.LedGroup.Controls.Add(this.Led11);
            this.LedGroup.Controls.Add(this.Led10);
            this.LedGroup.Controls.Add(this.Led9);
            this.LedGroup.Controls.Add(this.Led8);
            this.LedGroup.Controls.Add(this.Led7);
            this.LedGroup.Controls.Add(this.Led6);
            this.LedGroup.Controls.Add(this.Led5);
            this.LedGroup.Controls.Add(this.Led4);
            this.LedGroup.Controls.Add(this.Led3);
            this.LedGroup.Controls.Add(this.Led2);
            this.LedGroup.Controls.Add(this.Led1);
            this.LedGroup.Location = new System.Drawing.Point(1, 1);
            this.LedGroup.MinimumSize = new System.Drawing.Size(200, 35);
            this.LedGroup.Name = "LedGroup";
            this.LedGroup.Size = new System.Drawing.Size(200, 35);
                    this.LedGroup.TabIndex = 0;
                    this.LedGroup.TabStop = false;
                    this.LedGroup.Text = "LedBar";
                    // 
                    // LevelLabel
                    // 
                    this.LevelLabel.Location = new System.Drawing.Point(130, 10);
                    this.LevelLabel.Name = "LevelLabel";
                    this.LevelLabel.Size = new System.Drawing.Size(50, 12);
                    this.LevelLabel.TabIndex = 0;
                    this.LevelLabel.Text = "0%";
                    this.LevelLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
                    // 
                    // LedOver
                    // 
                    this.LedOver.AutoSize = true;
                    this.LedOver.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.LedOver.Location = new System.Drawing.Point(186, 13);
                    this.LedOver.Name = "RectLed";
                    this.LedOver.SizeOfLed = new System.Drawing.Size(10, 20);
                    this.LedOver.State = "GREY";
                    // 
                    // Led11
                    // 
                    this.Led11.AutoSize = true;
                    this.Led11.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led11.Location = new System.Drawing.Point(167, 20);
                    this.Led11.Name = "RectLed";
                    this.Led11.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led11.State = "GREY";
                    // 
                    // Led10
                    // 
                    this.Led10.AutoSize = true;
                    this.Led10.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led10.Location = new System.Drawing.Point(151, 20);
                    this.Led10.Name = "RectLed";
                    this.Led10.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led10.State = "GREY";
                    // 
                    // Led9
                    // 
                    this.Led9.AutoSize = true;
                    this.Led9.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led9.Location = new System.Drawing.Point(135, 20);
                    this.Led9.Name = "RectLed";
                    this.Led9.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led9.State = "GREY";
                    // 
                    // Led8
                    // 
                    this.Led8.AutoSize = true;
                    this.Led8.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led8.Location = new System.Drawing.Point(119, 20);
                    this.Led8.Name = "RectLed";
                    this.Led8.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led8.State = "GREY";
                    // 
                    // Led7
                    // 
                    this.Led7.AutoSize = true;
                    this.Led7.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led7.Location = new System.Drawing.Point(103, 20);
                    this.Led7.Name = "RectLed";
                    this.Led7.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led7.State = "GREY";
                    // 
                    // Led6
                    // 
                    this.Led6.AutoSize = true;
                    this.Led6.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led6.Location = new System.Drawing.Point(87, 20);
                    this.Led6.Name = "RectLed";
                    this.Led6.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led6.State = "GREY";
                    // 
                    // Led5
                    // 
                    this.Led5.AutoSize = true;
                    this.Led5.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led5.Location = new System.Drawing.Point(71, 20);
                    this.Led5.Name = "RectLed";
                    this.Led5.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led5.State = "GREY";
                    // 
                    // Led4
                    // 
                    this.Led4.AutoSize = true;
                    this.Led4.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led4.Location = new System.Drawing.Point(55, 20);
                    this.Led4.Name = "RectLed";
                    this.Led4.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led4.State = "GREY";
                    // 
                    // Led3
                    // 
                    this.Led3.AutoSize = true;
                    this.Led3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led3.Location = new System.Drawing.Point(39, 20);
                    this.Led3.Name = "RectLed";
                    this.Led3.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led3.State = "GREY";
                    // 
                    // Led2
                    // 
                    this.Led2.AutoSize = true;
                    this.Led2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led2.Location = new System.Drawing.Point(23, 20);
                    this.Led2.Name = "RectLed";
                    this.Led2.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led2.State = "GREY";
                    // 
                    // Led1
                    // 
                    this.Led1.AutoSize = true;
                    this.Led1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                    this.Led1.Location = new System.Drawing.Point(7, 20);
                    this.Led1.Name = "RectLed";
                    this.Led1.SizeOfLed = new System.Drawing.Size(15, 10);
                    this.Led1.State = "GREY";
                    // 
                    // LedBar
                    // 
                    this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                    this.Controls.Add(this.LedGroup);
                    this.Name = "LedBar";
                    this.Size = new System.Drawing.Size(202, 37);
                    this.LedGroup.ResumeLayout(false);
                    this.LedGroup.PerformLayout();
                    this.ResumeLayout(false);

                }

        private System.Windows.Forms.GroupBox LedGroup;
        private RectLed Led1;
        private RectLed Led11;
        private RectLed Led10;
        private RectLed Led9;
        private RectLed Led8;
        private RectLed Led7;
        private RectLed Led6;
        private RectLed Led5;
        private RectLed Led4;
        private RectLed Led3;
        private RectLed Led2;
        private RectLed LedOver;
        private System.Windows.Forms.Label LevelLabel;

The designer can be copied or the equivalent generated by hand by changing the properties of the designer form. The properties must coincide with that required by the .cs code. Note: only InitializeComponent() and declarations are here, the rest of the designer does not change!

    internal class LedBarDesigner : System.Windows.Forms.Design.ControlDesigner
    {
        public void LedBarDesigned()
        { }
        // clean up some unnecessary properties
        protected override void PreFilterProperties(IDictionary Properties)
        {
            Properties.Remove("BackColor");
            Properties.Remove("Size");
                    Properties.Remove("RightToLeft");
                    Properties.Remove("ContextMenuStrip");
                    Properties.Remove("TabIndex");
                    Properties.Remove("TabStop");
                    Properties.Remove("AutoSize");
                    Properties.Remove("AutoScrollMargin");
                    Properties.Remove("AutoScrollMinSize");
                    Properties.Remove("Padding");
                    Properties.Remove("MaximumSize");
                    Properties.Remove("MinimumSize");
                    Properties.Remove("AutoScroll");
                    Properties.Remove("AutoSizeMode");
                }

A simple internal designer class override is used to remove non-required properties.