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

SettingsDialog.cs

1377 строк · 58,404 байт · модуль UI
   1using System;
   2using System.Drawing;
   3using System.Drawing.Drawing2D;
   4using System.Reflection;
   5using System.Windows.Forms;
   6using System.Collections.Generic;
   7using WindowCapture.Helpers;
   8using WindowCapture.Models;
   9using WindowCapture.Native;
  10
  11namespace WindowCapture.UI
  12{
  13    public class SettingsDialog : Form
  14    {
  15        // Glass theme colors
  16        private static readonly Color GlassBg = Color.FromArgb(18, 20, 24);
  17        private static readonly Color DarkBg = Color.FromArgb(18, 20, 24);
  18        private static readonly Color DarkPanel = Color.FromArgb(22, 24, 28);
  19        private static readonly Color DarkControl = Color.FromArgb(32, 34, 40);
  20        private static readonly Color DarkBorder = Color.FromArgb(55, 60, 72);
  21        private static readonly Color GlassEdge = Color.FromArgb(225, 232, 245);
  22        private static readonly Color TextColor = Color.FromArgb(210, 218, 235);
  23        private static readonly Color DimText = Color.FromArgb(100, 110, 130);
  24        private static readonly Color AccentColor = Color.FromArgb(70, 130, 200);
  25
  26        // Get all installed system fonts
  27        private static List<string> GetSystemFonts()
  28        {
  29            var fonts = new List<string>();
  30            foreach (var family in System.Drawing.FontFamily.Families)
  31            {
  32                fonts.Add(family.Name);
  33            }
  34            return fonts;
  35        }
  36
  37        // Custom tab system
  38        private Panel tabPanel;
  39        private Panel contentPanel;
  40        private int selectedTab = 0;
  41        private string[] tabNames = { "General", "Effects", "Video", "Keys", "Text" };
  42        private Panel[] tabPages;
  43
  44        // General settings controls
  45        private DarkNumeric nudHighlightAlpha;
  46        private Button btnHighlightColor;
  47        private Button btnHighlightBorderColor;
  48        private DarkNumeric nudBorderWidth;
  49        private CheckBox chkShowBorder;
  50        private CheckBox chkDimAround;
  51        private DarkNumeric nudMarkerSize;
  52        private Button btnMarkerColor;
  53        private Button btnArrowColor;
  54        private CheckBox chkAutoFit;
  55        private DarkNumeric nudDefaultWidth;
  56        private DarkNumeric nudDefaultHeight;
  57
  58        // Window appearance controls
  59        private DarkNumeric nudBlurTintAlpha;
  60        private Button btnBlurTintColor;
  61        // Blur mode removed — always BlurBehind with noise grain
  62        private DarkNumeric nudCornerRadius;
  63        private DarkNumeric nudNoiseIntensity;
  64        private CheckBox chkWindowBorder;
  65
  66        // Effects settings controls
  67        private DarkFloatNumeric nudBlurRadius;
  68        private DarkNumeric nudMotionBlurDistance;
  69        private DarkNumeric nudDimAlpha;
  70        private DarkNumeric nudFeatherWidth;
  71        private CheckBox chkEnableFadeBlur;
  72        private DarkNumeric nudFadeBlurWidth;
  73
  74        // Text settings controls
  75        private DarkComboBox cmbTextFont;
  76        private DarkNumeric nudTextFontSize;
  77        private Button btnTextColor;
  78        private Button btnTextShadowColor;
  79        private DarkNumeric nudShadowOffset;
  80
  81        // Video recording controls
  82        private DarkNumeric nudVideoFps;
  83        private DarkNumeric nudVideoJpegQuality;
  84        private CheckBox chkRecordSystemAudio;
  85        private CheckBox chkRecordMicrophone;
  86
  87        // Key bindings controls
  88        private Panel keysListPanel;
  89        private DarkComboBox cmbActivationKey;
  90
  91        // Text processing controls
  92        private CheckBox chkAutoLangSwitch;
  93        private CheckBox chkAutoT9;
  94        private DarkNumeric nudT9Sensitivity;
  95        private CheckBox chkT9ShowTooltip;
  96
  97        // Form dragging
  98        private bool formDragging;
  99        private Point formDragStart;
 100
 101        // Glass shimmer — cursor-proximity glow on all elements
 102        private Timer shimmerTimer;
 103        private List<Label> shimmerLabels = new List<Label>();
 104        private List<Control> glowControls = new List<Control>();
 105        private Point lastShimmerCursorPos = new Point(-9999, -9999);
 106        private const float ShimmerRadius = 150f;
 107        private const float ShimmerFullRadius = 30f;
 108
 109        // Background-adaptive colors
 110        private Bitmap bgCapture;
 111        private Color adaptiveDim = DimText;
 112        private Color adaptiveGlow = GlassEdge;
 113
 114        private bool closing;
 115
 116        // Saved original blur settings for cancel/restore
 117        private int origBlurTintAlpha;
 118        private Color origBlurTintColor;
 119        private int origCornerRadius;
 120        private bool origShowBorder;
 121        private int origNoiseIntensity;
 122
 123        // Panels we need to invalidate for glow
 124        private Panel titleBarRef;
 125        private Panel buttonPanelRef;
 126
 127        // Enable double buffering on any control (prevents flicker on DWM-blurred windows)
 128        private static void EnableDoubleBuffer(Control c)
 129        {
 130            typeof(Control).InvokeMember("DoubleBuffered",
 131                BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
 132                null, c, new object[] { true });
 133        }
 134
 135        public SettingsDialog()
 136        {
 137            // Save original blur settings for cancel/restore
 138            origBlurTintAlpha = Settings.BlurTintAlpha;
 139            origBlurTintColor = Settings.BlurTintColor;
 140            origCornerRadius = Settings.CornerRadius;
 141            origShowBorder = Settings.ShowWindowBorder;
 142            origNoiseIntensity = Settings.NoiseIntensity;
 143
 144            InitializeComponents();
 145            LoadSettings();
 146        }
 147
 148        private void InitializeComponents()
 149        {
 150            Text = "Settings";
 151            Size = new Size(520, 560);
 152            FormBorderStyle = FormBorderStyle.None;
 153            MaximizeBox = false;
 154            MinimizeBox = false;
 155            StartPosition = FormStartPosition.CenterScreen;
 156            BackColor = GlassBg;
 157            DoubleBuffered = true;
 158
 159            // Shimmer timer — tracks cursor for glass label glow
 160            shimmerTimer = new Timer();
 161            shimmerTimer.Interval = 40;
 162            shimmerTimer.Tick += ShimmerTimer_Tick;
 163            shimmerTimer.Start();
 164
 165            // Capture background before showing, then enable DWM blur
 166            Shown += delegate { EnableDialogBlur(); };
 167            // Capture background BEFORE form is shown for adaptive text colors
 168            CaptureBackground();
 169
 170            // Custom title bar — glass style (double-buffered to prevent flicker)
 171            Panel titleBar = new Panel();
 172            titleBar.Dock = DockStyle.Top;
 173            titleBar.Height = 36;
 174            titleBar.BackColor = Color.Transparent;
 175            EnableDoubleBuffer(titleBar);
 176            titleBar.MouseDown += (s, e) => { if (e.Button == MouseButtons.Left) { formDragging = true; formDragStart = e.Location; } };
 177            titleBar.MouseMove += (s, e) => { if (formDragging) Location = new Point(Location.X + e.X - formDragStart.X, Location.Y + e.Y - formDragStart.Y); };
 178            titleBar.MouseUp += (s, e) => { formDragging = false; };
 179            titleBar.Paint += TitleBar_Paint;
 180            titleBarRef = titleBar;
 181
 182            // Close button — glass style
 183            Button btnClose = CreateButton("\u2715", titleBar.Width - 40, 5, 32, 26);
 184            btnClose.Anchor = AnchorStyles.Top | AnchorStyles.Right;
 185            btnClose.BackColor = Color.FromArgb(1, 0, 0, 0);
 186            btnClose.FlatAppearance.MouseOverBackColor = Color.FromArgb(60, 220, 80, 80);
 187            btnClose.Click += (s, e) => { if (closing) return; closing = true; RestoreBlurSettings(); DialogResult = DialogResult.Cancel; Close(); };
 188            titleBar.Controls.Add(btnClose);
 189
 190            // Custom tab panel (left side) — glass style, double-buffered
 191            tabPanel = new Panel();
 192            tabPanel.Location = new Point(0, 36);
 193            tabPanel.Size = new Size(105, Height - 36 - 52);
 194            tabPanel.BackColor = Color.Transparent;
 195            EnableDoubleBuffer(tabPanel);
 196            tabPanel.Paint += TabPanel_Paint;
 197            tabPanel.MouseClick += TabPanel_MouseClick;
 198
 199            // Content panel (right side) — transparent, double-buffered
 200            contentPanel = new Panel();
 201            contentPanel.Location = new Point(105, 36);
 202            contentPanel.Size = new Size(Width - 105, Height - 36 - 52);
 203            contentPanel.BackColor = Color.Transparent;
 204            EnableDoubleBuffer(contentPanel);
 205
 206            // Create tab pages
 207            tabPages = new Panel[5];
 208
 209            tabPages[0] = CreateGeneralPage();
 210            tabPages[1] = CreateEffectsPage();
 211            tabPages[2] = CreateVideoPage();
 212            tabPages[3] = CreateKeysPage();
 213            tabPages[4] = CreateTextPage();
 214
 215            foreach (var page in tabPages)
 216            {
 217                page.Visible = false;
 218                contentPanel.Controls.Add(page);
 219            }
 220            tabPages[0].Visible = true;
 221
 222            // Buttons panel — glass style, double-buffered
 223            Panel buttonPanel = new Panel();
 224            buttonPanel.Dock = DockStyle.Bottom;
 225            buttonPanel.Height = 52;
 226            buttonPanel.BackColor = Color.Transparent;
 227            EnableDoubleBuffer(buttonPanel);
 228            buttonPanel.Paint += ButtonPanel_Paint;
 229            buttonPanelRef = buttonPanel;
 230
 231            Button btnSave = CreateButton("Save", 310, 11, 90, 30);
 232            btnSave.BackColor = Color.FromArgb(50, AccentColor);
 233            btnSave.FlatAppearance.MouseOverBackColor = Color.FromArgb(90, AccentColor);
 234            btnSave.Click += delegate { if (closing) return; closing = true; SaveSettings(); DialogResult = DialogResult.OK; Close(); };
 235
 236            Button btnCancel = CreateButton("Cancel", 410, 11, 90, 30);
 237            btnCancel.Click += delegate { if (closing) return; closing = true; RestoreBlurSettings(); DialogResult = DialogResult.Cancel; Close(); };
 238
 239            Button btnReset = CreateButton("Reset", 10, 11, 90, 30);
 240            btnReset.Click += delegate { ResetToDefaults(); };
 241
 242            buttonPanel.Controls.Add(btnSave);
 243            buttonPanel.Controls.Add(btnCancel);
 244            buttonPanel.Controls.Add(btnReset);
 245
 246            Controls.Add(contentPanel);
 247            Controls.Add(tabPanel);
 248            Controls.Add(buttonPanel);
 249            Controls.Add(titleBar);
 250        }
 251
 252        private void EnableDialogBlur()
 253        {
 254            BlurHelper.Apply(Handle);
 255        }
 256
 257        private void CaptureBackground()
 258        {
 259            try
 260            {
 261                // Capture screen area where dialog will appear (before it's visible)
 262                var screen = Screen.PrimaryScreen.WorkingArea;
 263                int dx = (screen.Width - Width) / 2 + screen.X;
 264                int dy = (screen.Height - Height) / 2 + screen.Y;
 265                bgCapture = new Bitmap(Width, Height);
 266                using (var g = Graphics.FromImage(bgCapture))
 267                    g.CopyFromScreen(dx, dy, 0, 0, new Size(Width, Height));
 268            }
 269            catch { bgCapture = null; }
 270
 271            // Compute adaptive colors from actual Settings tint + captured background
 272            ComputeAdaptiveColors();
 273        }
 274
 275        private void ComputeAdaptiveColors()
 276        {
 277            // Use real settings tint values
 278            float ta = Settings.BlurTintAlpha / 255f;
 279            float tintR = Settings.BlurTintColor.R;
 280            float tintG = Settings.BlurTintColor.G;
 281            float tintB = Settings.BlurTintColor.B;
 282
 283            // Sample background if available, otherwise assume mid-gray
 284            float bgR = 128f, bgG = 128f, bgB = 128f;
 285            if (bgCapture != null)
 286            {
 287                try
 288                {
 289                    long totalR = 0, totalG = 0, totalB = 0; int samples = 0;
 290                    for (int y = 0; y < bgCapture.Height; y += 20)
 291                        for (int x = 0; x < bgCapture.Width; x += 20)
 292                        {
 293                            Color px = bgCapture.GetPixel(x, y);
 294                            totalR += px.R; totalG += px.G; totalB += px.B; samples++;
 295                        }
 296                    if (samples > 0)
 297                    {
 298                        bgR = totalR / (float)samples;
 299                        bgG = totalG / (float)samples;
 300                        bgB = totalB / (float)samples;
 301                    }
 302                }
 303                catch { }
 304            }
 305
 306            // Effective perceived color = tint blended over background
 307            float er = ta * tintR + (1 - ta) * bgR;
 308            float eg = ta * tintG + (1 - ta) * bgG;
 309            float eb = ta * tintB + (1 - ta) * bgB;
 310            float brightness = (er * 0.299f + eg * 0.587f + eb * 0.114f) / 255f;
 311
 312            if (brightness > 0.45f)
 313            {
 314                // Light background → dark text and glow
 315                adaptiveDim = Color.FromArgb(50, 50, 60);
 316                adaptiveGlow = Color.FromArgb(10, 12, 20);
 317                AdaptiveTextColor = Color.FromArgb(10, 12, 20);
 318                AdaptiveDimColor = Color.FromArgb(50, 50, 60);
 319            }
 320            else
 321            {
 322                // Dark background → light text and glow (default)
 323                adaptiveDim = DimText;
 324                adaptiveGlow = GlassEdge;
 325                AdaptiveTextColor = GlassEdge;
 326                AdaptiveDimColor = DimText;
 327            }
 328        }
 329
 330        // Adaptive colors accessible by child controls
 331        internal static Color AdaptiveTextColor = GlassEdge;
 332        internal static Color AdaptiveDimColor = DimText;
 333
 334        internal static float ComputeGlow(Control ctrl)
 335        {
 336            return GlowHelper.ComputeGlow(ctrl);
 337        }
 338
 339        private void ShimmerTimer_Tick(object sender, EventArgs e)
 340        {
 341            if (!Visible) return;
 342            Point screenPt = Cursor.Position;
 343            // Skip if cursor hasn't moved — eliminates flickering
 344            if (screenPt == lastShimmerCursorPos) return;
 345            lastShimmerCursorPos = screenPt;
 346
 347            // Update label text colors based on cursor proximity
 348            foreach (var lbl in shimmerLabels)
 349            {
 350                if (lbl.IsDisposed || !lbl.Visible || lbl.Parent == null) continue;
 351                try
 352                {
 353                    Point lblScreen = lbl.Parent.PointToScreen(new Point(lbl.Left + lbl.Width / 2, lbl.Top + lbl.Height / 2));
 354                    float dx = screenPt.X - lblScreen.X;
 355                    float dy = screenPt.Y - lblScreen.Y;
 356                    float dist = (float)Math.Sqrt(dx * dx + dy * dy);
 357
 358                    float glow = 0f;
 359                    if (dist < ShimmerFullRadius) glow = 1f;
 360                    else if (dist < ShimmerRadius)
 361                    {
 362                        float t = (dist - ShimmerFullRadius) / (ShimmerRadius - ShimmerFullRadius);
 363                        glow = 1f - t * t;
 364                    }
 365
 366                    // Adaptive base and glow target
 367                    int cr = adaptiveDim.R + (int)((adaptiveGlow.R - adaptiveDim.R) * glow);
 368                    int cg = adaptiveDim.G + (int)((adaptiveGlow.G - adaptiveDim.G) * glow);
 369                    int cb = adaptiveDim.B + (int)((adaptiveGlow.B - adaptiveDim.B) * glow);
 370                    Color newColor = Color.FromArgb(cr, cg, cb);
 371
 372                    if (lbl.ForeColor.ToArgb() != newColor.ToArgb())
 373                        lbl.ForeColor = newColor;
 374                }
 375                catch { }
 376            }
 377
 378            // Invalidate all glow-aware controls (borders, edges)
 379            foreach (var ctrl in glowControls)
 380            {
 381                if (!ctrl.IsDisposed && ctrl.Visible) ctrl.Invalidate();
 382            }
 383
 384            // Invalidate panels with custom painting
 385            if (tabPanel != null) tabPanel.Invalidate();
 386            if (titleBarRef != null) titleBarRef.Invalidate();
 387            if (buttonPanelRef != null) buttonPanelRef.Invalidate();
 388            Invalidate(); // dialog outer border
 389        }
 390
 391        protected override void OnPaintBackground(PaintEventArgs e)
 392        {
 393            // Let DWM blur show through — paint mostly transparent
 394            e.Graphics.Clear(Color.FromArgb(0, 0, 0, 0));
 395        }
 396
 397        protected override void OnPaint(PaintEventArgs e)
 398        {
 399            base.OnPaint(e);
 400            // Glass outer border with cursor glow
 401            Point sp = Cursor.Position;
 402            Point cp;
 403            try { cp = PointToClient(sp); } catch { cp = new Point(-999, -999); }
 404            // Compute glow based on distance to nearest edge
 405            float edgeDist = Math.Min(Math.Min(cp.X, Width - cp.X), Math.Min(cp.Y, Height - cp.Y));
 406            float edgeGlow = 0f;
 407            if (edgeDist < 0) edgeDist = 0;
 408            if (edgeDist < 80) edgeGlow = 1f - edgeDist / 80f;
 409            int borderA = 40 + (int)(60 * edgeGlow);
 410            using (var pen = new Pen(Color.FromArgb(borderA, AdaptiveTextColor), 1.0f))
 411                e.Graphics.DrawRectangle(pen, 0, 0, Width - 1, Height - 1);
 412        }
 413
 414        private void TitleBar_Paint(object sender, PaintEventArgs e)
 415        {
 416            var p = (Panel)sender;
 417            var g = e.Graphics;
 418            // Glow on title bar bottom edge
 419            Point sp = Cursor.Position;
 420            Point lp;
 421            try { lp = p.PointToClient(sp); } catch { lp = new Point(-999, -999); }
 422            float dist = Math.Abs(lp.Y - p.Height);
 423            float glow = dist < 60 ? 1f - dist / 60f : 0f;
 424            int edgeA = 40 + (int)(60 * glow);
 425            using (var pen = new Pen(Color.FromArgb(edgeA, AdaptiveTextColor), 1.0f))
 426                g.DrawLine(pen, 0, p.Height - 1, p.Width, p.Height - 1);
 427
 428            // Title text with shimmer
 429            float textGlow = 0f;
 430            float textDist = (float)Math.Sqrt((lp.X - 50) * (lp.X - 50) + (lp.Y - 18) * (lp.Y - 18));
 431            if (textDist < ShimmerFullRadius) textGlow = 1f;
 432            else if (textDist < ShimmerRadius) { float t = (textDist - ShimmerFullRadius) / (ShimmerRadius - ShimmerFullRadius); textGlow = 1f - t * t; }
 433            int tr = adaptiveDim.R + (int)((adaptiveGlow.R - adaptiveDim.R) * textGlow);
 434            int tg = adaptiveDim.G + (int)((adaptiveGlow.G - adaptiveDim.G) * textGlow);
 435            int tb = adaptiveDim.B + (int)((adaptiveGlow.B - adaptiveDim.B) * textGlow);
 436            using (var brush = new SolidBrush(Color.FromArgb(tr, tg, tb)))
 437            using (var font = new Font("Segoe UI", 11f, FontStyle.Regular, GraphicsUnit.Pixel))
 438            {
 439                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
 440                g.DrawString("Settings", font, brush, 14, 11);
 441            }
 442        }
 443
 444        private void TabPanel_Paint(object sender, PaintEventArgs e)
 445        {
 446            var g = e.Graphics;
 447            int w = tabPanel.Width;
 448            int h = tabPanel.Height;
 449
 450            // Get cursor position relative to tab panel for shimmer
 451            Point screenPt = Cursor.Position;
 452            Point localPt;
 453            try { localPt = tabPanel.PointToClient(screenPt); }
 454            catch { localPt = new Point(-999, -999); }
 455
 456            // Glass right edge (separator) with glow
 457            float sepDist = Math.Abs(localPt.X - w);
 458            float sepGlow = sepDist < 60 ? 1f - sepDist / 60f : 0f;
 459            int sepA = 35 + (int)(50 * sepGlow);
 460            using (var pen = new Pen(Color.FromArgb(sepA, AdaptiveTextColor), 1.0f))
 461                g.DrawLine(pen, w - 1, 0, w - 1, h);
 462
 463            int tabHeight = 36;
 464            int y = 16;
 465
 466            for (int i = 0; i < tabNames.Length; i++)
 467            {
 468                bool sel = (i == selectedTab);
 469
 470                if (sel)
 471                {
 472                    // Selected tab — subtle glass fill + left accent edge
 473                    using (var brush = new SolidBrush(Color.FromArgb(20, AdaptiveTextColor)))
 474                        g.FillRectangle(brush, 0, y, w - 1, tabHeight);
 475                    using (var pen = new Pen(Color.FromArgb(160, AdaptiveTextColor), 2f))
 476                        g.DrawLine(pen, 1, y + 4, 1, y + tabHeight - 4);
 477                }
 478
 479                // Compute shimmer glow for this tab label
 480                float tabCenterX = w / 2f;
 481                float tabCenterY = y + tabHeight / 2f;
 482                float dx = localPt.X - tabCenterX;
 483                float dy = localPt.Y - tabCenterY;
 484                float dist = (float)Math.Sqrt(dx * dx + dy * dy);
 485                float glow = 0f;
 486                if (dist < ShimmerFullRadius) glow = 1f;
 487                else if (dist < ShimmerRadius)
 488                {
 489                    float t = (dist - ShimmerFullRadius) / (ShimmerRadius - ShimmerFullRadius);
 490                    glow = 1f - t * t;
 491                }
 492
 493                Color baseC = sel ? adaptiveGlow : adaptiveDim;
 494                int cr = baseC.R + (int)((adaptiveGlow.R - baseC.R) * glow);
 495                int cg = baseC.G + (int)((adaptiveGlow.G - baseC.G) * glow);
 496                int cb = baseC.B + (int)((adaptiveGlow.B - baseC.B) * glow);
 497                Color tabColor = Color.FromArgb(cr, cg, cb);
 498
 499                using (var brush = new SolidBrush(tabColor))
 500                using (var font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel))
 501                {
 502                    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
 503                    var sf = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center };
 504                    g.DrawString(tabNames[i], font, brush, new Rectangle(16, y, w - 16, tabHeight), sf);
 505                }
 506
 507                y += tabHeight;
 508            }
 509        }
 510
 511        private void ButtonPanel_Paint(object sender, PaintEventArgs e)
 512        {
 513            var p = (Panel)sender;
 514            Point lp;
 515            try { lp = p.PointToClient(Cursor.Position); } catch { lp = new Point(-999, -999); }
 516            float dist = Math.Abs(lp.Y);
 517            float glow = dist < 60 ? 1f - dist / 60f : 0f;
 518            int edgeA = 40 + (int)(60 * glow);
 519            using (var pen = new Pen(Color.FromArgb(edgeA, AdaptiveTextColor), 1.0f))
 520                e.Graphics.DrawLine(pen, 0, 0, p.Width, 0);
 521        }
 522
 523        private void TabPanel_MouseClick(object sender, MouseEventArgs e)
 524        {
 525            int tabHeight = 36;
 526            int y = 16; // must match TabPanel_Paint's starting offset (was 20 → 4px hit-test misalignment)
 527
 528            for (int i = 0; i < tabNames.Length; i++)
 529            {
 530                if (e.Y >= y && e.Y < y + tabHeight)
 531                {
 532                    if (selectedTab != i)
 533                    {
 534                        tabPages[selectedTab].Visible = false;
 535                        selectedTab = i;
 536                        tabPages[selectedTab].Visible = true;
 537                        tabPanel.Invalidate();
 538                    }
 539                    break;
 540                }
 541                y += tabHeight;
 542            }
 543        }
 544
 545        private Panel CreateGeneralPage()
 546        {
 547            var page = new GlassScrollPanel();
 548            page.Dock = DockStyle.Fill;
 549            var inner = page.Content;
 550
 551            int y = 15;
 552            int labelX = 15;
 553            int controlX = 170;
 554
 555            AddLabel(inner, "Highlight Alpha:", labelX, y);
 556            nudHighlightAlpha = AddNumeric(inner, controlX, y, 0, 255, Settings.HighlightAlpha);
 557            y += 32;
 558
 559            AddLabel(inner, "Highlight Color:", labelX, y);
 560            btnHighlightColor = AddColorButton(inner, controlX, y, Settings.HighlightColor);
 561            y += 32;
 562
 563            AddLabel(inner, "Show Border:", labelX, y);
 564            chkShowBorder = AddCheckBox(inner, controlX, y, Settings.ShowHighlightBorder);
 565            y += 32;
 566
 567            AddLabel(inner, "Dim Around Selection:", labelX, y);
 568            chkDimAround = AddCheckBox(inner, controlX, y, Settings.DimAroundSelection);
 569            y += 32;
 570
 571            AddLabel(inner, "Border Color:", labelX, y);
 572            btnHighlightBorderColor = AddColorButton(inner, controlX, y, Settings.HighlightBorderColor);
 573            y += 32;
 574
 575            AddLabel(inner, "Border Width:", labelX, y);
 576            nudBorderWidth = AddNumeric(inner, controlX, y, 1, 10, (int)Settings.HighlightBorderWidth);
 577            y += 40;
 578
 579            AddLabel(inner, "Marker Size:", labelX, y);
 580            nudMarkerSize = AddNumeric(inner, controlX, y, 16, 64, Settings.MarkerSize);
 581            y += 32;
 582
 583            AddLabel(inner, "Marker Color:", labelX, y);
 584            btnMarkerColor = AddColorButton(inner, controlX, y, Settings.MarkerColor);
 585            y += 32;
 586
 587            AddLabel(inner, "Arrow Color:", labelX, y);
 588            btnArrowColor = AddColorButton(inner, controlX, y, Settings.ArrowColor);
 589            y += 40;
 590
 591            AddLabel(inner, "Auto-fit Window:", labelX, y);
 592            chkAutoFit = AddCheckBox(inner, controlX, y, Settings.AutoFitToWindow);
 593            y += 32;
 594
 595            AddLabel(inner, "Default Width:", labelX, y);
 596            nudDefaultWidth = AddNumeric(inner, controlX, y, 400, 3840, Settings.DefaultWindowWidth);
 597            y += 32;
 598
 599            AddLabel(inner, "Default Height:", labelX, y);
 600            nudDefaultHeight = AddNumeric(inner, controlX, y, 300, 2160, Settings.DefaultWindowHeight);
 601            y += 40;
 602
 603            // Window Appearance section — glass divider
 604            AddSectionHeader(inner, "WINDOW APPEARANCE", labelX, y);
 605            y += 28;
 606
 607            AddLabel(inner, "Tint Opacity:", labelX, y);
 608            nudBlurTintAlpha = AddNumeric(inner, controlX, y, 0, 255, Settings.BlurTintAlpha);
 609            nudBlurTintAlpha.ValueChanged += delegate { ApplyBlurPreview(); };
 610            y += 32;
 611
 612            AddLabel(inner, "Blur Tint Color:", labelX, y);
 613            btnBlurTintColor = AddColorButton(inner, controlX, y, Settings.BlurTintColor);
 614            btnBlurTintColor.BackColorChanged += delegate { ApplyBlurPreview(); };
 615            y += 32;
 616
 617            y += 0; // Blur mode removed — always BlurBehind with noise grain overlay
 618
 619            AddLabel(inner, "Corner Radius:", labelX, y);
 620            nudCornerRadius = AddNumeric(inner, controlX, y, 0, 24, Settings.CornerRadius);
 621            nudCornerRadius.ValueChanged += delegate { ApplyBlurPreview(); };
 622            y += 32;
 623
 624            AddLabel(inner, "Window Border:", labelX, y);
 625            chkWindowBorder = AddCheckBox(inner, controlX, y, Settings.ShowWindowBorder);
 626            chkWindowBorder.CheckedChanged += delegate { ApplyBlurPreview(); };
 627            y += 32;
 628
 629            AddLabel(inner, "Noise Grain:", labelX, y);
 630            nudNoiseIntensity = AddNumeric(inner, controlX, y, 0, 30, Settings.NoiseIntensity);
 631            nudNoiseIntensity.ValueChanged += delegate { ApplyBlurPreview(); };
 632
 633            page.SetupScroll();
 634            page.HookChildWheelEvents(inner);
 635            return page;
 636        }
 637
 638        private Panel CreateEffectsPage()
 639        {
 640            var page = new GlassScrollPanel();
 641            page.Dock = DockStyle.Fill;
 642            var inner = page.Content;
 643
 644            int y = 15;
 645            int labelX = 15;
 646            int controlX = 170;
 647
 648            AddLabel(inner, "Blur Radius:", labelX, y);
 649            nudBlurRadius = AddFloatNumeric(inner, controlX, y, 0.1f, 10f, 0.1f, Settings.BlurRadius);
 650            y += 32;
 651
 652            AddLabel(inner, "Motion Blur:", labelX, y);
 653            nudMotionBlurDistance = AddNumeric(inner, controlX, y, 1, 50, Settings.MotionBlurDistance);
 654            y += 32;
 655
 656            AddLabel(inner, "Dim Alpha:", labelX, y);
 657            nudDimAlpha = AddNumeric(inner, controlX, y, 0, 255, Settings.DimAlpha);
 658            y += 32;
 659
 660            AddLabel(inner, "Feather Width:", labelX, y);
 661            nudFeatherWidth = AddNumeric(inner, controlX, y, 0, 50, Settings.FeatherWidth);
 662            y += 40;
 663
 664            AddLabel(inner, "Fade Blur:", labelX, y);
 665            chkEnableFadeBlur = AddCheckBox(inner, controlX, y, Settings.EnableFadeBlur);
 666            y += 32;
 667
 668            AddLabel(inner, "Fade Width:", labelX, y);
 669            nudFadeBlurWidth = AddNumeric(inner, controlX, y, 5, 100, Settings.FadeBlurWidth);
 670            y += 50;
 671
 672            AddSectionHeader(inner, "TEXT BLOCK", labelX, y);
 673            y += 28;
 674
 675            AddLabel(inner, "Font:", labelX, y);
 676            cmbTextFont = new DarkComboBox();
 677            cmbTextFont.Location = new Point(controlX, y);
 678            cmbTextFont.Size = new Size(160, 26);
 679            var systemFonts = GetSystemFonts();
 680            foreach (string font in systemFonts)
 681                cmbTextFont.Items.Add(font);
 682            int fontIdx = systemFonts.IndexOf(Settings.TextBlockFont);
 683            if (fontIdx >= 0)
 684                cmbTextFont.SelectedIndex = fontIdx;
 685            else if (cmbTextFont.Items.Count > 0)
 686                cmbTextFont.SelectedIndex = 0;
 687            inner.Controls.Add(cmbTextFont);
 688            glowControls.Add(cmbTextFont);
 689            y += 32;
 690
 691            AddLabel(inner, "Font Size:", labelX, y);
 692            nudTextFontSize = AddNumeric(inner, controlX, y, 8, 300, (int)Settings.TextBlockFontSize);
 693            y += 32;
 694
 695            AddLabel(inner, "Text Color:", labelX, y);
 696            btnTextColor = AddColorButton(inner, controlX, y, Settings.TextBlockColor);
 697            y += 32;
 698
 699            AddLabel(inner, "Shadow Color:", labelX, y);
 700            btnTextShadowColor = AddColorButton(inner, controlX, y, Settings.TextBlockShadowColor);
 701            y += 32;
 702
 703            AddLabel(inner, "Shadow Offset:", labelX, y);
 704            nudShadowOffset = AddNumeric(inner, controlX, y, 0, 50, Settings.TextBlockShadowOffset);
 705
 706            page.SetupScroll();
 707            page.HookChildWheelEvents(inner);
 708            return page;
 709        }
 710
 711        private Panel CreateVideoPage()
 712        {
 713            var page = new GlassScrollPanel();
 714            page.Dock = DockStyle.Fill;
 715            var inner = page.Content;
 716
 717            int y = 15;
 718            int labelX = 15;
 719            int controlX = 170;
 720
 721            AddSectionHeader(inner, "RECORDING", labelX, y);
 722            y += 30;
 723
 724            AddLabel(inner, "FPS:", labelX, y);
 725            nudVideoFps = AddNumeric(inner, controlX, y, 1, 120, Settings.VideoFps);
 726            y += 32;
 727
 728            AddLabel(inner, "JPEG Quality:", labelX, y);
 729            nudVideoJpegQuality = AddNumeric(inner, controlX, y, 10, 100, Settings.VideoJpegQuality);
 730            y += 38;
 731
 732            AddSectionHeader(inner, "AUDIO", labelX, y);
 733            y += 30;
 734
 735            AddLabel(inner, "System Audio:", labelX, y);
 736            chkRecordSystemAudio = AddCheckBox(inner, controlX, y, Settings.RecordSystemAudio);
 737            y += 32;
 738
 739            AddLabel(inner, "Microphone:", labelX, y);
 740            chkRecordMicrophone = AddCheckBox(inner, controlX, y, Settings.RecordMicrophone);
 741            y += 38;
 742
 743            // Info label
 744            var infoLabel = new Label();
 745            infoLabel.Text = "Format: MJPEG AVI with PCM audio\nSystem Audio: captures desktop sound\nMicrophone: captures mic input\nBoth can be enabled simultaneously";
 746            infoLabel.ForeColor = Color.FromArgb(140, AdaptiveTextColor);
 747            infoLabel.BackColor = Color.Transparent;
 748            infoLabel.Font = new Font("Segoe UI", 8.5f);
 749            infoLabel.Location = new Point(labelX, y + 5);
 750            infoLabel.Size = new Size(280, 70);
 751            inner.Controls.Add(infoLabel);
 752            shimmerLabels.Add(infoLabel);
 753
 754            page.SetupScroll();
 755            page.HookChildWheelEvents(inner);
 756            return page;
 757        }
 758
 759        private Panel CreateKeysPage()
 760        {
 761            Panel page = new Panel();
 762            page.Dock = DockStyle.Fill;
 763            page.BackColor = Color.Transparent;
 764
 765            int y = 15;
 766
 767            // Activation key setting
 768            Label lblActivation = new Label();
 769            lblActivation.Text = "Activation (+ Win):";
 770            lblActivation.Location = new Point(15, y + 4);
 771            lblActivation.AutoSize = true;
 772            lblActivation.ForeColor = AdaptiveDimColor;
 773            lblActivation.BackColor = Color.Transparent;
 774            lblActivation.Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel);
 775            page.Controls.Add(lblActivation);
 776            shimmerLabels.Add(lblActivation);
 777
 778            cmbActivationKey = new DarkComboBox();
 779            cmbActivationKey.Location = new Point(170, y);
 780            cmbActivationKey.Size = new Size(200, 26);
 781            cmbActivationKey.AddItem("Alt");
 782            cmbActivationKey.AddItem("Ctrl");
 783            cmbActivationKey.AddItem("Shift");
 784            cmbActivationKey.AddItem("F1");
 785            cmbActivationKey.AddItem("F2");
 786            cmbActivationKey.AddItem("F3");
 787            cmbActivationKey.AddItem("F4");
 788            cmbActivationKey.AddItem("F5");
 789            cmbActivationKey.AddItem("F6");
 790            cmbActivationKey.AddItem("F7");
 791            cmbActivationKey.AddItem("F8");
 792            cmbActivationKey.AddItem("F9");
 793            cmbActivationKey.AddItem("F10");
 794            cmbActivationKey.AddItem("F11");
 795            cmbActivationKey.AddItem("F12");
 796            // Set current value
 797            int activationIdx = cmbActivationKey.FindItem(Settings.ActivationKeyName);
 798            if (activationIdx >= 0) cmbActivationKey.SelectedIndex = activationIdx;
 799            page.Controls.Add(cmbActivationKey);
 800            glowControls.Add(cmbActivationKey);
 801
 802            y += 45;
 803
 804            keysListPanel = new Panel();
 805            keysListPanel.Location = new Point(10, y);
 806            keysListPanel.Size = new Size(390, 330);
 807            keysListPanel.BackColor = Color.FromArgb(10, AdaptiveTextColor);
 808
 809            int listY = 10;
 810            AddKeyRow(keysListPanel, "Capture Screen", KeyBindings.CaptureKey, 0, ref listY);
 811            AddKeyRow(keysListPanel, "Copy and Close", KeyBindings.CopyAndClose, 1, ref listY);
 812            AddKeyRow(keysListPanel, "Undo (Ctrl+)", KeyBindings.Undo, 2, ref listY);
 813            AddKeyRow(keysListPanel, "Cancel", KeyBindings.Cancel, 3, ref listY);
 814
 815            Label lblInfo = new Label();
 816            lblInfo.Text = "Click on key to change binding";
 817            lblInfo.Location = new Point(10, y + 340);
 818            lblInfo.AutoSize = true;
 819            lblInfo.ForeColor = AdaptiveDimColor;
 820            lblInfo.BackColor = Color.Transparent;
 821            lblInfo.Font = new Font("Segoe UI", 10f, GraphicsUnit.Pixel);
 822            page.Controls.Add(lblInfo);
 823            shimmerLabels.Add(lblInfo);
 824
 825            page.Controls.Add(keysListPanel);
 826            return page;
 827        }
 828
 829        private Panel CreateTextPage()
 830        {
 831            Panel page = new Panel();
 832            page.Dock = DockStyle.Fill;
 833            page.BackColor = Color.Transparent;
 834
 835            int y = 15;
 836
 837            // Section: Auto Language Switch
 838            Label lblLangSection = new Label();
 839            lblLangSection.Text = "LANGUAGE";
 840            lblLangSection.Location = new Point(15, y);
 841            lblLangSection.AutoSize = true;
 842            lblLangSection.ForeColor = AccentColor;
 843            lblLangSection.BackColor = Color.Transparent;
 844            lblLangSection.Font = new Font("Segoe UI Semibold", 10f, GraphicsUnit.Pixel);
 845            page.Controls.Add(lblLangSection);
 846            shimmerLabels.Add(lblLangSection);
 847            y += 22;
 848
 849            chkAutoLangSwitch = new CheckBox();
 850            chkAutoLangSwitch.Text = "Auto EN ↔ RU switch";
 851            chkAutoLangSwitch.Location = new Point(15, y);
 852            chkAutoLangSwitch.Size = new Size(360, 24);
 853            chkAutoLangSwitch.Checked = Settings.AutoLangSwitch;
 854            chkAutoLangSwitch.ForeColor = AdaptiveDimColor;
 855            chkAutoLangSwitch.BackColor = Color.Transparent;
 856            chkAutoLangSwitch.Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel);
 857            chkAutoLangSwitch.FlatStyle = FlatStyle.Flat;
 858            page.Controls.Add(chkAutoLangSwitch);
 859            glowControls.Add(chkAutoLangSwitch);
 860            y += 30;
 861
 862            Label lblLangDesc = new Label();
 863            lblLangDesc.Text = "Detects wrong keyboard layout and auto-corrects typed word";
 864            lblLangDesc.Location = new Point(34, y);
 865            lblLangDesc.AutoSize = true;
 866            lblLangDesc.ForeColor = Color.FromArgb(80, AdaptiveTextColor);
 867            lblLangDesc.BackColor = Color.Transparent;
 868            lblLangDesc.Font = new Font("Segoe UI", 10f, GraphicsUnit.Pixel);
 869            page.Controls.Add(lblLangDesc);
 870            shimmerLabels.Add(lblLangDesc);
 871            y += 35;
 872
 873            // Section: T9 Autocorrect
 874            Label lblT9Section = new Label();
 875            lblT9Section.Text = "AUTOCORRECT";
 876            lblT9Section.Location = new Point(15, y);
 877            lblT9Section.AutoSize = true;
 878            lblT9Section.ForeColor = AccentColor;
 879            lblT9Section.BackColor = Color.Transparent;
 880            lblT9Section.Font = new Font("Segoe UI Semibold", 10f, GraphicsUnit.Pixel);
 881            page.Controls.Add(lblT9Section);
 882            shimmerLabels.Add(lblT9Section);
 883            y += 22;
 884
 885            chkAutoT9 = new CheckBox();
 886            chkAutoT9.Text = "Enable T9 autocorrection";
 887            chkAutoT9.Location = new Point(15, y);
 888            chkAutoT9.Size = new Size(360, 24);
 889            chkAutoT9.Checked = Settings.AutoT9;
 890            chkAutoT9.ForeColor = AdaptiveDimColor;
 891            chkAutoT9.BackColor = Color.Transparent;
 892            chkAutoT9.Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel);
 893            chkAutoT9.FlatStyle = FlatStyle.Flat;
 894            page.Controls.Add(chkAutoT9);
 895            glowControls.Add(chkAutoT9);
 896            y += 35;
 897
 898            Label lblSensitivity = new Label();
 899            lblSensitivity.Text = "Sensitivity:";
 900            lblSensitivity.Location = new Point(15, y + 4);
 901            lblSensitivity.AutoSize = true;
 902            lblSensitivity.ForeColor = AdaptiveDimColor;
 903            lblSensitivity.BackColor = Color.Transparent;
 904            lblSensitivity.Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel);
 905            page.Controls.Add(lblSensitivity);
 906            shimmerLabels.Add(lblSensitivity);
 907
 908            nudT9Sensitivity = new DarkNumeric();
 909            nudT9Sensitivity.Minimum = 1;
 910            nudT9Sensitivity.Maximum = 5;
 911            nudT9Sensitivity.Value = Settings.T9Sensitivity;
 912            nudT9Sensitivity.Location = new Point(170, y);
 913            nudT9Sensitivity.Size = new Size(80, 28);
 914            page.Controls.Add(nudT9Sensitivity);
 915            glowControls.Add(nudT9Sensitivity);
 916            y += 40;
 917
 918            chkT9ShowTooltip = new CheckBox();
 919            chkT9ShowTooltip.Text = "Show correction tooltip";
 920            chkT9ShowTooltip.Location = new Point(15, y);
 921            chkT9ShowTooltip.Size = new Size(360, 24);
 922            chkT9ShowTooltip.Checked = Settings.T9ShowTooltip;
 923            chkT9ShowTooltip.ForeColor = AdaptiveDimColor;
 924            chkT9ShowTooltip.BackColor = Color.Transparent;
 925            chkT9ShowTooltip.Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel);
 926            chkT9ShowTooltip.FlatStyle = FlatStyle.Flat;
 927            page.Controls.Add(chkT9ShowTooltip);
 928            glowControls.Add(chkT9ShowTooltip);
 929
 930            return page;
 931        }
 932
 933        private void AddKeyRow(Panel parent, string actionName, Keys key, int index, ref int y)
 934        {
 935            Label lblAction = new Label();
 936            lblAction.Text = actionName;
 937            lblAction.Location = new Point(15, y + 8);
 938            lblAction.Size = new Size(180, 24);
 939            lblAction.ForeColor = AdaptiveDimColor;
 940            lblAction.BackColor = Color.Transparent;
 941            lblAction.Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel);
 942            parent.Controls.Add(lblAction);
 943            shimmerLabels.Add(lblAction);
 944
 945            Button btnKey = CreateButton(key.ToString(), 200, y, 170, 32);
 946            btnKey.Tag = index;
 947            btnKey.Click += BtnKey_Click;
 948            parent.Controls.Add(btnKey);
 949
 950            y += 45;
 951        }
 952
 953        private void BtnKey_Click(object sender, EventArgs e)
 954        {
 955            Button btn = (Button)sender;
 956            int index = (int)btn.Tag;
 957
 958            string[] actions = { "Capture Screen", "Copy and Close", "Undo", "Cancel" };
 959
 960            using (var dlg = new KeyCaptureDialog(actions[index]))
 961            {
 962                if (dlg.ShowDialog() == DialogResult.OK)
 963                {
 964                    btn.Text = dlg.CapturedKey.ToString();
 965                }
 966            }
 967        }
 968
 969        private Button CreateButton(string text, int x, int y, int w, int h)
 970        {
 971            var btn = new Button();
 972            btn.Text = text;
 973            btn.Location = new Point(x, y);
 974            btn.Size = new Size(w, h);
 975            btn.FlatStyle = FlatStyle.Flat;
 976            btn.FlatAppearance.BorderSize = 0;
 977            btn.FlatAppearance.MouseOverBackColor = Color.FromArgb(40, AdaptiveTextColor);
 978            btn.FlatAppearance.MouseDownBackColor = Color.FromArgb(60, AdaptiveTextColor);
 979            btn.BackColor = Color.FromArgb(15, AdaptiveTextColor);
 980            btn.ForeColor = AdaptiveTextColor;
 981            btn.Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel);
 982            btn.Cursor = Cursors.Hand;
 983            // Custom paint for glow border + adaptive text color
 984            btn.Paint += (s, pe) =>
 985            {
 986                var b = (Button)s;
 987                b.ForeColor = AdaptiveTextColor;
 988                float glow = ComputeGlow(b);
 989                int borderA = 40 + (int)(60 * glow);
 990                using (var pen = new Pen(Color.FromArgb(borderA, AdaptiveTextColor), 1f))
 991                    pe.Graphics.DrawRectangle(pen, 0, 0, b.Width - 1, b.Height - 1);
 992            };
 993            glowControls.Add(btn);
 994            return btn;
 995        }
 996
 997        private Label AddLabel(Control parent, string text, int x, int y)
 998        {
 999            Label lbl = new Label();
1000            lbl.Text = text;
1001            lbl.Location = new Point(x, y + 4);
1002            lbl.AutoSize = true;
1003            lbl.ForeColor = AdaptiveDimColor;
1004            lbl.BackColor = Color.Transparent;
1005            lbl.Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel);
1006            parent.Controls.Add(lbl);
1007            shimmerLabels.Add(lbl);
1008            return lbl;
1009        }
1010
1011        private void AddSectionHeader(Control parent, string text, int x, int y)
1012        {
1013            var lbl = new Label();
1014            lbl.Text = text;
1015            lbl.Location = new Point(x, y + 4);
1016            lbl.AutoSize = false;
1017            lbl.Size = new Size(parent.Width > 0 ? parent.Width - x * 2 : 380, 20);
1018            lbl.ForeColor = Color.FromArgb(140, AdaptiveTextColor);
1019            lbl.BackColor = Color.Transparent;
1020            lbl.Font = new Font("Segoe UI", 10f, GraphicsUnit.Pixel);
1021            lbl.Paint += (s, ev) =>
1022            {
1023                var g = ev.Graphics;
1024                float glow = ComputeGlow(lbl);
1025                var sz = g.MeasureString(text, lbl.Font);
1026                int lineX = (int)sz.Width + 6;
1027                int lineA = 30 + (int)(40 * glow);
1028                using (var pen = new Pen(Color.FromArgb(lineA, AdaptiveTextColor), 1.0f))
1029                    g.DrawLine(pen, lineX, lbl.Height / 2, lbl.Width - 4, lbl.Height / 2);
1030            };
1031            parent.Controls.Add(lbl);
1032            shimmerLabels.Add(lbl);
1033            glowControls.Add(lbl);
1034        }
1035
1036        private DarkNumeric AddNumeric(Control parent, int x, int y, int min, int max, int value)
1037        {
1038            DarkNumeric nud = new DarkNumeric();
1039            nud.Location = new Point(x, y);
1040            nud.Size = new Size(80, 26);
1041            nud.Minimum = min;
1042            nud.Maximum = max;
1043            nud.Value = Math.Max(min, Math.Min(max, value));
1044            parent.Controls.Add(nud);
1045            glowControls.Add(nud);
1046            return nud;
1047        }
1048
1049        private DarkFloatNumeric AddFloatNumeric(Control parent, int x, int y, float min, float max, float step, float value)
1050        {
1051            DarkFloatNumeric nud = new DarkFloatNumeric();
1052            nud.Location = new Point(x, y);
1053            nud.Size = new Size(80, 26);
1054            nud.Minimum = min;
1055            nud.Maximum = max;
1056            nud.Step = step;
1057            nud.Value = Math.Max(min, Math.Min(max, value));
1058            parent.Controls.Add(nud);
1059            glowControls.Add(nud);
1060            return nud;
1061        }
1062
1063        private CheckBox AddCheckBox(Control parent, int x, int y, bool isChecked)
1064        {
1065            CheckBox chk = new CheckBox();
1066            chk.Location = new Point(x, y + 2);
1067            chk.Checked = isChecked;
1068            chk.AutoSize = false;
1069            chk.Size = new Size(22, 22);
1070            chk.ForeColor = AdaptiveTextColor;
1071            chk.BackColor = Color.Transparent;
1072            chk.FlatStyle = FlatStyle.Flat;
1073            chk.FlatAppearance.BorderSize = 0;
1074            chk.Font = new Font("Segoe UI", 11f, GraphicsUnit.Pixel);
1075            chk.Appearance = Appearance.Button;
1076            // Custom paint: dark-themed toggle
1077            chk.Paint += (s, pe) =>
1078            {
1079                var cb = (CheckBox)s;
1080                var g = pe.Graphics;
1081                g.SmoothingMode = SmoothingMode.AntiAlias;
1082                float glow = ComputeGlow(cb);
1083
1084                // Glass box
1085                int fillA = cb.Checked ? 30 + (int)(20 * glow) : 8 + (int)(12 * glow);
1086                Color ge = Color.FromArgb(225, 232, 245);
1087                using (var brush = new SolidBrush(Color.FromArgb(fillA, ge)))
1088                    g.FillRectangle(brush, 2, 2, cb.Width - 4, cb.Height - 4);
1089                int borderA = 40 + (int)(60 * glow);
1090                using (var pen = new Pen(Color.FromArgb(borderA, ge), 1f))
1091                    g.DrawRectangle(pen, 2, 2, cb.Width - 5, cb.Height - 5);
1092
1093                // Checkmark
1094                if (cb.Checked)
1095                {
1096                    int a = 180 + (int)(60 * glow);
1097                    using (var pen = new Pen(Color.FromArgb(a, AccentColor), 2f))
1098                    {
1099                        pen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
1100                        pen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
1101                        g.DrawLine(pen, 6, cb.Height / 2, 9, cb.Height / 2 + 3);
1102                        g.DrawLine(pen, 9, cb.Height / 2 + 3, cb.Width - 6, cb.Height / 2 - 4);
1103                    }
1104                }
1105            };
1106            parent.Controls.Add(chk);
1107            glowControls.Add(chk);
1108            return chk;
1109        }
1110
1111        private Button AddColorButton(Control parent, int x, int y, Color color)
1112        {
1113            Button btn = new Button();
1114            btn.Location = new Point(x, y);
1115            btn.Size = new Size(80, 26);
1116            btn.BackColor = color;
1117            btn.FlatStyle = FlatStyle.Flat;
1118            btn.FlatAppearance.BorderSize = 0;
1119            btn.Cursor = Cursors.Hand;
1120            // Custom paint — explicitly draw color swatch so it works on DWM-blurred windows
1121            btn.Paint += (s, pe) =>
1122            {
1123                var b = (Button)s;
1124                var g = pe.Graphics;
1125                // Draw solid color fill (the actual selected color)
1126                using (var brush = new SolidBrush(b.BackColor))
1127                    g.FillRectangle(brush, 2, 2, b.Width - 4, b.Height - 4);
1128                // Glass border with glow
1129                float glow = ComputeGlow(b);
1130                int borderA = 40 + (int)(60 * glow);
1131                using (var pen = new Pen(Color.FromArgb(borderA, AdaptiveTextColor), 1f))
1132                    g.DrawRectangle(pen, 0, 0, b.Width - 1, b.Height - 1);
1133            };
1134            btn.Click += delegate
1135            {
1136                using (var dlg = new DarkColorPicker(btn.BackColor))
1137                {
1138                    if (dlg.ShowDialog() == DialogResult.OK)
1139                    {
1140                        btn.BackColor = dlg.SelectedColor;
1141                    }
1142                }
1143            };
1144            parent.Controls.Add(btn);
1145            glowControls.Add(btn);
1146            return btn;
1147        }
1148
1149        private void LoadSettings()
1150        {
1151        }
1152
1153        /// <summary>Restore original blur settings when Cancel is pressed.</summary>
1154        private void RestoreBlurSettings()
1155        {
1156            Settings.BlurTintAlpha = origBlurTintAlpha;
1157            Settings.BlurTintColor = origBlurTintColor;
1158            Settings.CornerRadius = origCornerRadius;
1159            Settings.ShowWindowBorder = origShowBorder;
1160            Settings.NoiseIntensity = origNoiseIntensity;
1161
1162            foreach (Form f in Application.OpenForms)
1163            {
1164                var editor = f as EditorForm;
1165                if (editor != null)
1166                {
1167                    Helpers.BlurHelper.Apply(editor.Handle);
1168                    editor.ApplyRoundedCorners();
1169                    editor.Invalidate(true);
1170                }
1171            }
1172        }
1173
1174        /// <summary>Live preview: apply appearance changes to the parent editor window in real-time.</summary>
1175        private void ApplyBlurPreview()
1176        {
1177            if (nudBlurTintAlpha == null || btnBlurTintColor == null) return;
1178
1179            Settings.BlurTintAlpha = nudBlurTintAlpha.Value;
1180            Settings.BlurTintColor = btnBlurTintColor.BackColor;
1181            if (nudCornerRadius != null) Settings.CornerRadius = nudCornerRadius.Value;
1182            if (chkWindowBorder != null) Settings.ShowWindowBorder = chkWindowBorder.Checked;
1183            if (nudNoiseIntensity != null) Settings.NoiseIntensity = nudNoiseIntensity.Value;
1184
1185            // Apply to ALL open editor forms
1186            foreach (Form f in Application.OpenForms)
1187            {
1188                var editor = f as EditorForm;
1189                if (editor != null)
1190                {
1191                    Helpers.BlurHelper.Apply(editor.Handle);
1192                    editor.ApplyRoundedCorners();
1193                    editor.Invalidate(true);
1194                }
1195            }
1196
1197            // Also update this dialog
1198            Helpers.BlurHelper.Apply(Handle);
1199
1200            // Recompute adaptive colors based on new tint
1201            ComputeAdaptiveColors();
1202            Invalidate(true);
1203        }
1204
1205        private void SaveSettings()
1206        {
1207            Settings.HighlightAlpha = nudHighlightAlpha.Value;
1208            Settings.HighlightColor = btnHighlightColor.BackColor;
1209            Settings.ShowHighlightBorder = chkShowBorder.Checked;
1210            Settings.DimAroundSelection = chkDimAround.Checked;
1211            Settings.HighlightBorderColor = btnHighlightBorderColor.BackColor;
1212            Settings.HighlightBorderWidth = nudBorderWidth.Value;
1213            Settings.MarkerSize = nudMarkerSize.Value;
1214            Settings.MarkerColor = btnMarkerColor.BackColor;
1215            Settings.ArrowColor = btnArrowColor.BackColor;
1216            Settings.AutoFitToWindow = chkAutoFit.Checked;
1217            Settings.DefaultWindowWidth = nudDefaultWidth.Value;
1218            Settings.DefaultWindowHeight = nudDefaultHeight.Value;
1219            Settings.BlurTintAlpha = nudBlurTintAlpha.Value;
1220            Settings.BlurTintColor = btnBlurTintColor.BackColor;
1221            Settings.BlurMode = 0;
1222            Settings.CornerRadius = nudCornerRadius.Value;
1223            Settings.ShowWindowBorder = chkWindowBorder.Checked;
1224            Settings.NoiseIntensity = nudNoiseIntensity.Value;
1225
1226            Settings.BlurRadius = nudBlurRadius.Value;
1227            Settings.MotionBlurDistance = nudMotionBlurDistance.Value;
1228            Settings.DimAlpha = nudDimAlpha.Value;
1229            Settings.FeatherWidth = nudFeatherWidth.Value;
1230            Settings.EnableFadeBlur = chkEnableFadeBlur.Checked;
1231            Settings.FadeBlurWidth = nudFadeBlurWidth.Value;
1232            Settings.TextBlockFont = cmbTextFont.SelectedItem;
1233            Settings.TextBlockFontSize = (float)nudTextFontSize.Value;
1234            Settings.TextBlockColor = btnTextColor.BackColor;
1235            Settings.TextBlockShadowColor = btnTextShadowColor.BackColor;
1236            Settings.TextBlockShadowOffset = nudShadowOffset.Value;
1237
1238            Settings.VideoFps = nudVideoFps.Value;
1239            Settings.VideoJpegQuality = nudVideoJpegQuality.Value;
1240            Settings.RecordSystemAudio = chkRecordSystemAudio.Checked;
1241            Settings.RecordMicrophone = chkRecordMicrophone.Checked;
1242
1243            // Save text processing settings
1244            Settings.AutoLangSwitch = chkAutoLangSwitch.Checked;
1245            Settings.AutoT9 = chkAutoT9.Checked;
1246            Settings.T9Sensitivity = nudT9Sensitivity.Value;
1247            Settings.T9ShowTooltip = chkT9ShowTooltip.Checked;
1248
1249            // Save activation key
1250            if (cmbActivationKey != null && cmbActivationKey.SelectedIndex >= 0)
1251            {
1252                string keyName = cmbActivationKey.SelectedItem;
1253                Settings.ActivationKeyName = keyName;
1254                Settings.ActivationKey = GetVirtualKeyCode(keyName);
1255            }
1256
1257            foreach (Control c in keysListPanel.Controls)
1258            {
1259                Button btn = c as Button;
1260                if (btn != null && btn.Tag != null)
1261                {
1262                    int index = (int)btn.Tag;
1263                    Keys key;
1264                    if (Enum.TryParse(btn.Text, out key))
1265                    {
1266                        switch (index)
1267                        {
1268                            case 0: KeyBindings.CaptureKey = key; break;
1269                            case 1: KeyBindings.CopyAndClose = key; break;
1270                            case 2: KeyBindings.Undo = key; break;
1271                            case 3: KeyBindings.Cancel = key; break;
1272                        }
1273                    }
1274                }
1275            }
1276
1277            Settings.Save();
1278            KeyBindings.Save();
1279        }
1280
1281        private void ResetToDefaults()
1282        {
1283            Settings.ResetDefaults();
1284            KeyBindings.ResetDefaults();
1285
1286            nudHighlightAlpha.Value = Settings.HighlightAlpha;
1287            btnHighlightColor.BackColor = Settings.HighlightColor;
1288            chkShowBorder.Checked = Settings.ShowHighlightBorder;
1289            chkDimAround.Checked = Settings.DimAroundSelection;
1290            btnHighlightBorderColor.BackColor = Settings.HighlightBorderColor;
1291            nudBorderWidth.Value = (int)Settings.HighlightBorderWidth;
1292            nudMarkerSize.Value = Settings.MarkerSize;
1293            btnMarkerColor.BackColor = Settings.MarkerColor;
1294            btnArrowColor.BackColor = Settings.ArrowColor;
1295            chkAutoFit.Checked = Settings.AutoFitToWindow;
1296            nudDefaultWidth.Value = Settings.DefaultWindowWidth;
1297            nudDefaultHeight.Value = Settings.DefaultWindowHeight;
1298            nudBlurTintAlpha.Value = Settings.BlurTintAlpha;
1299            btnBlurTintColor.BackColor = Settings.BlurTintColor;
1300
1301            nudCornerRadius.Value = Settings.CornerRadius;
1302            chkWindowBorder.Checked = Settings.ShowWindowBorder;
1303            nudBlurRadius.Value = Settings.BlurRadius;
1304            nudMotionBlurDistance.Value = Settings.MotionBlurDistance;
1305            nudDimAlpha.Value = Settings.DimAlpha;
1306            nudFeatherWidth.Value = Settings.FeatherWidth;
1307            chkEnableFadeBlur.Checked = Settings.EnableFadeBlur;
1308            nudFadeBlurWidth.Value = Settings.FadeBlurWidth;
1309            var fonts = GetSystemFonts();
1310            int fontIdx = fonts.IndexOf(Settings.TextBlockFont);
1311            if (fontIdx >= 0) cmbTextFont.SelectedIndex = fontIdx;
1312            nudTextFontSize.Value = (int)Settings.TextBlockFontSize;
1313            btnTextColor.BackColor = Settings.TextBlockColor;
1314            btnTextShadowColor.BackColor = Settings.TextBlockShadowColor;
1315            nudShadowOffset.Value = Settings.TextBlockShadowOffset;
1316
1317            foreach (Control c in keysListPanel.Controls)
1318            {
1319                Button btn = c as Button;
1320                if (btn != null && btn.Tag != null)
1321                {
1322                    int index = (int)btn.Tag;
1323                    switch (index)
1324                    {
1325                        case 0: btn.Text = KeyBindings.CaptureKey.ToString(); break;
1326                        case 1: btn.Text = KeyBindings.CopyAndClose.ToString(); break;
1327                        case 2: btn.Text = KeyBindings.Undo.ToString(); break;
1328                        case 3: btn.Text = KeyBindings.Cancel.ToString(); break;
1329                    }
1330                }
1331            }
1332
1333            // Reset activation key
1334            int activationIdx = cmbActivationKey.FindItem(Settings.ActivationKeyName);
1335            if (activationIdx >= 0) cmbActivationKey.SelectedIndex = activationIdx;
1336
1337            // Reset text processing
1338            chkAutoLangSwitch.Checked = Settings.AutoLangSwitch;
1339            chkAutoT9.Checked = Settings.AutoT9;
1340            nudT9Sensitivity.Value = Settings.T9Sensitivity;
1341            chkT9ShowTooltip.Checked = Settings.T9ShowTooltip;
1342        }
1343
1344        private int GetVirtualKeyCode(string keyName)
1345        {
1346            switch (keyName)
1347            {
1348                case "Alt": return 0xA4; // VK_LMENU
1349                case "Ctrl": return 0xA2; // VK_LCONTROL
1350                case "Shift": return 0xA0; // VK_LSHIFT
1351                case "F1": return 0x70;
1352                case "F2": return 0x71;
1353                case "F3": return 0x72;
1354                case "F4": return 0x73;
1355                case "F5": return 0x74;
1356                case "F6": return 0x75;
1357                case "F7": return 0x76;
1358                case "F8": return 0x77;
1359                case "F9": return 0x78;
1360                case "F10": return 0x79;
1361                case "F11": return 0x7A;
1362                case "F12": return 0x7B;
1363                default: return 0xA4; // Default to Alt
1364            }
1365        }
1366
1367        protected override void Dispose(bool disposing)
1368        {
1369            if (disposing)
1370            {
1371                if (shimmerTimer != null) { shimmerTimer.Stop(); shimmerTimer.Dispose(); shimmerTimer = null; }
1372                if (bgCapture != null) { bgCapture.Dispose(); bgCapture = null; }
1373            }
1374            base.Dispose(disposing);
1375        }
1376    }
1377}