209 lines
8.3 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|