windowcapture
исходный код / UI/Controls/GlassScrollPanel.cs

GlassScrollPanel.cs

188 строк · 6,248 байт · модуль UI
  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}