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 scrollable panel — replaces native AutoScroll with custom glass scrollbar 11 public class GlassScrollPanel : Panel 12 { 13 private static readonly Color GE = Color.FromArgb(225, 232, 245); 14 private Panel innerPanel; 15 private int scrollY; 16 private int contentHeight; 17 private bool thumbHover, thumbDrag; 18 private int dragStartMouseY, dragStartScroll; 19 private const int ScrollBarW = 6; 20 private const int ThumbMinH = 20; 21 22 public Panel Content { get { return innerPanel; } } 23 24 public GlassScrollPanel() 25 { 26 SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true); 27 BackColor = Color.Transparent; 28 innerPanel = new Panel(); 29 innerPanel.BackColor = Color.Transparent; 30 innerPanel.Location = new Point(0, 0); 31 Controls.Add(innerPanel); 32 } 33 34 public void SetupScroll() 35 { 36 // Measure content height from children 37 contentHeight = 0; 38 foreach (Control c in innerPanel.Controls) 39 { 40 int bot = c.Bottom + 10; 41 if (bot > contentHeight) contentHeight = bot; 42 } 43 innerPanel.Size = new Size(NeedScroll ? Width - ScrollBarW - 2 : Width, Math.Max(contentHeight, Height)); 44 ClampScroll(); 45 Invalidate(); 46 } 47 48 private bool NeedScroll { get { return contentHeight > Height; } } 49 private int MaxScroll { get { return Math.Max(0, contentHeight - Height); } } 50 51 private int ThumbH 52 { 53 get 54 { 55 if (!NeedScroll) return 0; 56 int h = (int)((float)Height * Height / contentHeight); 57 return Math.Max(ThumbMinH, Math.Min(Height - 4, h)); 58 } 59 } 60 61 private int ThumbY 62 { 63 get 64 { 65 if (MaxScroll <= 0) return 2; 66 int trackH = Height - ThumbH - 4; 67 return 2 + (int)((float)scrollY / MaxScroll * trackH); 68 } 69 } 70 71 private Rectangle ThumbRect 72 { 73 get { return new Rectangle(Width - ScrollBarW, ThumbY, ScrollBarW - 1, ThumbH); } 74 } 75 76 private void ClampScroll() 77 { 78 scrollY = Math.Max(0, Math.Min(MaxScroll, scrollY)); 79 innerPanel.Top = -scrollY; 80 } 81 82 protected override void OnPaint(PaintEventArgs e) 83 { 84 if (!NeedScroll) return; 85 var g = e.Graphics; 86 float glow = GlowHelper.ComputeGlow(this); 87 Color sc = SettingsDialog.AdaptiveTextColor; 88 // Track with glow 89 int trackA = 10 + (int)(12 * glow); 90 using (var brush = new SolidBrush(Color.FromArgb(trackA, sc))) 91 g.FillRectangle(brush, Width - ScrollBarW - 1, 0, ScrollBarW + 1, Height); 92 // Thumb with glow 93 var tr = ThumbRect; 94 int alpha = (thumbDrag ? 80 : (thumbHover ? 55 : 30)) + (int)(30 * glow); 95 if (alpha > 255) alpha = 255; 96 using (var brush = new SolidBrush(Color.FromArgb(alpha, sc))) 97 g.FillRectangle(brush, tr); 98 } 99 100 protected override void OnMouseWheel(MouseEventArgs e) 101 { 102 if (!NeedScroll) return; 103 scrollY -= e.Delta / 4; 104 ClampScroll(); 105 Invalidate(); 106 } 107 108 protected override void OnMouseDown(MouseEventArgs e) 109 { 110 if (!NeedScroll) return; 111 if (e.X >= Width - ScrollBarW - 2) 112 { 113 var tr = ThumbRect; 114 if (tr.Contains(e.Location)) 115 { 116 thumbDrag = true; 117 dragStartMouseY = e.Y; 118 dragStartScroll = scrollY; 119 Capture = true; 120 Invalidate(); 121 } 122 else 123 { 124 // Click on track — jump to position 125 int trackH = Height - ThumbH - 4; 126 if (trackH > 0) 127 { 128 float ratio = (float)(e.Y - ThumbH / 2 - 2) / trackH; 129 scrollY = (int)(ratio * MaxScroll); 130 ClampScroll(); 131 Invalidate(); 132 } 133 } 134 } 135 } 136 137 protected override void OnMouseMove(MouseEventArgs e) 138 { 139 if (thumbDrag) 140 { 141 int trackH = Height - ThumbH - 4; 142 if (trackH > 0) 143 { 144 int delta = e.Y - dragStartMouseY; 145 scrollY = dragStartScroll + (int)((float)delta / trackH * MaxScroll); 146 ClampScroll(); 147 Invalidate(); 148 } 149 } 150 else if (NeedScroll) 151 { 152 bool newHover = ThumbRect.Contains(e.Location); 153 if (newHover != thumbHover) { thumbHover = newHover; Invalidate(); } 154 } 155 } 156 157 protected override void OnMouseUp(MouseEventArgs e) 158 { 159 if (thumbDrag) 160 { 161 thumbDrag = false; 162 Capture = false; 163 Invalidate(); 164 } 165 } 166 167 protected override void OnMouseLeave(EventArgs e) 168 { 169 if (thumbHover) { thumbHover = false; Invalidate(); } 170 } 171 172 protected override void OnResize(EventArgs e) 173 { 174 base.OnResize(e); 175 if (innerPanel != null) SetupScroll(); 176 } 177 178 // Forward mouse wheel from child controls 179 public void HookChildWheelEvents(Control parent) 180 { 181 foreach (Control c in parent.Controls) 182 { 183 c.MouseWheel += (s, ev) => { OnMouseWheel(ev); }; 184 if (c.Controls.Count > 0) HookChildWheelEvents(c); 185 } 186 } 187 } 188}