using System.Drawing.Drawing2D; using anjianjingling.Common; namespace anjianjingling.Forms { /// 坐标取色器:置顶小窗,实时显示鼠标坐标与屏幕颜色,可复制坐标/颜色或写入日志。 public sealed class PickerForm : Form { private const int MagZoom = 7; private const int SampleSize = 15; private readonly LogBus _log; private readonly System.Windows.Forms.Timer _timer = new() { Interval = 60 }; private readonly Label _lblPos = new(); private readonly Label _lblHex = new(); private readonly Label _lblRgb = new(); private readonly Panel _mag = new(); private readonly Panel _swatch = new(); private readonly Label _title = new(); private readonly Label _btnClose = new(); private Bitmap? _sample; private Point _cursor; private Color _color = Color.Black; private Point _dragOffset; private bool _dragging; public PickerForm(LogBus log) { _log = log; Text = "坐标取色器"; FormBorderStyle = FormBorderStyle.None; ShowInTaskbar = false; TopMost = true; StartPosition = FormStartPosition.Manual; ClientSize = new Size(288, 188); BackColor = Color.FromArgb(30, 34, 42); Font = new Font("Microsoft YaHei UI", 9F); KeyPreview = true; var start = Cursor.Position; Location = new Point( Math.Max(0, Math.Min(Screen.PrimaryScreen!.WorkingArea.Right - Width - 24, start.X + 40)), Math.Max(0, Math.Min(Screen.PrimaryScreen!.WorkingArea.Bottom - Height - 24, start.Y + 40))); // 顶栏 _title.Text = " 坐标取色器"; _title.Dock = DockStyle.None; _title.SetBounds(0, 0, 240, 26); _title.TextAlign = ContentAlignment.MiddleLeft; _title.ForeColor = Color.FromArgb(220, 228, 240); _title.Font = new Font("Microsoft YaHei UI", 9F, FontStyle.Bold); _title.BackColor = Color.FromArgb(42, 48, 60); _btnClose.Text = "✕"; _btnClose.SetBounds(ClientSize.Width - 26, 0, 26, 26); _btnClose.TextAlign = ContentAlignment.MiddleCenter; _btnClose.ForeColor = Color.FromArgb(200, 210, 225); _btnClose.BackColor = Color.FromArgb(42, 48, 60); _btnClose.Cursor = Cursors.Hand; _btnClose.Click += (s, e) => Close(); _btnClose.MouseEnter += (s, e) => _btnClose.BackColor = Color.FromArgb(190, 70, 60); _btnClose.MouseLeave += (s, e) => _btnClose.BackColor = Color.FromArgb(42, 48, 60); // 放大镜 _mag.SetBounds(10, 34, SampleSize * MagZoom, SampleSize * MagZoom); _mag.BackColor = Color.FromArgb(20, 24, 30); _mag.Paint += MagPaint; // 色块 _swatch.SetBounds(124, 34, 62, 46); _swatch.Paint += (s, e) => { e.Graphics.Clear(_color); using var pen = new Pen(Color.FromArgb(90, 98, 112)); e.Graphics.DrawRectangle(pen, 0, 0, _swatch.Width - 1, _swatch.Height - 1); }; // 文字 _lblPos.SetBounds(124, 86, 160, 18); _lblHex.SetBounds(124, 106, 160, 18); _lblRgb.SetBounds(124, 126, 160, 18); foreach (var l in new[] { _lblPos, _lblHex, _lblRgb }) { l.ForeColor = Color.FromArgb(214, 222, 235); l.Font = new Font("Consolas", 9.5F); } _lblPos.Text = "坐标 -"; _lblHex.Text = "颜色 -"; _lblRgb.Text = "RGB -"; // 按钮 var bar = new FlowLayoutPanel { FlowDirection = FlowDirection.LeftToRight, WrapContents = false }; bar.SetBounds(10, 150, 268, 30); bar.Controls.Add(MkBtn("复制坐标", () => Copy(_cursor.X + ", " + _cursor.Y))); bar.Controls.Add(MkBtn("复制颜色", () => Copy($"{_color.R:X2}{_color.G:X2}{_color.B:X2}"))); bar.Controls.Add(MkBtn("写入日志", () => _log.Write($"取色:坐标 ({_cursor.X}, {_cursor.Y}) 颜色 #{_color.R:X2}{_color.G:X2}{_color.B:X2}"))); Controls.AddRange(new Control[] { _mag, _swatch, _lblPos, _lblHex, _lblRgb, bar, _title, _btnClose }); KeyDown += (s, e) => { if (e.KeyCode == Keys.Escape) Close(); }; MouseDown += DragStart; _title.MouseDown += DragStart; MouseMove += DragMove; _title.MouseMove += DragMove; MouseUp += (s, e) => _dragging = false; _timer.Tick += (s, e) => Tick(); _timer.Start(); FormClosed += (s, e) => { _timer.Stop(); _sample?.Dispose(); }; } private Button MkBtn(string text, Action onClick) { var b = new Button { Text = text, Width = 84, Height = 26, Margin = new Padding(0, 2, 4, 0), FlatStyle = FlatStyle.Flat, BackColor = Color.FromArgb(52, 60, 74), ForeColor = Color.FromArgb(222, 230, 242), Cursor = Cursors.Hand, Font = new Font("Microsoft YaHei UI", 8.5F) }; b.FlatAppearance.BorderColor = Color.FromArgb(70, 80, 96); b.Click += (s, e) => onClick(); return b; } private void Copy(string text) { try { Clipboard.SetText(text); _log.Write("已复制:" + text); } catch { } } private void DragStart(object? s, MouseEventArgs e) { if (e.Button != MouseButtons.Left) return; _dragging = true; _dragOffset = e.Location; if (s != _title && s != this) _dragOffset = new Point(e.X + (s as Control)!.Left, e.Y + (s as Control)!.Top + 26); } private void DragMove(object? s, MouseEventArgs e) { if (!_dragging) return; var screen = s == this ? PointToScreen(e.Location) : (s as Control)!.PointToScreen(e.Location); Location = new Point(screen.X - _dragOffset.X, screen.Y - _dragOffset.Y); } private void Tick() { if (IsDisposed) return; var p = Cursor.Position; if (p == _cursor && _sample != null) return; _cursor = p; try { int half = SampleSize / 2; _sample?.Dispose(); _sample = new Bitmap(SampleSize, SampleSize); using (var g = Graphics.FromImage(_sample)) g.CopyFromScreen(p.X - half, p.Y - half, 0, 0, new Size(SampleSize, SampleSize)); _color = _sample.GetPixel(half, half); } catch { return; } _lblPos.Text = $"坐标 {_cursor.X}, {_cursor.Y}"; _lblHex.Text = $"颜色 #{_color.R:X2}{_color.G:X2}{_color.B:X2}"; _lblRgb.Text = $"RGB {_color.R}, {_color.G}, {_color.B}"; _mag.Invalidate(); _swatch.Invalidate(); } private void MagPaint(object? s, PaintEventArgs e) { e.Graphics.Clear(Color.FromArgb(20, 24, 30)); if (_sample == null) return; e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor; e.Graphics.PixelOffsetMode = PixelOffsetMode.Half; e.Graphics.DrawImage(_sample, new Rectangle(0, 0, _mag.Width, _mag.Height)); // 准星 int c = _mag.Width / 2; using var pen = new Pen(Color.FromArgb(220, 255, 80, 80)) { Width = 1 }; e.Graphics.DrawLine(pen, c, 0, c, _mag.Height); e.Graphics.DrawLine(pen, 0, c, _mag.Width, c); using var inner = new Pen(Color.White) { Width = 1 }; e.Graphics.DrawRectangle(inner, c - MagZoom / 2, c - MagZoom / 2, MagZoom, MagZoom); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); using var pen = new Pen(Color.FromArgb(64, 72, 86)); e.Graphics.DrawRectangle(pen, 0, 0, ClientSize.Width - 1, ClientSize.Height - 1); } } }