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 // Font size control with geometric progression after 16pt 11 public class DarkFontSizeNumeric : Control 12 { 13 private static readonly Color GE = Color.FromArgb(225, 232, 245); 14 15 // Preset sizes: 8-16 linear, then geometric up to 300 16 private static readonly int[] FontSizes = { 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 24, 28, 32, 36, 42, 48, 56, 64, 72, 84, 96, 110, 128, 150, 175, 200, 230, 265, 300 }; 17 18 private int _sizeIndex; 19 private bool hoverUp, hoverDown; 20 private Timer repeatTimer; 21 private int repeatDir; 22 23 public event EventHandler ValueChanged; 24 25 public int Value 26 { 27 get { return FontSizes[_sizeIndex]; } 28 set 29 { 30 int newIdx = FindClosestIndex(value); 31 if (newIdx != _sizeIndex) 32 { 33 _sizeIndex = newIdx; 34 Invalidate(); 35 if (ValueChanged != null) ValueChanged(this, EventArgs.Empty); 36 } 37 } 38 } 39 40 private int FindClosestIndex(int size) 41 { 42 for (int i = 0; i < FontSizes.Length; i++) 43 { 44 if (FontSizes[i] >= size) return i; 45 } 46 return FontSizes.Length - 1; 47 } 48 49 public DarkFontSizeNumeric() 50 { 51 SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor, true); 52 BackColor = Color.Transparent; 53 Size = new Size(70, 26); 54 Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel); 55 _sizeIndex = 4; // default 12 56 57 repeatTimer = new Timer(); 58 repeatTimer.Interval = 150; 59 repeatTimer.Tick += (s, e) => { ChangeValue(repeatDir); }; 60 } 61 62 protected override void OnPaint(PaintEventArgs e) 63 { 64 var g = e.Graphics; 65 float glow = GlowHelper.ComputeGlow(this); 66 int fillA = 12 + (int)(18 * glow); 67 using (var brush = new SolidBrush(Color.FromArgb(fillA, GE))) 68 g.FillRectangle(brush, 0, 0, Width, Height); 69 int borderA = 40 + (int)(60 * glow); 70 using (var pen = new Pen(Color.FromArgb(borderA, GE), 1f)) 71 g.DrawRectangle(pen, 0, 0, Width - 1, Height - 1); 72 73 g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; 74 Color tc = SettingsDialog.AdaptiveTextColor; 75 int textA = 160 + (int)(65 * glow); 76 using (var brush = new SolidBrush(Color.FromArgb(textA, tc))) 77 { 78 var sf = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }; 79 g.DrawString(Value.ToString(), Font, brush, new Rectangle(7, 0, Width - 30, Height), sf); 80 } 81 82 int btnW = 22, btnH = Height / 2; 83 if (hoverUp) using (var brush = new SolidBrush(Color.FromArgb(25, tc))) g.FillRectangle(brush, Width - btnW, 0, btnW, btnH); 84 if (hoverDown) using (var brush = new SolidBrush(Color.FromArgb(25, tc))) g.FillRectangle(brush, Width - btnW, btnH, btnW, btnH); 85 int sepA = 30 + (int)(30 * glow); 86 using (var pen = new Pen(Color.FromArgb(sepA, tc), 1f)) g.DrawLine(pen, Width - btnW, 0, Width - btnW, Height); 87 88 DrawGlassArrow(g, new Rectangle(Width - btnW, 0, btnW, btnH), true, hoverUp, glow); 89 DrawGlassArrow(g, new Rectangle(Width - btnW, btnH, btnW, btnH), false, hoverDown, glow); 90 } 91 92 private void DrawGlassArrow(Graphics g, Rectangle r, bool up, bool hov, float glow) 93 { 94 Color tc = SettingsDialog.AdaptiveTextColor; 95 int cx = r.X + r.Width / 2, cy = r.Y + r.Height / 2, sz = 3; 96 Point[] pts = up 97 ? new Point[] { new Point(cx - sz, cy + 1), new Point(cx + sz, cy + 1), new Point(cx, cy - 2) } 98 : new Point[] { new Point(cx - sz, cy - 1), new Point(cx + sz, cy - 1), new Point(cx, cy + 2) }; 99 int arrowA = (int)((hov ? 180 : 80) + (40 * glow)); 100 if (arrowA > 255) arrowA = 255; 101 using (var brush = new SolidBrush(Color.FromArgb(arrowA, tc))) 102 g.FillPolygon(brush, pts); 103 } 104 105 protected override void OnMouseMove(MouseEventArgs e) 106 { 107 int btnW = 20; 108 int btnH = Height / 2; 109 bool newHoverUp = e.X >= Width - btnW && e.Y < btnH; 110 bool newHoverDown = e.X >= Width - btnW && e.Y >= btnH; 111 112 if (newHoverUp != hoverUp || newHoverDown != hoverDown) 113 { 114 hoverUp = newHoverUp; 115 hoverDown = newHoverDown; 116 Invalidate(); 117 } 118 } 119 120 protected override void OnMouseLeave(EventArgs e) 121 { 122 hoverUp = hoverDown = false; 123 Invalidate(); 124 } 125 126 protected override void OnMouseDown(MouseEventArgs e) 127 { 128 int btnW = 20; 129 int btnH = Height / 2; 130 131 if (e.X >= Width - btnW) 132 { 133 if (e.Y < btnH) 134 { 135 ChangeValue(1); 136 repeatDir = 1; 137 repeatTimer.Start(); 138 } 139 else 140 { 141 ChangeValue(-1); 142 repeatDir = -1; 143 repeatTimer.Start(); 144 } 145 } 146 } 147 148 protected override void OnMouseUp(MouseEventArgs e) 149 { 150 repeatTimer.Stop(); 151 } 152 153 protected override void OnMouseWheel(MouseEventArgs e) 154 { 155 ChangeValue(e.Delta > 0 ? 1 : -1); 156 } 157 158 private void ChangeValue(int delta) 159 { 160 int newIdx = _sizeIndex + delta; 161 if (newIdx >= 0 && newIdx < FontSizes.Length) 162 { 163 _sizeIndex = newIdx; 164 Invalidate(); 165 if (ValueChanged != null) ValueChanged(this, EventArgs.Empty); 166 } 167 } 168 169 protected override void Dispose(bool disposing) 170 { 171 if (disposing && repeatTimer != null) 172 { 173 repeatTimer.Dispose(); 174 repeatTimer = null; 175 } 176 base.Dispose(disposing); 177 } 178 } 179}