//----------------------------------------------------------------------- // // See below. // //----------------------------------------------------------------------- namespace AquaControls { using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Globalization; using System.Windows.Forms; using global::SharedObjects; /// /// Aqua Gauge Control - A Windows User Control. /// Author : Ambalavanar Thirugnanam /// Date : 24th August 2007 /// email : ambalavanar.thiru@gmail.com /// This is control is for free. You can use for any commercial or non-commercial purposes. /// [Please do no remove this header when using this control in your application.] /// [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1119:StatementMustNotUseUnnecessaryParenthesis", Justification = "Reviewed.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1504:AllAccessorsMustBeSingleLineOrMultiLine", Justification = "Reviewed.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1126:PrefixCallsCorrectly", Justification = "Reviewed.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:CurlyBracketsMustNotBeOmitted", Justification = "Reviewed.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Tool Generated.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:FieldsMustBePrivate", Justification = "Tool Generated.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:PrefixLocalCallsWithThis", Justification = "Tool Generated.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:AccessModifierMustBeDeclared", Justification = "Tool Generated.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:ClosingCurlyBracketMustBeFollowedByBlankLine", Justification = "Tool Generated.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Tool Generated.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:PartialElementsMustBeDocumented", Justification = "Tool Generated.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1623:PropertySummaryDocumentationMustMatchAccessors", Justification = "Reviewed.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1504:AllAccessorsMustBeSingleLineOrMultiLine", Justification = "Reviewed.")] public partial class AquaGauge : UserControl { #region Private Attributes private float minValue; private float maxValue; private float currentValue; private float currentDigitalValue; private Color digitColor = Color.Black; private float recommendedValueMin; private float recommendedValueMax; private float red1ValueMin; private float red1ValueMax; private float red2ValueMin; private float red2ValueMax; private float yellowValueMin; private float yellowValueMax; private float blueValueMin; private float blueValueMax; private uint noOfDivisions; private uint noOfSubDivisions; private string dialText; private string digitalGaugeText; private Color dialColor = Color.Lavender; private float glossinessAlpha = 25; private int oldWidth, oldHeight; int x, y, width, height; float fromAngle = 135F; float toAngle = 405F; private bool enableTransparentBackground; private bool requiresRedraw; private Image backgroundImg; private Rectangle rectImg; private string digitMask = "000.00"; #endregion public AquaGauge() { this.InitializeComponent(); this.x = 5; this.y = 5; this.width = this.Width - 10; this.height = this.Height - 10; this.noOfDivisions = 10; this.noOfSubDivisions = 3; this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); this.SetStyle(ControlStyles.ResizeRedraw, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.BackColor = Color.Transparent; this.Resize += new EventHandler(this.AquaGauge_Resize); this.requiresRedraw = true; } #region Public Properties /// /// Event logging interface instance. /// public ILogging iLogging { get; set; } /// /// Color of digits. /// public Color DigitColor { get { return this.digitColor; } set { this.digitColor = value; } } /// /// Mask for formatting digital value. /// public string DigitMask { get { return this.digitMask; } set { this.digitMask = value; } } /// /// Gets or sets Mininum value on the scale /// [DefaultValue(0)] [Description("Mininum value on the scale")] public float MinValue { get { return this.minValue; } set { if (value < this.maxValue) { this.minValue = value; if (this.currentValue < this.minValue) this.currentValue = this.minValue; if (this.recommendedValueMin < this.minValue) this.recommendedValueMin = this.minValue; if (this.recommendedValueMax < this.minValue) this.recommendedValueMax = this.minValue; if (this.red1ValueMin < this.minValue) this.red1ValueMin = this.minValue; if (this.red1ValueMax < this.minValue) this.red1ValueMax = this.minValue; if (this.red2ValueMin < this.minValue) this.red2ValueMin = this.minValue; if (this.red2ValueMax < this.minValue) this.red2ValueMax = this.minValue; if (this.yellowValueMin < this.minValue) this.yellowValueMin = this.minValue; if (this.yellowValueMax < this.minValue) this.yellowValueMax = this.minValue; if (this.blueValueMin < this.minValue) this.blueValueMin = this.minValue; if (this.blueValueMax < this.minValue) this.blueValueMax = this.minValue; this.requiresRedraw = true; this.Invalidate(); } } } /// /// Gets or sets Maximum value on the scale /// [DefaultValue(100)] [Description("Maximum value on the scale")] public float MaxValue { get { return maxValue; } set { if (value > minValue) { maxValue = value; if (currentValue > maxValue) currentValue = maxValue; if (recommendedValueMin > maxValue) recommendedValueMin = maxValue; if (recommendedValueMax > maxValue) recommendedValueMax = maxValue; if (red1ValueMin > maxValue) red1ValueMin = maxValue; if (red1ValueMax > maxValue) red1ValueMax = maxValue; if (red2ValueMin > maxValue) red2ValueMin = maxValue; if (red2ValueMax > maxValue) red2ValueMax = maxValue; if (yellowValueMin > maxValue) yellowValueMin = maxValue; if (yellowValueMax > maxValue) yellowValueMax = maxValue; if (blueValueMin > maxValue) blueValueMin = maxValue; if (blueValueMax > maxValue) blueValueMax = maxValue; requiresRedraw = true; this.Invalidate(); } } } /// /// Gets or sets Threshold value from which green area will be marked. /// [DefaultValue(10.0)] [Description("Threshold value from which green area will be marked.")] public float RecommendedValueMin { get { return recommendedValueMin; } set { float newValue = value; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; recommendedValueMin = newValue; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Threshold value from which green area will be marked. /// [DefaultValue(20.0)] [Description("Threshold value from which green area will be marked.")] public float RecommendedValueMax { get { return recommendedValueMax; } set { float newValue = value; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; recommendedValueMax = newValue; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Threshold value from which green area will be marked. /// [DefaultValue(10.0)] [Description("Threshold value from which green area will be marked.")] public float Red1ValueMin { get { return red1ValueMin; } set { float newValue = value; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; red1ValueMin = newValue; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Threshold value from which green area will be marked. /// [DefaultValue(20.0)] [Description("Threshold value from which green area will be marked.")] public float Red1ValueMax { get { return red1ValueMax; } set { float newValue = value; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; red1ValueMax = newValue; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Threshold value from which green area will be marked. /// [DefaultValue(10.0)] [Description("Threshold value from which green area will be marked.")] public float Red2ValueMin { get { return red2ValueMin; } set { float newValue = value; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; red2ValueMin = newValue; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Threshold value from which green area will be marked. /// [DefaultValue(20.0)] [Description("Threshold value from which green area will be marked.")] public float Red2ValueMax { get { return red2ValueMax; } set { float newValue = value; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; red2ValueMax = newValue; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Threshold value from which green area will be marked. /// [DefaultValue(10.0)] [Description("Threshold value from which green area will be marked.")] public float YellowValueMin { get { return yellowValueMin; } set { float newValue = value; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; yellowValueMin = newValue; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Threshold value from which green area will be marked. /// [DefaultValue(20.0)] [Description("Threshold value from which green area will be marked.")] public float YellowValueMax { get { return yellowValueMax; } set { float newValue = value; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; yellowValueMax = newValue; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Threshold value from which green area will be marked. /// [DefaultValue(10.0)] [Description("Threshold value from which green area will be marked.")] public float BlueValueMin { get { return blueValueMin; } set { float newValue = value; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; blueValueMin = newValue; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Threshold value from which green area will be marked. /// [DefaultValue(20.0)] [Description("Threshold value from which green area will be marked.")] public float BlueValueMax { get { return blueValueMax; } set { float newValue = value; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; blueValueMax = newValue; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Value where the pointer will point to. /// [DefaultValue(0)] [Description("Value where the pointer will point to.")] public float Value { get { return currentValue; } set { if (value >= minValue && value <= maxValue) { currentValue = value; } else { if (value < minValue) { currentValue = minValue; } else { currentValue = maxValue; } } this.Refresh(); } } /// /// Gets or sets Value for digital display. /// [DefaultValue(0)] [Description("Value to display in digital display.")] public float DigitalValue { get { return this.currentDigitalValue; } set { this.currentDigitalValue = value; } } /// /// Gets or sets Background color of the dial /// [Description("Background color of the dial")] public Color DialColor { get { return dialColor; } set { dialColor = value; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or sets Glossiness strength. Range: 0-100 /// [DefaultValue(72)] [Description("Glossiness strength. Range: 0-100")] public float Glossiness { get { return (glossinessAlpha * 100) / 220; } set { float val = value; if (val > 100) value = 100; if (val < 0) value = 0; glossinessAlpha = (value * 220) / 100; this.Refresh(); } } /// /// Get or sets the number of Divisions in the dial scale. /// [DefaultValue(10)] [Description("Get or Sets the number of Divisions in the dial scale.")] public int NoOfDivisions { get { return (int)this.noOfDivisions; } set { if (value > 1 && value < 25) { this.noOfDivisions = (uint)value; requiresRedraw = true; this.Invalidate(); } } } /// /// Gets or Sets the number of Sub Divisions in the scale per Division. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "SubDivisions", Justification = "Reviewed")] [DefaultValue(3)] [Description("Gets or Sets the number of Sub Divisions in the scale per Division.")] public int NoOfSubDivisions { get { return (int)this.noOfSubDivisions; } set { if (value > 0 && value <= 10) { this.noOfSubDivisions = (uint)value; requiresRedraw = true; this.Invalidate(); } } } /// /// Gets or Sets the Text to be displayed in the dial /// [Description("Gets or Sets the Text to be displayed in the dial")] public string DialText { get { return this.dialText; } set { this.dialText = value; requiresRedraw = true; this.Invalidate(); } } /// /// Gets or Sets the Text to be displayed in the dial /// [Description("Gets or Sets the Text to be displayed for digital gauge in the dial")] public string DigitalGaugeText { get { return this.digitalGaugeText; } set { this.digitalGaugeText = value; requiresRedraw = true; this.Invalidate(); } } /// /// Enables or Disables Transparent Background color. /// Note: Enabling this will reduce the performance and may make the control flicker. /// [DefaultValue(false)] [Description("Enables or Disables Transparent Background color. Note: Enabling this will reduce the performance and may make the control flicker.")] public bool EnableTransparentBackground { get { return this.enableTransparentBackground; } set { this.enableTransparentBackground = value; this.SetStyle(ControlStyles.OptimizedDoubleBuffer, !enableTransparentBackground); requiresRedraw = true; this.Refresh(); } } #endregion #region Overriden Control methods /// /// Draws the pointer. /// /// Event arguments. protected override void OnPaint(PaintEventArgs e) { if (e != null) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; width = this.Width - (x * 2); height = this.Height - (y * 2); DrawPointer(e.Graphics, ((width) / 2) + x, ((height) / 2) + y); RectangleF digiFRect = new RectangleF((this.Width / 2) - (this.width / 7), (int)(this.height / 1.2), this.width / 4, this.Height / 12); DisplayNumber(e.Graphics, this.currentDigitalValue, digiFRect); } } /// /// Draws the dial background. /// /// Event arguments. protected override void OnPaintBackground(PaintEventArgs e) { if (e != null) { if (!enableTransparentBackground) { base.OnPaintBackground(e); } e.Graphics.SmoothingMode = SmoothingMode.HighQuality; using (SolidBrush brush = new SolidBrush(Color.Transparent)) { e.Graphics.FillRectangle(brush, new Rectangle(0, 0, Width, Height)); } if (backgroundImg == null || requiresRedraw) { backgroundImg = new Bitmap(this.Width, this.Height); Graphics g = Graphics.FromImage(backgroundImg); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; width = this.Width - (x * 2); height = this.Height - (y * 2); rectImg = new Rectangle(x, y, width, height); // Draw background color // using (Brush backGroundBrush = new SolidBrush(Color.FromArgb(120, dialColor))) using (Brush backGroundBrush = new SolidBrush(Color.FromArgb(255, dialColor))) { g.FillEllipse(backGroundBrush, x, y, width, height); } // Draw Rim using (SolidBrush outlineBrush = new SolidBrush(Color.FromArgb(100, Color.SlateGray))) { using (Pen outline = new Pen(outlineBrush, (float)(width * .03))) { g.DrawEllipse(outline, rectImg); } } using (Pen darkRim = new Pen(Color.SlateGray)) { g.DrawEllipse(darkRim, x, y, width, height); } // Draw Callibration DrawCalibration(g, rectImg, ((width) / 2) + x, ((height) / 2) + y); // Draw Colored Rim int gap = (int)(this.Width * 0.03F); Rectangle rectg = new Rectangle(rectImg.X + gap, rectImg.Y + gap, rectImg.Width - (gap * 2), rectImg.Height - (gap * 2)); using (Pen colorPen = new Pen(Color.FromArgb(190, Color.Gainsboro), this.Width / 40)) { g.DrawArc(colorPen, rectg, 135, 270); } // Drawing in opposite order of importance to allow the most important // zones to overwrite the zones of lesser importance in case there // is an overlap. // Draw Recommended zone using (Pen colorPen = new Pen(Color.FromArgb(200, Color.LawnGreen), this.Width / 50)) { drawColorZone(g, gap, rectg, colorPen, this.recommendedValueMin, this.recommendedValueMax); } // Draw Blue zone using (Pen colorPen = new Pen(Color.FromArgb(200, Color.Blue), this.Width / 50)) { drawColorZone(g, gap, rectg, colorPen, this.blueValueMin, this.blueValueMax); } // Draw Yellow zone using (Pen colorPen = new Pen(Color.FromArgb(200, Color.Yellow), this.Width / 50)) { drawColorZone(g, gap, rectg, colorPen, this.yellowValueMin, this.yellowValueMax); } // Draw Red2 zone using (Pen colorPen = new Pen(Color.FromArgb(200, Color.Red), this.Width / 50)) { drawColorZone(g, gap, rectg, colorPen, this.red2ValueMin, this.red2ValueMax); } // Draw Red1 zone using (Pen colorPen = new Pen(Color.FromArgb(200, Color.Red), this.Width / 50)) { drawColorZone(g, gap, rectg, colorPen, this.red1ValueMin, this.red1ValueMax); } // Draw Digital Value RectangleF digiRect = new RectangleF((float)(this.Width / 2F) - (float)(this.width / 5F), (float)this.height / 1.22F, (float)this.width / 2.5F, (float)this.Height / 9F); using (SolidBrush digiBrush = new SolidBrush(Color.FromArgb(30, Color.Gray))) { g.FillRectangle(digiBrush, digiRect); } drawText(g, this.dialText, (int)(this.height / 1.5)); drawText(g, this.digitalGaugeText, (int)(this.height / 1.07)); requiresRedraw = false; } e.Graphics.DrawImage(backgroundImg, rectImg); } } #endregion #region Private methods /// /// Converts the given degree to radian. /// /// Degree value. /// Radian value. private static float GetRadian(float theta) { return theta * (float)Math.PI / 180F; } /// /// Gets Relative X for the given width to draw digit /// /// X to convert. /// Width value. /// Converted value. private static float GetX(float itemX, float itemWidth) { return itemX * itemWidth / 12; } /// /// Gets relative Y for the given height to draw digit /// /// Y to convert. /// Height value. /// Converted value. private static float GetY(float itemY, float itemHeight) { return itemY * itemHeight / 15; } /// /// Returns true if a given number is available in the given list. /// /// Number to look for. /// List to look in. /// 'true' if number exists. private static bool IsNumberAvailable(int number, params int[] listOfNumbers) { if (listOfNumbers.Length > 0) { foreach (int i in listOfNumbers) { if (i == number) return true; } } return false; } /// /// Draw text string. /// /// Graphics instance. /// Text to draw. /// Y-position for text. private void drawText(Graphics g, string text, int yText) { SizeF textSize = g.MeasureString(text, this.Font); RectangleF digiFRectText = new RectangleF((this.Width / 2) - (textSize.Width / 2), yText, textSize.Width, textSize.Height); using (SolidBrush digiFBrush = new SolidBrush(this.ForeColor)) { g.DrawString(text, this.Font, digiFBrush, digiFRectText); } } /// /// Draws zoning band. /// /// Graphics instance. /// Gap value. /// Rectangle covered. /// Color of band. /// Value for start of band /// Value for end of band private void drawColorZone(Graphics g, int gap, Rectangle rectg, Pen colorPen, float minThreshValue, float maxThreshValue) { // Only go through the calculations if necessary. if (maxThreshValue > minThreshValue) { rectg = new Rectangle(rectImg.X + gap, rectImg.Y + gap, rectImg.Width - (gap * 2), rectImg.Height - (gap * 2)); float val = MaxValue - MinValue; float stAngle = (100 * (minThreshValue - MinValue)) / val; stAngle = ((toAngle - fromAngle) * stAngle) / 100; stAngle += fromAngle; float endAngle = (100 * (maxThreshValue - MinValue)) / val; endAngle = ((toAngle - fromAngle) * endAngle) / 100; endAngle += fromAngle; float sweepAngle = endAngle - stAngle; g.DrawArc(colorPen, rectg, stAngle, sweepAngle); } } /// /// Draws the Pointer. /// /// Graphics instance. /// X coordinate. /// Y coordinate. private void DrawPointer(Graphics gr, int cx, int cy) { float radius = (this.Width / 2) - (this.Width * .12F); float val = MaxValue - MinValue; using (Image img = new Bitmap(this.Width, this.Height)) { Graphics g = Graphics.FromImage(img); g.SmoothingMode = SmoothingMode.AntiAlias; val = (100 * (this.currentValue - MinValue)) / val; val = ((toAngle - fromAngle) * val) / 100; val += fromAngle; float angle = GetRadian(val); PointF[] pts = new PointF[5]; pts[0].X = (float)(cx + (radius * Math.Cos(angle))); pts[0].Y = (float)(cy + (radius * Math.Sin(angle))); pts[4].X = (float)(cx + (radius * Math.Cos(angle - 0.02))); pts[4].Y = (float)(cy + (radius * Math.Sin(angle - 0.02))); angle = GetRadian((val + 20)); pts[1].X = (float)(cx + ((this.Width * .09F) * Math.Cos(angle))); pts[1].Y = (float)(cy + ((this.Width * .09F) * Math.Sin(angle))); pts[2].X = cx; pts[2].Y = cy; angle = GetRadian((val - 20)); pts[3].X = (float)(cx + ((this.Width * .09F) * Math.Cos(angle))); pts[3].Y = (float)(cy + ((this.Width * .09F) * Math.Sin(angle))); using (Brush pointer = new SolidBrush(Color.Black)) { g.FillPolygon(pointer, pts); } PointF[] shinePts = new PointF[3]; angle = GetRadian(val); shinePts[0].X = (float)(cx + (radius * Math.Cos(angle))); shinePts[0].Y = (float)(cy + (radius * Math.Sin(angle))); angle = GetRadian(val + 20); shinePts[1].X = (float)(cx + ((this.Width * .09F) * Math.Cos(angle))); shinePts[1].Y = (float)(cy + ((this.Width * .09F) * Math.Sin(angle))); shinePts[2].X = cx; shinePts[2].Y = cy; using (LinearGradientBrush gpointer = new LinearGradientBrush(shinePts[0], shinePts[2], Color.SlateGray, Color.Black)) { g.FillPolygon(gpointer, shinePts); } Rectangle rect = new Rectangle(x, y, width, height); DrawCenterPoint(g, rect, ((width) / 2) + x, ((height) / 2) + y); DrawGloss(g); gr.DrawImage(img, 0, 0); } } /// /// Draws the glossiness. /// /// Graphics instance. private void DrawGloss(Graphics g) { RectangleF glossRect = new RectangleF( x + (float)(width * 0.10), y + (float)(height * 0.07), (float)(width * 0.80), (float)(height * 0.7)); using (LinearGradientBrush gradientBrush = new LinearGradientBrush( glossRect, Color.FromArgb((int)glossinessAlpha, Color.White), Color.Transparent, LinearGradientMode.Vertical)) { g.FillEllipse(gradientBrush, glossRect); } glossRect = new RectangleF( x + (float)(width * 0.25), y + (float)(height * 0.77), (float)(width * 0.50), (float)(height * 0.2)); int gloss = (int)(glossinessAlpha / 3); using (LinearGradientBrush gradientBrush = new LinearGradientBrush( glossRect, Color.Transparent, Color.FromArgb(gloss, this.BackColor), LinearGradientMode.Vertical)) { g.FillEllipse(gradientBrush, glossRect); } } /// /// Draws the center point. /// /// Graphics instance. /// Drawing rectangle. /// Center X. /// Center Y. private void DrawCenterPoint(Graphics g, Rectangle rect, int cX, int cY) { float shift = Width / 5; RectangleF rectangle = new RectangleF(cX - (shift / 2), cY - (shift / 2), shift, shift); using (LinearGradientBrush brush = new LinearGradientBrush(rect, Color.Black, Color.FromArgb(100, this.dialColor), LinearGradientMode.Vertical)) { g.FillEllipse(brush, rectangle); shift = Width / 7; rectangle = new RectangleF(cX - (shift / 2), cY - (shift / 2), shift, shift); } using (LinearGradientBrush brush = new LinearGradientBrush(rect, Color.SlateGray, Color.Black, LinearGradientMode.ForwardDiagonal)) { g.FillEllipse(brush, rectangle); } } /// /// Draws the Ruler /// /// Graphics instance. /// Drawing rectangle. /// Center X. /// Center Y. private void DrawCalibration(Graphics g, Rectangle rect, int cX, int cY) { uint noOfParts = this.noOfDivisions + 1; uint noOfIntermediates = this.noOfSubDivisions; float currentAngle = GetRadian(fromAngle); int gap = (int)(this.Width * 0.01F); float shift = this.Width / 25; Rectangle rectangle = new Rectangle(rect.Left + gap, rect.Top + gap, rect.Width - gap, rect.Height - gap); float itemX, itemY, itemX1, itemY1, itemTX, itemTY, radius; radius = (rectangle.Width / 2) - (gap * 5); float totalAngle = toAngle - fromAngle; float incr = GetRadian(((totalAngle) / ((noOfParts - 1) * (noOfIntermediates + 1)))); using (Pen thickPen = new Pen(Color.Black, Width / 50)) { using (Pen thinPen = new Pen(Color.Black, Width / 100)) { using (StringFormat strFormat = new StringFormat(StringFormatFlags.NoClip)) { strFormat.Alignment = StringAlignment.Center; using (Font f = new Font(this.Font.FontFamily, (float)(this.Width / 23), this.Font.Style)) { using (Brush stringPen = new SolidBrush(this.ForeColor)) { float rulerValue = MinValue; for (int i = 0; i <= noOfParts; i++) { // Draw Thick Line itemX = (float)(cX + (radius * Math.Cos(currentAngle))); itemY = (float)(cY + (radius * Math.Sin(currentAngle))); itemX1 = (float)(cX + ((radius - (Width / 20)) * Math.Cos(currentAngle))); itemY1 = (float)(cY + ((radius - (Width / 20)) * Math.Sin(currentAngle))); g.DrawLine(thickPen, itemX, itemY, itemX1, itemY1); // Draw Strings itemTX = (float)(cX + ((radius - (Width / 10)) * Math.Cos(currentAngle))); itemTY = (float)(cY - shift + ((radius - (Width / 10)) * Math.Sin(currentAngle))); g.DrawString(rulerValue.ToString(CultureInfo.CurrentCulture), f, stringPen, new PointF(itemTX, itemTY), strFormat); rulerValue += (float)((MaxValue - MinValue) / (noOfParts - 1)); rulerValue = (float)Math.Round(rulerValue, 2); // currentAngle += incr; if (i == noOfParts - 1) break; for (int j = 0; j <= noOfIntermediates; j++) { // Draw thin lines currentAngle += incr; itemX = (float)(cX + (radius * Math.Cos(currentAngle))); itemY = (float)(cY + (radius * Math.Sin(currentAngle))); itemX1 = (float)(cX + ((radius - (Width / 50)) * Math.Cos(currentAngle))); itemY1 = (float)(cY + ((radius - (Width / 50)) * Math.Sin(currentAngle))); g.DrawLine(thinPen, itemX, itemY, itemX1, itemY1); } } } } } } } } /// /// Displays the given number in the 7-Segement format. /// /// Graphics instance. /// Number to draw. /// Containing Rectangle [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Justification = "Reviewed.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Windows.Forms.MessageBox.Show(System.String)", Justification = "Reviewed.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Reviewed.")] private void DisplayNumber(Graphics g, float number, RectangleF drect) { try { string num = number.ToString(this.digitMask, CultureInfo.InvariantCulture); num = num.PadLeft(3, '0'); float shift = 0; if (number < 0) { shift -= width / 17; } char[] chars = num.ToCharArray(); for (int i = 0; i < chars.Length; i++) { char c = chars[i]; bool drawDPS = (i < chars.Length - 1 && chars[i + 1] == '.'); if (c != '.') { if (c == '-') { DrawDigit(g, -1, new PointF(drect.X + shift, drect.Y), drawDPS, drect.Height); } else { if (c >= '0' && c <= '9') { int val = (int)c - '0'; DrawDigit(g, val, new PointF(drect.X + shift, drect.Y), drawDPS, drect.Height); } } shift += 15 * this.width / 250; } else { shift += 2 * this.width / 250; } } } catch (Exception ex) { MessageBox.Show(ex.GetType().ToString() + ": " + ex.Message); } } /// /// Draws a digit in 7-Segement format. /// /// Graphics instance. /// Number to draw. /// Position for item. /// Decimal point. /// Height of digit. private void DrawDigit(Graphics g, int number, PointF position, bool dp, float digitHeight) { float digitWidth = 10F * digitHeight / 13; // Segment A PointF[] segmentA = new PointF[5]; segmentA[0] = segmentA[4] = new PointF(position.X + GetX(2.8F, digitWidth), position.Y + GetY(1F, digitHeight)); segmentA[1] = new PointF(position.X + GetX(10, digitWidth), position.Y + GetY(1F, digitHeight)); segmentA[2] = new PointF(position.X + GetX(8.8F, digitWidth), position.Y + GetY(2F, digitHeight)); segmentA[3] = new PointF(position.X + GetX(3.8F, digitWidth), position.Y + GetY(2F, digitHeight)); // Segment B PointF[] segmentB = new PointF[5]; segmentB[0] = segmentB[4] = new PointF(position.X + GetX(10, digitWidth), position.Y + GetY(1.4F, digitHeight)); segmentB[1] = new PointF(position.X + GetX(9.3F, digitWidth), position.Y + GetY(6.8F, digitHeight)); segmentB[2] = new PointF(position.X + GetX(8.4F, digitWidth), position.Y + GetY(6.4F, digitHeight)); segmentB[3] = new PointF(position.X + GetX(9F, digitWidth), position.Y + GetY(2.2F, digitHeight)); // Segment C PointF[] segmentC = new PointF[5]; segmentC[0] = segmentC[4] = new PointF(position.X + GetX(9.2F, digitWidth), position.Y + GetY(7.2F, digitHeight)); segmentC[1] = new PointF(position.X + GetX(8.7F, digitWidth), position.Y + GetY(12.7F, digitHeight)); segmentC[2] = new PointF(position.X + GetX(7.6F, digitWidth), position.Y + GetY(11.9F, digitHeight)); segmentC[3] = new PointF(position.X + GetX(8.2F, digitWidth), position.Y + GetY(7.7F, digitHeight)); // Segment D PointF[] segmentD = new PointF[5]; segmentD[0] = segmentD[4] = new PointF(position.X + GetX(7.4F, digitWidth), position.Y + GetY(12.1F, digitHeight)); segmentD[1] = new PointF(position.X + GetX(8.4F, digitWidth), position.Y + GetY(13F, digitHeight)); segmentD[2] = new PointF(position.X + GetX(1.3F, digitWidth), position.Y + GetY(13F, digitHeight)); segmentD[3] = new PointF(position.X + GetX(2.2F, digitWidth), position.Y + GetY(12.1F, digitHeight)); // Segment E PointF[] segmentE = new PointF[5]; segmentE[0] = segmentE[4] = new PointF(position.X + GetX(2.2F, digitWidth), position.Y + GetY(11.8F, digitHeight)); segmentE[1] = new PointF(position.X + GetX(1F, digitWidth), position.Y + GetY(12.7F, digitHeight)); segmentE[2] = new PointF(position.X + GetX(1.7F, digitWidth), position.Y + GetY(7.2F, digitHeight)); segmentE[3] = new PointF(position.X + GetX(2.8F, digitWidth), position.Y + GetY(7.7F, digitHeight)); // Segment F PointF[] segmentF = new PointF[5]; segmentF[0] = segmentF[4] = new PointF(position.X + GetX(3F, digitWidth), position.Y + GetY(6.4F, digitHeight)); segmentF[1] = new PointF(position.X + GetX(1.8F, digitWidth), position.Y + GetY(6.8F, digitHeight)); segmentF[2] = new PointF(position.X + GetX(2.6F, digitWidth), position.Y + GetY(1.3F, digitHeight)); segmentF[3] = new PointF(position.X + GetX(3.6F, digitWidth), position.Y + GetY(2.2F, digitHeight)); // Segment G PointF[] segmentG = new PointF[7]; segmentG[0] = segmentG[6] = new PointF(position.X + GetX(2F, digitWidth), position.Y + GetY(7F, digitHeight)); segmentG[1] = new PointF(position.X + GetX(3.1F, digitWidth), position.Y + GetY(6.5F, digitHeight)); segmentG[2] = new PointF(position.X + GetX(8.3F, digitWidth), position.Y + GetY(6.5F, digitHeight)); segmentG[3] = new PointF(position.X + GetX(9F, digitWidth), position.Y + GetY(7F, digitHeight)); segmentG[4] = new PointF(position.X + GetX(8.2F, digitWidth), position.Y + GetY(7.5F, digitHeight)); segmentG[5] = new PointF(position.X + GetX(2.9F, digitWidth), position.Y + GetY(7.5F, digitHeight)); using (Pen outline = new Pen(Color.FromArgb(40, this.dialColor))) { // Segment DP g.FillPolygon(outline.Brush, segmentA); g.FillPolygon(outline.Brush, segmentB); g.FillPolygon(outline.Brush, segmentC); g.FillPolygon(outline.Brush, segmentD); g.FillPolygon(outline.Brush, segmentE); g.FillPolygon(outline.Brush, segmentF); g.FillPolygon(outline.Brush, segmentG); } using (Pen fillPen = new Pen(Color.Black)) { // Fill SegmentA if (IsNumberAvailable(number, 0, 2, 3, 5, 6, 7, 8, 9)) { g.FillPolygon(fillPen.Brush, segmentA); } // Fill SegmentB if (IsNumberAvailable(number, 0, 1, 2, 3, 4, 7, 8, 9)) { g.FillPolygon(fillPen.Brush, segmentB); } // Fill SegmentC if (IsNumberAvailable(number, 0, 1, 3, 4, 5, 6, 7, 8, 9)) { g.FillPolygon(fillPen.Brush, segmentC); } // Fill SegmentD if (IsNumberAvailable(number, 0, 2, 3, 5, 6, 8, 9)) { g.FillPolygon(fillPen.Brush, segmentD); } // Fill SegmentE if (IsNumberAvailable(number, 0, 2, 6, 8)) { g.FillPolygon(fillPen.Brush, segmentE); } // Fill SegmentF if (IsNumberAvailable(number, 0, 4, 5, 6, 7, 8, 9)) { g.FillPolygon(fillPen.Brush, segmentF); } // Fill SegmentG if (IsNumberAvailable(number, 2, 3, 4, 5, 6, 8, 9, -1)) { g.FillPolygon(fillPen.Brush, segmentG); } // Draw decimal point if (dp) { g.FillEllipse( fillPen.Brush, new RectangleF( position.X + GetX(10F, digitWidth), position.Y + GetY(12F, digitHeight), digitWidth / 7, digitWidth / 7)); } } } /// /// Restricts the size to make sure the height and width are always same. /// /// Sending object. /// Event data. private void AquaGauge_Resize(object sender, EventArgs e) { if (this.Width < 136) { this.Width = 136; } if (oldWidth != this.Width) { this.Height = this.Width; oldHeight = this.Width; } if (oldHeight != this.Height) { this.Width = this.Height; oldWidth = this.Width; } } #endregion } }