A highly customizable, feature-rich Windows Forms gauge control library for displaying real-time measurements with stunning visual effects and multiple needle styles.
- Purpose & Overview
- Project Scope
- Technical Architecture
- Installation & Setup
- Quick Start
- Complete API Reference
- Enumerations
- Classes & Components
- Properties Detailed Guide
- Needle Styles
- Usage Examples
- White Paper
- Contributing
- License
SpeedoMeter is a professional-grade Windows Forms control that renders sophisticated analog gauge displays. It combines classical speedometer aesthetics with modern visual effects and unprecedented customization capabilities.
- β Provide a reusable gauge control for Windows Forms applications
- β Support 25+ unique needle visual styles
- β Enable intuitive real-time value display
- β Deliver high-quality rendering with gradient effects and shadows
- β Offer comprehensive property-based customization
- β Maintain performance with optimized drawing techniques
- β Support color zones for value ranges (green/yellow/red status indicators)
- Performance Monitoring: CPU usage, memory consumption, disk I/O
- Industrial Applications: Machine speed, pressure gauges, flow meters
- Vehicle Dashboards: Speed, RPM, fuel consumption displays
- Medical Equipment: Vital sign monitors, oxygen levels
- Data Visualization: Any metric requiring analog gauge representation
- Dynamic Gauge Rendering: Real-time value-to-angle mapping
- 25+ Needle Styles: From modern to vintage to sci-fi themes
- Color Zones: Three-color range indicators (green β yellow β red)
- Gradient Fills: Professional gradient backgrounds and effects
- Advanced Typography: Scalable fonts with shadow effects
- Tick Marks & Labels: Automatic and manual tick positioning
- Glass Effect: Optional highlight overlay for depth
- Hub Customization: Central hub styling with gradients
- Shadow Effects: Drop shadows and inner shadows
- High-Quality Rendering: ClearType text rendering, high-quality interpolation
- Framework: .NET Framework 4.8
- Technology: Windows Forms (WinForms)
- Language: C#
- Inheritance:
UserControl - Graphics: System.Drawing namespace
SpeedometerControl (UserControl) βββ Core Properties (Value, Min/Max) βββ Layout Properties (Padding, Angles, Sizing) βββ Appearance Properties (Colors, Gradients, Effects) βββ Needle Properties (Style, Shape, Color) βββ Font & Text Properties (Typography) βββ Drawing Methods (OnPaint Pipeline) βββ Helper Utilities (Math, Geometry, Conversion)
OnPaint() βββ DrawOuterShadow() β Drop shadow effect βββ DrawFace() β Dial background gradient βββ DrawBezel() β 3D bezel frame βββ DrawInnerBezelShadow() β Inner depth effect βββ DrawZones() β Color range indicators βββ DrawTicks() β Major & minor tick marks βββ DrawNeedle() β Animated needle indicator βββ DrawValueLabel() β Current value + unit text βββ DrawThinBorder() β Outer edge highlight βββ DrawGlassEffect() β Highlight overlay
- Visual Studio 2022 (or compatible)
- .NET Framework 4.8 SDK
- Windows Forms support enabled
-
Copy Files: SpeedometerControl.cs SpeedometerControl.Designer.cs
-
Add to Project:
- Right-click project β Add Existing Item
- Select the
.csfiles - Build the project
- Toolbox Registration:
- The control appears automatically in the Toolbox
- Drag onto your form
- Programmatic Usage: var speedometer = new SpeedometerControl(); speedometer.Value = 100; speedometer.MaxValue = 500; this.Controls.Add(speedometer);
// Create and configure
var gauge = new SpeedometerControl
{
MinValue = 0,
MaxValue = 450,
Value = 0,
UnitLabel = "M/min"
};
// Add to form
this.Controls.Add(gauge);
// Update value over time
timer.Tick += (s, e) => gauge.Value += 1;
timer.Start();- Drag
SpeedometerControlfrom Toolbox onto Form - Configure properties in Property Grid:
- Set
MaxValue= 450 - Set
UnitLabel= "M/min" - Set
NeedleStyle= ModernThin
- Set
- Bind value in code-behind
| Property | Type | Default | Description |
|---|---|---|---|
Value |
float | 0f | Current gauge reading, clamped to [MinValue, MaxValue] |
MinValue |
float | 0f | Minimum gauge value |
MaxValue |
float | 450f | Maximum gauge value |
UnitLabel |
string | "M/min" | Unit text displayed below value |
Example: gauge.MinValue = 0; gauge.MaxValue = 500; gauge.Value = 250; // Mid-scale
| Property | Type | Default | Description |
|---|---|---|---|
ScaleStartAngle |
float | 135f | Start angle of scale arc (degrees) |
ScaleSweepAngle |
float | 270f | Total sweep angle of scale (degrees) |
GaugePadding |
int | 10 | Padding from control edges (pixels) |
DialPadding |
float | 1f | Space between bezel and zones (pixels) |
TickZonePadding |
float | 5f | Space between zones and ticks (pixels) |
TickLabelSpacing |
float | 7f | Distance from ticks to labels (pixels) |
ValuePosition |
PointF | (0.5f, 0.85f) | Relative position of value text |
BezelWidthMultiplier |
float | 0.08f | Bezel thickness as % of radius |
Layout Example: // Create 360-degree gauge gauge.ScaleStartAngle = 0; gauge.ScaleSweepAngle = 360;
// Adjust label position gauge.ValuePosition = new PointF(0.5f, 0.9f); // Lower
| Property | Type | Default | Description |
|---|---|---|---|
DialColor1 |
Color | White | Center gradient color of dial |
DialColor2 |
Color | RGB(224,224,224) | Outer gradient color of dial |
BezelColor1 |
Color | White | Bezel start gradient color |
BezelColor2 |
Color | White | Bezel end gradient color |
BezelHighlightColor |
Color | White | Bezel top-left highlight |
BezelShadowColor |
Color | White | Bezel bottom-right shadow |
Example: gauge.DialColor1 = Color.White; gauge.DialColor2 = Color.FromArgb(240, 240, 240); gauge.BezelShadowColor = Color.FromArgb(200, 200, 200);
| Property | Type | Default | Description |
|---|---|---|---|
ZoneGreenEndValue |
float | 100f | Upper bound of green zone |
ZoneRedStartValue |
float | 250f | Lower bound of red zone |
ZoneGreenColor |
Color | RGB(0,200,83) | Green zone color |
ZoneYellowColor |
Color | RGB(255,193,7) | Yellow zone color |
ZoneRedColor |
Color | RGB(244,67,54) | Red zone color |
ZoneThicknessMultiplier |
float | 0.02f | Zone width as % of radius |
ZoneMinThickness |
float | 2f | Minimum zone width (pixels) |
Zone Configuration: // Define ranges: 0-100 Green, 100-250 Yellow, 250+ Red gauge.ZoneGreenEndValue = 100; gauge.ZoneRedStartValue = 250; gauge.ZoneGreenColor = Color.Green; gauge.ZoneYellowColor = Color.Gold; gauge.ZoneRedColor = Color.Red;
| Property | Type | Default | Description |
|---|---|---|---|
MajorTickStep |
int | 50 | Interval between major ticks (0=auto) |
DesiredTickLabelCount |
int | 8 | Target number of labels for auto mode |
MinorTicksPerMajor |
int | 5 | Minor ticks between majors |
MajorTickLengthMultiplier |
float | 0.09f | Major tick length as % of radius |
MinorTickLengthMultiplier |
float | 0.05f | Minor tick length as % of radius |
MajorTickWidth |
float | 5f | Major tick width (pixels) |
MinorTickWidth |
float | 2f | Minor tick width (pixels) |
TickLabelFontFamily |
string | "Segoe UI" | Font for tick labels |
TickLabelFontSizeMultiplier |
float | 0.05f | Font size as % of radius |
TickLabelMinFontSize |
float | 10f | Minimum font size (points) |
TickLabelColor |
Color | ARGB(220,60,60,60) | Tick label color |
MajorTickColor |
Color | ARGB(220,60,60,60) | Major tick color |
MinorTickColor |
Color | ARGB(160,60,60,60) | Minor tick color |
Tick Configuration: gauge.MajorTickStep = 50; // Every 50 units gauge.MinorTicksPerMajor = 5; // 5 minor ticks between majors gauge.MajorTickWidth = 4f; gauge.MajorTickColor = Color.Black;
| Property | Type | Default | Description |
|---|---|---|---|
ValueFontFamily |
string | "Segoe UI" | Font family for value text |
ValueFontSizeMultiplier |
float | 0.1f | Value font size as % of radius |
UnitFontSizeScale |
float | 0.4f | Unit font size relative to value |
ValueUnitVerticalSpacing |
float | -12f | Vertical spacing between value & unit |
ValueMinFontSize |
float | 18f | Minimum value font size (points) |
UnitMinFontSize |
float | 10f | Minimum unit font size (points) |
ValueTextColor |
Color | ARGB(220,40,40,40) | Value text color |
UnitTextColor |
Color | ARGB(180,80,80,80) | Unit text color |
| Property | Type | Default | Description |
|---|---|---|---|
NeedleStyle |
NeedleStyle | ModernThin | Visual style of needle |
NeedleTransparency |
int | 180 | Alpha transparency (0-255) |
NeedleTipMultiplier |
float | 0.75f | Tip distance as % of radius |
NeedleTailMultiplier |
float | 0.20f | Tail distance as % of radius |
NeedleTailSplitDistanceMultiplier |
float | 0.24f | Forked tail position |
NeedleShoulderDistanceMultiplier |
float | 0.08f | Shoulder position |
NeedleShoulderWidthMultiplier |
float | 0.055f | Shoulder width |
NeedleTailWidthMultiplier |
float | 0.03f | Tail width |
NeedleHighlightWidth |
float | 2.0f | Center highlight width (pixels) |
NeedleShadowOffsetMultiplier |
float | 0.02f | Shadow offset as % of radius |
NeedleColor1 |
Color | Red | Primary needle color |
NeedleColor2 |
Color | Red | Secondary/shade color |
NeedleHighlightColor1 |
Color | ARGB(200,255,255,255) | Highlight start color |
NeedleHighlightColor2 |
Color | ARGB(0,255,255,255) | Highlight end color |
NeedleShadowColor |
Color | ARGB(72,0,0,0) | Shadow color |
| Property | Type | Default | Description |
|---|---|---|---|
BlockyNeedleWidthMultiplier |
float | 0.1f | ModernBlocky width |
ClassicNeedleBaseWidthMultiplier |
float | 0.15f | Tapered needle base width |
OrnateDiamondSizeMultiplier |
float | 0.1f | Diamond tip size |
OrnateCircleTailRadiusMultiplier |
float | 0.08f | Circle tail radius |
ArrowheadSizeMultiplier |
float | 0.1f | Arrowhead dimensions |
DualLineGapMultiplier |
float | 0.02f | Gap between dual lines |
KiteTailSizeMultiplier |
float | 0.1f | Kite tail dimensions |
IndicatorTipWidthMultiplier |
float | 0.05f | ModernIndicator tip width |
IndicatorTipLengthMultiplier |
float | 0.1f | ModernIndicator tip length |
IndicatorHubColor |
Color | RGB(40,40,40) | Indicator hub color |
IndicatorHubHighlightColor |
Color | RGB(100,100,100) | Indicator hub highlight |
| Property | Type | Default | Description |
|---|---|---|---|
HubSizeMultiplier |
float | 0.12f | Hub radius as % of control radius |
HubMinSize |
float | 12f | Minimum hub size (pixels) |
HubColor1 |
Color | RGB(224,224,224) | Hub gradient start |
HubColor2 |
Color | Transparent | Hub gradient end |
HubShadowColor |
Color | ARGB(50,0,0,0) | Hub shadow color |
HubHighlightColor |
Color | ARGB(150,255,255,255) | Hub highlight |
| Property | Type | Default | Description |
|---|---|---|---|
OuterBorderColor |
Color | ARGB(120,80,80,80) | Border line color |
OuterBorderWidth |
float | 1.5f | Border width (pixels) |
OuterShadowColor |
Color | ARGB(50,0,0,0) | Drop shadow color |
InnerShadowColor |
Color | ARGB(100,0,0,0) | Inner bezel shadow |
TextShadowColor |
Color | ARGB(30,0,0,0) | Text drop shadow |
GlassEffectCenterColor |
Color | Transparent | Glass center color |
GlassEffectOuterColor |
Color | ARGB(0,255,255,255) | Glass outer color |
GlassEffectRect |
RectangleF | (0.1f, 0.05f, 0.8f, 0.4f) | Glass area bounds |
public enum NeedleStyle { // Modern Collection (6 styles) ModernIndicator, // Blocky tip with dual-line shaft ModernThin, // Elegant thin needle with split tail ModernBlocky, // Wide blocky design ModernSleek, // Curved aerodynamic shape ModernCutout, // Triangular with center void ModernDualLine, // Two parallel lines
// Classic Collection (2 styles)
ClassicTapered, // Traditional tapered needle
ClassicWide, // Wide triangular needle
// Arrow Collection (3 styles)
Arrowhead, // Simple triangular arrowhead
Broadhead, // Wide arrowhead with barbs
CrossbowBolt, // Arrow with fletched tail
// Vintage Collection (4 styles)
VintageThinWithTail, // Thin shaft with triangular tail
VintageArtDeco, // Art Deco stepped style
VintageCrescentTail, // Thin with crescent tail cutout
VintageAviator, // Flat swept design
// Ornate Collection (4 styles)
OrnateDiamond, // Diamond-shaped tip
OrnateSpearTip, // Multi-pointed spear
OrnateFleurDeLis, // French lily pattern tail
OrnateSword, // Sword-like blade
// Specialty Collection (3 styles)
CompassNorth, // Compass rose dual-color
AnchorTail, // Anchor with forked tail
Harpoon, // Harpoon with barbs
// Sci-Fi Collection (3 styles)
SciFiArrow, // Futuristic arrow
SciFiDataSpike, // Data spike shape
EnergyBlade, // Glowing energy effect
// Utility Collection (2 styles)
SimplePin, // Minimal single line
KiteTail // Kite/diamond tail
}
Inheritance: UserControl
Namespace: SpeedoMeter
Key Characteristics:
- Fully owner-drawn custom control
- Double-buffered rendering (optimized drawing)
- Property-based customization
- Real-time value animation support
public SpeedometerControl() { SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true); Size = new Size(340, 340); BackColor = Color.White; }
Features Enabled:
AllPaintingInWmPaint: No background eraseOptimizedDoubleBuffer: Double buffering for flicker-free renderingResizeRedraw: Redraw on resizeUserPaint: Custom paint handling
protected override void OnPaint(PaintEventArgs e) // Main painting pipeline orchestrator
private void DrawOuterShadow(Graphics g, Rectangle rect) // Outer drop shadow effect
private void DrawFace(Graphics g, Rectangle rect) // Radial gradient dial background
private void DrawBezel(Graphics g, Rectangle rect) // 3D beveled frame with highlights
private void DrawInnerBezelShadow(Graphics g, Rectangle rect) // Inner shadow for depth
private void DrawZones(Graphics g, Rectangle rect) // Color range indicator arcs
private void DrawTicks(Graphics g, Rectangle rect) // Major and minor tick marks with labels
private void DrawNeedle(Graphics g, Rectangle rect) // Dispatches to appropriate needle style renderer
private void DrawValueLabel(Graphics g, Rectangle rect) // Current value and unit text display
private void DrawThinBorder(Graphics g, Rectangle rect) // Outer edge highlight
private void DrawGlassEffect(Graphics g, Rectangle rect) // Reflective highlight overlay
private void DrawNeedle_ModernIndicator(Graphics g, Rectangle rect) private void DrawNeedle_ModernThin(Graphics g, Rectangle rect) private void DrawNeedle_ModernSleek(Graphics g, Rectangle rect) private void DrawNeedle_ModernCutout(Graphics g, Rectangle rect) private void DrawNeedle_ModernDualLine(Graphics g, Rectangle rect) private void DrawNeedle_ClassicTapered(Graphics g, Rectangle rect) private void DrawNeedle_ClassicWide(Graphics g, Rectangle rect) private void DrawNeedle_OrnateDiamond(Graphics g, Rectangle rect) private void DrawNeedle_OrnateSpearTip(Graphics g, Rectangle rect) private void DrawNeedle_OrnateFleurDeLis(Graphics g, Rectangle rect) private void DrawNeedle_OrnateSword(Graphics g, Rectangle rect) private void DrawNeedle_Arrowhead(Graphics g, Rectangle rect) private void DrawNeedle_Broadhead(Graphics g, Rectangle rect) private void DrawNeedle_CrossbowBolt(Graphics g, Rectangle rect) private void DrawNeedle_VintageThinWithTail(Graphics g, Rectangle rect) private void DrawNeedle_VintageArtDeco(Graphics g, Rectangle rect) private void DrawNeedle_VintageCrescentTail(Graphics g, Rectangle rect) private void DrawNeedle_VintageAviator(Graphics g, Rectangle rect) private void DrawNeedle_CompassNorth(Graphics g, Rectangle rect) private void DrawNeedle_AnchorTail(Graphics g, Rectangle rect) private void DrawNeedle_Harpoon(Graphics g, Rectangle rect) private void DrawNeedle_SciFiArrow(Graphics g, Rectangle rect) private void DrawNeedle_SciFiDataSpike(Graphics g, Rectangle rect) private void DrawNeedle_EnergyBlade(Graphics g, Rectangle rect) private void DrawNeedle_SimplePin(Graphics g, Rectangle rect)
// Value-to-Angle Mapping private float MapValueToAngle(float value) Returns: angle in degrees based on value
// Circular Geometry private PointF PointOnCircle(PointF center, float radius, float value) Returns: point on circle at value's angle
private PointF PointOnCircle(PointF center, float radius, float value, float angleOffset) Returns: point with additional angle offset
// Vector Operations private PointF GetDirectionVector(float angle) Returns: unit direction vector at angle
private PointF GetPerpendicularVector(float angle) Returns: perpendicular unit vector
// Math Utilities private static float Clamp(float value, float min, float max) Constrains value to range
private float SpanForRange(float from, float to) Calculates arc span for value range
private static double DegToRad(float degrees) Converts degrees to radians
private static int NiceNumber(float raw) Calculates nice round number for auto-scaling
// Drawing Utilities private void DrawNeedleShadowAndFill(Graphics g, GraphicsPath path, float angle, float radius) Renders shadow and filled needle path
private void DrawNeedleShadowAndFill(Graphics g, Pen pen, GraphicsPath path, float angle, float radius) Renders shadow and stroked needle path
private void DrawNeedleHub(Graphics g, PointF center, float radius) Renders central hub circle
private void DrawNeedleHub_IndicatorStyle(Graphics g, PointF center, float radius) Renders indicator-style hub with highlight
- ModernIndicator: Blocky rectangular tip with dual-line shaft
- ModernThin: Elegant tapered needle with split forked tail (default)
- ModernSleek: Curved aerodynamic shape with smooth contours
- ModernCutout: Triangle with center void cutout
- ModernDualLine: Two parallel lines representing needle edges
- ModernBlocky: Wide blocky rectangular design
- ClassicTapered: Traditional tapered triangular needle
- ClassicWide: Wide rectangular needle without split tail
- Arrowhead: Simple triangular arrowhead with connector line
- Broadhead: Wider arrowhead with side barbs
- CrossbowBolt: Arrow with narrow tip and fletched tail
- VintageThinWithTail: Thin line with triangular tail
- VintageArtDeco: Stepped multi-segment art deco design
- VintageCrescentTail: Thin needle with crescent cutout tail
- VintageAviator: Flat swept-wing aviation style
- OrnateDiamond: Diamond-shaped ornamental tip
- OrnateSpearTip: Multi-pointed spear head
- OrnateFleurDeLis: French lily pattern with curves
- OrnateSword: Blade-like needle with cross-guard
- CompassNorth: Compass rose with dual-color split
- AnchorTail: Pin with anchor-shaped tail
- Harpoon: Barbed harpoon head with spikes
- SciFiArrow: Futuristic narrow arrow
- SciFiDataSpike: Data visualization spike shape
- EnergyBlade: Glowing gradient blade with highlight
- SimplePin: Minimal single line pointer
- KiteTail: Kite/diamond shaped tail
public partial class RPMGaugeForm : Form { private Timer rpmTimer;
public RPMGaugeForm()
{
InitializeComponent();
ConfigureRPMGauge();
}
private void ConfigureRPMGauge()
{
var rpm = new SpeedometerControl
{
MinValue = 0,
MaxValue = 8000,
Value = 0,
UnitLabel = "RPM",
NeedleStyle = NeedleStyle.ModernThin,
NeedleColor1 = Color.Red,
ZoneGreenEndValue = 3000,
ZoneRedStartValue = 6000,
ScaleStartAngle = 225,
ScaleSweepAngle = 270,
Size = new Size(400, 400)
};
this.Controls.Add(rpm);
// Simulate engine speed variation
rpmTimer = new Timer();
rpmTimer.Interval = 50;
rpmTimer.Tick += (s, e) =>
{
rpm.Value = Math.Min(8000, rpm.Value + 15);
if (rpm.Value >= 7500)
rpm.Value = 0; // Reset
};
rpmTimer.Start();
}
}
public partial class CPUMonitorForm : Form { private PerformanceCounter cpuCounter; private Timer updateTimer;
public CPUMonitorForm()
{
InitializeComponent();
InitializeCPUGauge();
}
private void InitializeCPUGauge()
{
var cpuGauge = new SpeedometerControl
{
MinValue = 0,
MaxValue = 100,
UnitLabel = "%",
NeedleStyle = NeedleStyle.SciFiArrow,
NeedleColor1 = Color.FromArgb(0, 200, 83),
ZoneGreenEndValue = 50,
ZoneYellowColor = Color.FromArgb(255, 193, 7),
ZoneRedColor = Color.FromArgb(244, 67, 54),
ZoneRedStartValue = 80,
BezelColor1 = Color.FromArgb(30, 30, 30),
BezelColor2 = Color.FromArgb(60, 60, 60),
ValueTextColor = Color.White,
TickLabelColor = Color.White
};
cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
updateTimer = new Timer();
updateTimer.Interval = 1000;
updateTimer.Tick += (s, e) =>
{
cpuGauge.Value = (float)cpuCounter.NextValue();
};
updateTimer.Start();
this.Controls.Add(cpuGauge);
}
}
public class VehicleSpeedometerPanel : UserControl { public VehicleSpeedometerPanel() { CreateSpeedometer(); }
private void CreateSpeedometer()
{
var speedometer = new SpeedometerControl
{
MinValue = 0,
MaxValue = 300,
UnitLabel = "km/h",
ScaleStartAngle = 135,
ScaleSweepAngle = 270,
GaugePadding = 10,
DialColor1 = Color.White,
DialColor2 = Color.FromArgb(240, 240, 240),
BezelShadowColor = Color.FromArgb(200, 200, 200),
ZoneGreenEndValue = 80,
ZoneRedStartValue = 200,
ZoneGreenColor = Color.Green,
ZoneYellowColor = Color.Gold,
ZoneRedColor = Color.Red,
NeedleStyle = NeedleStyle.ClassicTapered,
NeedleColor1 = Color.Black,
NeedleColor2 = Color.Gray,
MajorTickStep = 20,
MinorTicksPerMajor = 4,
OuterShadowColor = Color.FromArgb(50, 0, 0, 0),
TextShadowColor = Color.FromArgb(30, 0, 0, 0)
};
this.Controls.Add(speedometer);
}
}
public class TechGaugeTheme { public static void ApplyDarkTheme(SpeedometerControl gauge) { gauge.DialColor1 = Color.FromArgb(20, 20, 30); gauge.DialColor2 = Color.FromArgb(40, 40, 50); gauge.NeedleColor1 = Color.FromArgb(0, 255, 200); gauge.NeedleHighlightColor1 = Color.FromArgb(100, 255, 255); gauge.ValueTextColor = Color.White; gauge.TickLabelColor = Color.FromArgb(200, 200, 255); gauge.BezelColor1 = Color.FromArgb(50, 50, 60); gauge.BezelHighlightColor = Color.FromArgb(100, 200, 255); gauge.BezelShadowColor = Color.FromArgb(0, 0, 0); gauge.ZoneGreenColor = Color.FromArgb(0, 255, 100); gauge.ZoneYellowColor = Color.FromArgb(255, 255, 0); gauge.ZoneRedColor = Color.FromArgb(255, 100, 0); }
public static void ApplyVintageTheme(SpeedometerControl gauge)
{
gauge.DialColor1 = Color.FromArgb(240, 240, 220);
gauge.DialColor2 = Color.FromArgb(200, 200, 180);
gauge.NeedleColor1 = Color.FromArgb(140, 80, 50);
gauge.NeedleColor2 = Color.FromArgb(100, 60, 40);
gauge.TickLabelColor = Color.FromArgb(80, 60, 40);
gauge.ValueTextColor = Color.FromArgb(100, 80, 60);
gauge.BezelColor1 = Color.FromArgb(200, 190, 170);
gauge.BezelShadowColor = Color.FromArgb(150, 140, 120);
}
}
The control uses a polar coordinate system internally:
- Center: Gauge center point (calculated from control bounds)
- Radius: Half of minimum dimension (width/height) minus padding
- Angles: Degrees (0Β° = right, 90Β° = down, 180Β° = left, 270Β° = up)
- Scale: Starts at
ScaleStartAngleand sweepsScaleSweepAngledegrees
Angle-to-Value Mapping: angle = ScaleStartAngle + (value - MinValue) / (MaxValue - MinValue) * ScaleSweepAngle
-
Double Buffering: Eliminates flicker ControlStyles.OptimizedDoubleBuffer
-
Owner Drawing: Minimal framework overhead ControlStyles.UserPaint
-
Efficient Gradient Brushes: Computed once per frame using (var brush = new LinearGradientBrush(...)) g.FillPath(brush, path);
-
Graphics Hints: High-quality rendering g.SmoothingMode = SmoothingMode.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
The OnPaint method orchestrates the rendering in specific order:
- Clear background
- Calculate dimensions & center point
- Outer Shadow (visual depth)
- Dial Face (background gradient)
- Bezel Frame (3D effect)
- Inner Bezel Shadow (depth enhancement)
- Color Zones (status indicators)
- Tick Marks & Labels (scale reference)
- Needle (current value indicator)
- Value Text Label (digital display)
- Thin Border (edge highlight)
- Glass Effect (reflective finish)
Order Significance: Each layer builds on previous ones, creating depth through painter's algorithm (back-to-front rendering).
Categories:
-
Path-Based: Most styles use
GraphicsPathfor complex shapes- Polygon-based (triangles, diamonds)
- Curve-based (smooth Bezier curves)
- Region operations (CompassNorth fill split)
-
Line-Based: Minimal styles use direct line drawing
- SimplePin: Single line
- ModernDualLine: Two parallel lines
- Harpoon: Connected line segments
-
Gradient-Enhanced: Advanced effects
- EnergyBlade: PathGradientBrush for glow
- ModernIndicator: Highlight stripe
- All styles: Linear gradient for shading
Dynamic font sizing based on control size:
fontSizeInPoints = Max( MinFontSize, ControlRadius Γ FontSizeMultiplier )
Automatic Label Count: MajorTickStep = NiceNumber( (MaxValue - MinValue) / DesiredTickLabelCount )
Nice Number Algorithm: Generates round numbers (1, 2, 5, 10, 20, 50, 100, ...)
- Property-Based Configuration: All customization through properties
- Owner-Drawn Control: Complete visual control
- Observer Pattern: Property changes trigger
Invalidate() - Strategy Pattern: Multiple needle drawing strategies in
DrawNeedle() - Composite Pattern: Complex shapes from simple primitives
To extend SpeedoMeter:
-
Add Needle Style:
- Add enum value to
NeedleStyle - Implement
DrawNeedle_[StyleName]()method - Add case to
DrawNeedle()switch statement
- Add enum value to
-
Add Property:
- Add backing field:
private [Type] _fieldName; - Add property with
[Category]attribute - Call
Invalidate()on setter
- Add backing field:
-
Customize Colors: Modify color constants in backing fields
This project is licensed under the MIT License. See the LICENSE file for details.
- GitHub Issues: Report bugs or request features
- Pull Requests: Submit improvements
- Documentation: Help improve documentation
- Examples: Share your usage examples
Happy Gauging! π―
This project is designed to provide a functional speedometer application that can be used in various contexts. It showcases the implementation of speed measurement and display functionalities.
- Real-time speed tracking
- User-friendly interface
- Compatibility with multiple devices
To install the SpeedoMeter application, follow these steps:
- Clone the repository: git clone https://github.com/yourusername/SpeedoMeter-WorkingCode.git
- Navigate to the project directory: cd SpeedoMeter-WorkingCode
- Install the required dependencies: npm install
To run the application, use the following command: npm start This will launch the speedometer interface in your default web browser.
We would like to thank all contributors and users for their support and feedback.
This document has been updated and saved successfully. Thank you for your contributions to the SpeedoMeter project!