![]() |
Desktop Development »
Miscellaneous »
Miscellaneous Controls
Intermediate
License: The Code Project Open License (CPOL)
Sliding Scale GaugeBy Tefik BecirovicAn endless moving graphical scale gauge with a linear representation of data. |
C# (C#1.0, C#2.0, C#3.0), Windows, .NET (.NET2.0), GDI+, Dev, Design
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||

The sliding scale is a very simple, but fast, performing, and powerful .NET user control, figured as a graphical scale gauge with a linear representation of data. The instrument consists of a static pointer (needle) and a movable linear scale. The static needle refers to the current position of the moving scale, and shows the input values through a graphical position along the scale. The sliding scale is endless, and can represent an unlimited value (type double) at a certain moment.
On the CodeProject, there are several very useful and good-looking instruments already available. I want to take the trouble to add one more to the chain.
This project is developed in C#, with SharpDevelop and .NET 2.0, using GDI+.
The sliding scale is inherited from System.Windows.Forms.UserControl, with an overridden OnPaint method and some new properties:
Value |
The current position of the scale. |
ScaleRange |
The visible range of the scale. |
LargeTicksCount |
The number of large ticks. |
SmallTickCount |
The number of small ticks. |
ShadowEnabled |
Is the shadow enabled? |
ShadowColor |
The shadow color of the component. |
NeedleColor |
The color of the scale needle. |
In the code, the following properties from the parent control are used:
BackColor |
The background color of the component. |
BorderStyle |
Indicates whether the control should have a border. |
ForeColor |
The foreground color used to display the text and ticks. |
The sliding scale is composed of four layers.
The complete logic is placed in the OnPaint method. There is a small invariant part for purists, closed in a signed region, which can be moved outside the OnPaint. Everything else happens in a few simple steps:
LinearGradientBrush.protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// Draw simple text, don't waste time with luxus render:
e.Graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
#region Can be moved outside OnPaint ...
// Calculate help variables
int W = this.ClientRectangle.Width;
int H = this.ClientRectangle.Height;
int Wm = W / 2;
int Hm = H / 2;
// Calculate distances between ticks
double largeTicksDistance = scaleRange / largeTicksCount;
double smallTicksDistance = largeTicksDistance / (smallTicksCount+1);
// Calculate number of pixel between small ticks
float smallTicksPixels = (float)(W/scaleRange*smallTicksDistance);
#endregion Can be moved outside OnPaint
// Calculate first large tick value and position
double tickValue = Math.Floor((curValue-scaleRange/2) /
largeTicksDistance) * largeTicksDistance;
float tickPosition = (float)Math.Floor(Wm - W/scaleRange*(curValue-tickValue));
// Create drawing resources
Pen pen = new Pen(ForeColor);
Brush brush = new SolidBrush(ForeColor);
// For all large ticks
for (int L=0; L<=largeTicksCount; L++)
{
// Draw large tick
e.Graphics.DrawLine(pen, tickPosition-0,0, tickPosition-0,15);
e.Graphics.DrawLine(pen, tickPosition-1,0, tickPosition-1,15);
// Draw large tick numerical value
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
e.Graphics.DrawString(Math.Round(tickValue,2).ToString(),
Font, brush,
new PointF(tickPosition, Hm),sf);
// For all small ticks
for (int S=1; S<=smallTicksCount; S++)
{
// Update tick value and position
tickValue += smallTicksDistance;
tickPosition += smallTicksPixels;
// Draw small tick
e.Graphics.DrawLine(pen, tickPosition,0,tickPosition,10);
}
// Update tick value and position
tickValue += smallTicksDistance;
tickPosition += smallTicksPixels;
}
// Dispose drawing resources
brush.Dispose();
pen.Dispose();
if (ShadowEnabled)
{
LinearGradientBrush LGBrush = null;
// Draw left side shadow
LGBrush = new LinearGradientBrush(new Rectangle(0, 0, Wm, H),
Color.FromArgb(255, ShadowColor),
Color.FromArgb(0, BackColor),
000, true);
e.Graphics.FillRectangle(LGBrush, new Rectangle(0,0, Wm, H));
// Draw right side shadow
LGBrush = new LinearGradientBrush(new Rectangle(Wm+1, 0, Wm, H),
Color.FromArgb(255, ShadowColor),
Color.FromArgb(0, BackColor),
180, true);
e.Graphics.FillRectangle(LGBrush, new Rectangle(Wm+1, 0, Wm, H));
LGBrush.Dispose();
}
// Draw scale needle
e.Graphics.DrawLine(new Pen(NeedleColor), Wm-0,0, Wm-0,H);
e.Graphics.DrawLine(new Pen(NeedleColor), Wm-1,0, Wm-1,H);
}
This control has a good set of default property values so that, once included in your own solution, it can be simply selected from the tools palette, dropped to your form, and used immediately. Otherwise, there are only a few other listed properties to be configured. You just need one line of code to get it working:
slidingScale1.Value = your value here!
The included archive files contain the complete source code and the compiled binaries of the component, and a simple test application.
There are many possibilities to improve this control. Here are some ideas, if someone wants to do it:
Owing to the LinearGradientBrush shading, there is a three dimensional feel, the sliding scale looks already like a real instrument. I personally miss some flexibility in order to draw the numbers on the face of the scale and to customize the lengths of the ticks.
In order to set up the instrument so that it behaves as a real instrument, we must look at two important areas:
MinValue and MaxValue, and by controlling the changes of the existing Value property. Only values from a defined range should be accepted.These are some other desired features:
The sliding scale shown here, in terms of measurement technology, is an “indicator”. We can make it a “control”. Therefore, we should override the OnMouseDown and OnMouseMove methods to process mouse events, and implement a ChangeValue method to announce value changing.
This is the preliminary version of the control, and many features have to be implemented yet. I will attempt to cover this as soon as possible.
Any suggestions/comments/feedback is welcome and highly appreciated.
If you like it, please vote, and if you use it commercially, describe your success story in the discussion board below.
| You must Sign In to use this message board. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 17 Oct 2008 Editor: Smitha Vijayan |
Copyright 2008 by Tefik Becirovic Everything else Copyright © CodeProject, 1999-2010 Web09 | Advertise on the Code Project |