65.9K
CodeProject is changing. Read more.
Home

Liquid Container Control

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.40/5 (8 votes)

May 10, 2015

CPOL

2 min read

viewsIcon

25127

downloadIcon

3215

This is a liquid container control for displaying liquid level in container or tank.

Introduction

Let's say you have a need to reflect a physical tank or a container of liquid in your command & control application. You can do so using some kind of a gage control, you can also use a progress bar (vertical or horizontal) and you can buy one of the few industrial control packs out there. Encountering this exact dilemma while developing my industrial printing machine control application - I have decided to create a generic liquid control.

Background

Having to display our industrial printing machine Ink Tanks Levels, in our command & control application using readings from a level sensor - I began searching for a control of such purpose and found nothing. There are some free excellent gage controls out there and I could use a vertical progress bar to simulate liquid level - but this was not good enough for my purposes. I needed a more real looking container to show my machines' Ink Levels.

Using the Code

This control inherits from the Windows Button Control for more flexibility. You can easily set which text to display on the container, what will be the color of liquid when it reaches warning and critical levels and many more properties. As you can see in the below code, I am implementing the various paint methods to draw my container image, and for the liquid level I am drawing a filled rectangle according to the input level value. 

        private void Paintimage(PaintEventArgs e)
        {
            if (e == null)
                return;
            if (e.Graphics == null)
                return;

            Image image = GetCurrentImage(btnState);

            if (image != null)
            {
                Graphics g = e.Graphics;
                Rectangle rect = GetImageDestinationRect();

                if ((btnState == ButtonState.Pushed) && (offsetPressedContent))
                    rect.Offset(1, 1);

                if (this.StretchImage)
                {
                    g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
                }
                else
                {
                    Rectangle r = GetImageDestinationRect();
                    g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
                }

                PaintImageFillRect(g, rect);
            }
        }

When the liquid reaches a pre-determined low level value (calculated as percentage of Full Tank), the color of the liquid is changed to the warning level color. NOTE: So is being done for the critical level value and color.

         private void PaintImageFillRect(Graphics g, Rectangle ImageRect)
        {
            Rectangle liquidRect = ImageRect;

            // Calc the rectangle
            liquidRect.Inflate((-15 * liquidRect.Width) / 100, (-14 * liquidRect.Height) / 100);
            liquidRect.Height = (Value * liquidRect.Height) / 100;

            Color selectedColor = liquidRect.Height <= (warningLevelValue * 
            ImageRect.Height / 100) && liquidRect.Height > 
            (criticalLevelValue * ImageRect.Height / 100) ? warningLevelColor : liquidRect.Height 
            <= (criticalLevelValue * ImageRect.Height / 100) ? criticalLevelColor : normalLevelColor;
            if (btnState == ButtonState.Disabled) selectedColor = inactiveColor;
            System.Drawing.Drawing2D.LinearGradientBrush brush = 
            new System.Drawing.Drawing2D.LinearGradientBrush
            (ImageRect, selectedColor, Blend(selectedColor, Color.White, 50), 270, true);

             //Fill Rectangle
             g.FillRectangle(brush, ((14 * ImageRect.Width) / 100), 
             ImageRect.Height - ((14 * ImageRect.Height) / 100) - 
             liquidRect.Height, liquidRect.Width, liquidRect.Height);
        }

If you need to display several containers and have some disabled - simply set the control enable flag to false.

Drawing the Text

Text can be displayed with a shadow effect. This effect is being implemented by double drawing the text with a small location shifting and color change. You may also choose to display a constant text prior to the value display. If a constant text is entered, value will be concatenated to it automatically. 

NOTE: You may want to add the ability to determine if constant text is to be added after or before the value text.
       private void PaintText(PaintEventArgs e)
        {
            if (e == null)
                return;
            if (e.Graphics == null)
                return;
            Rectangle rect = new Rectangle(0, 0, Size.Width, Size.Height); //GetTextDestinationRect();

            if ((btnState == ButtonState.Pushed) && (OffsetPressedContent))
                rect.Offset(1, 1);

            string text = this.Text;

            if (displayConstantText)
            {
                text = constantText;

                if (displayValueText)
                {
                    if (displayValueAsPercentage)
                    {
                        text = string.Format("{0} {1}%", constantText, liquidValue);
                    }
                    else
                    {
                        text = string.Format("{0} {1}", constantText, liquidValue);
                    }
                }

            }
            else if (displayValueText)
            {
                if (displayValueAsPercentage)
                {
                    text = string.Format("{0}%", liquidValue);
                }
                else
                {
                    text = string.Format("{0}", liquidValue);
                }
            }

            // Calc Rectangle for the text
            SizeF textSize = GetTextSize(e.Graphics, text, this.Font);

            // Calc starting location to point of the text
            Point textStartPoint = CalculateLeftEdgeTopEdge
            (this.TextAlign, rect, (int)textSize.Width, (int)textSize.Height);

            if (btnState == ButtonState.Disabled)
            {
                e.Graphics.DrawString(text, this.Font, 
                new SolidBrush(Color.White), textStartPoint.X + 1, textStartPoint.Y + 1);
                e.Graphics.DrawString(text, this.Font, 
                new SolidBrush(Color.FromArgb(50, 50, 50)), textStartPoint.X, textStartPoint.Y);
            }
            else
            {
                RectangleF rectangle;
                rect.Inflate((-15 * rect.Width) / 100, (-14 * rect.Height) / 100);

                if (TextDropShadow)
                {
                    Brush TransparentBrush0 = new SolidBrush(Color.FromArgb(50, Color.Black));
                    Brush TransparentBrush1 = new SolidBrush(Color.FromArgb(20, Color.Black));

                    rectangle = new RectangleF
                    (textStartPoint.X, textStartPoint.Y + 1, rect.Width, rect.Height);
                    e.Graphics.DrawString(text, this.Font, TransparentBrush0, rectangle);

                    rectangle = new RectangleF
                    (textStartPoint.X + 1, textStartPoint.Y, rect.Width, rect.Height);
                    e.Graphics.DrawString(text, this.Font, TransparentBrush0, rectangle);

                    rectangle = new RectangleF
                    (textStartPoint.X + 1, textStartPoint.Y + 1, rect.Width, rect.Height);
                    e.Graphics.DrawString(text, this.Font, TransparentBrush1, rectangle);

                    rectangle = new RectangleF
                    (textStartPoint.X, textStartPoint.Y + 2, rect.Width, rect.Height);
                    e.Graphics.DrawString(text, this.Font, TransparentBrush1, rectangle);

                    rectangle = new RectangleF
                    (textStartPoint.X + 2, textStartPoint.Y, rect.Width, rect.Height);
                    e.Graphics.DrawString(text, this.Font, TransparentBrush1, rectangle);

                    TransparentBrush0.Dispose();
                    TransparentBrush1.Dispose();
                }

                rectangle = new RectangleF
                (textStartPoint.X, textStartPoint.Y, rect.Width, rect.Height);
                e.Graphics.DrawString(text, this.Font, new SolidBrush(this.ForeColor), rectangle);
            }
        }

History

  • 10th May, 2015: Initial version