这是一种简化的方法(它不需要 PInvoking、鼠标跟踪/挂钩或其他低级运营)。
如果您不需要对窗口后面发生的事情进行太多控制,您不想记录动画图像,只需执行问题描述中的操作:捕获当前在鼠标指针。
这里使用了一个技巧:Form的BackColor
和它的TransparencyKey
被设置为蓝色(Color.Navy
)。这允许有一个透明但solid Form.
在实践中,MouseMove
即使表单完全透明,也会引发事件点击通过.
另一个准技巧是使用标准双缓冲表单双缓冲财产,而不是OptimizedDoubleBuffer
可以调用以下命令来启用SetStyle()
method.
The 调整大小重画属性设置为 true,因此如果/当调整大小时,表单会重新绘制自身。
通过此设置,要获取光标位置下的颜色,您只需使用大小为的位图拍摄当前屏幕的单像素快照(1, 1)
(我们只需要那个像素)并使用(不是很快但功能齐全)GetPixel()方法从位图中读取颜色。
单击鼠标右键时,光标下的颜色将保存在List<Color>
(可以使用公共/只读访问SavedColors
属性),然后在用作画布的 PictureBox 中绘制Palette.
要构建此示例:
- 创建一个新表格
- 添加一个PictureBox(此处命名为
picColor
)并将其锚定在右上角。该控件用于当鼠标指针移动时显示光标下的当前颜色。
- 添加第二个 PictureBox(此处名为
picPalette
) 在前一个下方并将其锚定为“上-右-下”。这用于绘制已保存颜色的当前调色板。
在设计器中,使用事件面板通过您可以在此代码中找到的处理程序方法订阅 Paint 事件(即,不要添加另一个)。
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
public partial class frmColorPicker : Form
{
Color m_CurrentColor = Color.Empty;
List<Color> m_SavedColors = new List<Color>();
public frmColorPicker()
{
InitializeComponent();
ResizeRedraw = true;
DoubleBuffered = true;
TopMost = true;
BackColor = Color.Navy;
TransparencyKey = Color.Navy;
}
public Color CursorEllipseColor { get; set; } = Color.Orange;
public List<Color> SavedColors => m_SavedColors;
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
GetColorUnderCursor();
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
var rect = GetCursorEllipse();
using (var pen = new Pen(CursorEllipseColor, 2)) {
e.Graphics.DrawEllipse(pen, rect);
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Right) {
m_SavedColors.Add(m_CurrentColor);
picPalette.Invalidate();
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
Invalidate();
}
private Rectangle GetCursorEllipse()
{
var cursorEllipse = new Rectangle(PointToClient(Cursor.Position), Cursor.Size);
cursorEllipse.Offset(-cursorEllipse.Width / 2, -cursorEllipse.Height / 2);
return cursorEllipse;
}
private void GetColorUnderCursor()
{
using (var bmp = new Bitmap(1, 1))
using (var g = Graphics.FromImage(bmp)) {
g.CopyFromScreen(Cursor.Position, Point.Empty, new Size(1, 1));
m_CurrentColor = bmp.GetPixel(0, 0);
picColor.BackColor = m_CurrentColor;
}
}
private void picPalette_Paint(object sender, PaintEventArgs e)
{
int rectsCount = 0;
int rectsLines = 0;
int rectsPerLine = picPalette.Width / 20;
foreach (var color in m_SavedColors) {
using (var brush = new SolidBrush(color)) {
var rect = new Rectangle(new Point(rectsCount * 20, rectsLines * 20), new Size(20, 20));
e.Graphics.FillRectangle(brush, rect);
e.Graphics.DrawRectangle(Pens.DarkGray, rect);
rectsCount += 1;
if (rectsCount == rectsPerLine) {
rectsCount = 0;
rectsLines += 1;
}
}
}
}
}
它是这样工作的: