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;
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);
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);
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);
}
}
SizeF textSize = GetTextSize(e.Graphics, text, this.Font);
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