Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Liquid Container Control

0.00/5 (No votes)
10 May 2015 1  
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. 

C#
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);
    }
}

Image 1

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.

C#
 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);
}

Image 2

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

Image 3

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.
C#
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);
     }
 }

Image 4

History

  • 10th May, 2015: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here