Click here to Skip to main content
15,885,188 members
Articles / Desktop Programming / Windows Forms
Tip/Trick

Liquid Container Control

Rate me:
Please Sign up or sign in to vote.
4.40/5 (8 votes)
10 May 2015CPOL2 min read 23.9K   3.1K   12   6
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Scodix
Israel Israel
Project Manager and Application Developer, in a wide variety of business applications. Particularly interested in client/server and Graphical User Interface design using Visual C#.

Specialties: 13 Y'rs in C#, 10 Y'rs experience in C++ Highly experienced in wide technologies, IT projects, military projects etc'.

Comments and Discussions

 
Questionheeelp Pin
Member 129323186-Jan-17 6:08
Member 129323186-Jan-17 6:08 
PraiseExactly what I needed Pin
aestepa28-Mar-16 12:02
aestepa28-Mar-16 12:02 
GeneralRe: Exactly what I needed Pin
Member 129323183-Jan-17 0:53
Member 129323183-Jan-17 0:53 
Questioncolor gradient Pin
_Nizar10-May-15 4:56
_Nizar10-May-15 4:56 
AnswerRe: color gradient Pin
T_uRRiCA_N10-May-15 7:24
professionalT_uRRiCA_N10-May-15 7:24 
AnswerRe: color gradient Pin
Peer Adi10-May-15 20:22
professionalPeer Adi10-May-15 20:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.