1using System; 2using System.Drawing; 3using System.Drawing.Drawing2D; 4using System.Windows.Forms; 5using System.Collections.Generic; 6using WindowCapture.Helpers; 7 8namespace WindowCapture.UI 9{ 10 // Glass-style numeric control 11 public class DarkNumeric : Control 12 { 13 private static readonly Color GE = Color.FromArgb(225, 232, 245); 14 15 private int _value, _min, _max; 16 private bool hoverUp, hoverDown; 17 private Timer repeatTimer; 18 private int repeatDir; 19 20 public event EventHandler ValueChanged; 21 22 public int Value 23 { 24 get { return _value; } 25 set { int v = Math.Max(_min, Math.Min(_max, value)); if (v != _value) { _value = v; Invalidate(); if (ValueChanged != null) ValueChanged(this, EventArgs.Empty); } } 26 } 27 public int Minimum { get { return _min; } set { _min = value; } } 28 public int Maximum { get { return _max; } set { _max = value; } } 29 30 public DarkNumeric() 31 { 32 SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor, true); 33 BackColor = Color.Transparent; 34 Size = new Size(80, 26); Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel); 35 _min = 0; _max = 100; _value = 0; 36 repeatTimer = new Timer(); repeatTimer.Interval = 100; 37 repeatTimer.Tick += (s, e) => { ChangeValue(repeatDir); }; 38 } 39 40 protected override void OnPaint(PaintEventArgs e) 41 { 42 var g = e.Graphics; 43 float glow = GlowHelper.ComputeGlow(this); 44 45 // Glass fill — brighter when cursor near 46 int fillA = 12 + (int)(18 * glow); 47 using (var brush = new SolidBrush(Color.FromArgb(fillA, GE))) 48 g.FillRectangle(brush, 0, 0, Width, Height); 49 // Glass border — glows with cursor 50 int borderA = 40 + (int)(60 * glow); 51 using (var pen = new Pen(Color.FromArgb(borderA, GE), 1f)) 52 g.DrawRectangle(pen, 0, 0, Width - 1, Height - 1); 53 54 // Value text — uses adaptive color for background visibility 55 g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; 56 Color tc = SettingsDialog.AdaptiveTextColor; 57 int textA = 160 + (int)(65 * glow); 58 using (var brush = new SolidBrush(Color.FromArgb(textA, tc))) 59 { 60 var sf = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }; 61 g.DrawString(_value.ToString(), Font, brush, new Rectangle(7, 0, Width - 30, Height), sf); 62 } 63 64 // Up/Down arrows with glass hover 65 int btnW = 22, btnH = Height / 2; 66 if (hoverUp) using (var brush = new SolidBrush(Color.FromArgb(25, tc))) g.FillRectangle(brush, Width - btnW, 0, btnW, btnH); 67 if (hoverDown) using (var brush = new SolidBrush(Color.FromArgb(25, tc))) g.FillRectangle(brush, Width - btnW, btnH, btnW, btnH); 68 // Separator line 69 int sepA = 30 + (int)(30 * glow); 70 using (var pen = new Pen(Color.FromArgb(sepA, tc), 1f)) g.DrawLine(pen, Width - btnW, 0, Width - btnW, Height); 71 72 DrawGlassArrow(g, new Rectangle(Width - btnW, 0, btnW, btnH), true, hoverUp, glow); 73 DrawGlassArrow(g, new Rectangle(Width - btnW, btnH, btnW, btnH), false, hoverDown, glow); 74 } 75 76 private void DrawGlassArrow(Graphics g, Rectangle r, bool up, bool hov, float glow) 77 { 78 Color tc = SettingsDialog.AdaptiveTextColor; 79 int cx = r.X + r.Width / 2, cy = r.Y + r.Height / 2, sz = 3; 80 Point[] pts = up 81 ? new Point[] { new Point(cx - sz, cy + 1), new Point(cx + sz, cy + 1), new Point(cx, cy - 2) } 82 : new Point[] { new Point(cx - sz, cy - 1), new Point(cx + sz, cy - 1), new Point(cx, cy + 2) }; 83 int arrowA = (int)((hov ? 180 : 80) + (40 * glow)); 84 if (arrowA > 255) arrowA = 255; 85 using (var brush = new SolidBrush(Color.FromArgb(arrowA, tc))) 86 g.FillPolygon(brush, pts); 87 } 88 89 protected override void OnMouseMove(MouseEventArgs e) 90 { 91 int btnW = 22, btnH = Height / 2; 92 bool u = e.X >= Width - btnW && e.Y < btnH, d = e.X >= Width - btnW && e.Y >= btnH; 93 if (u != hoverUp || d != hoverDown) { hoverUp = u; hoverDown = d; Invalidate(); } 94 } 95 protected override void OnMouseLeave(EventArgs e) { hoverUp = hoverDown = false; Invalidate(); } 96 protected override void OnMouseDown(MouseEventArgs e) 97 { 98 int btnW = 22, btnH = Height / 2; 99 if (e.X >= Width - btnW) { int dir = e.Y < btnH ? 1 : -1; ChangeValue(dir); repeatDir = dir; repeatTimer.Start(); } 100 } 101 protected override void OnMouseUp(MouseEventArgs e) { repeatTimer.Stop(); } 102 protected override void OnMouseWheel(MouseEventArgs e) { ChangeValue(e.Delta > 0 ? 1 : -1); } 103 104 private void ChangeValue(int delta) 105 { 106 int v = _value + delta; 107 if (v >= _min && v <= _max) { _value = v; Invalidate(); if (ValueChanged != null) ValueChanged(this, EventArgs.Empty); } 108 } 109 110 protected override void Dispose(bool disposing) 111 { if (disposing && repeatTimer != null) { repeatTimer.Dispose(); repeatTimer = null; } base.Dispose(disposing); } 112 } 113}