Files
2026-10-24 13:02:19 +08:00

209 lines
8.3 KiB
C#

using System.Drawing.Drawing2D;
using anjianjingling.Common;
namespace anjianjingling.Forms
{
/// <summary>坐标取色器:置顶小窗,实时显示鼠标坐标与屏幕颜色,可复制坐标/颜色或写入日志。</summary>
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);
}
}
}