Это упрощенный метод (он не требует PInvoking, отслеживания / подключения мыши или других операций низкого уровня ).
Он может работать достаточно хорошо, если вам не нужно слишком много контроля о том, что происходит за вашим окном, вы не хотите записывать анимированные изображения, просто сделайте то, что указано в описании вопроса: захватите цвета внешних Windows / элементов рабочего стола, которые в настоящее время находятся под указателем мыши.
Здесь используется трюк: формы BackColor
и TransparencyKey
устанавливаются в цвет blue-i sh (Color.Navy
). Это позволяет иметь прозрачную, но solid Форму.
На практике, MouseMove
события возникают, даже если Форма полностью прозрачна и может быть нажата, хотя .
Другой квази-трюк - это двойная буферизация формы с использованием стандартного свойства DoubleBuffer , а не OptimizedDoubleBuffer
, которое можно включить, вызвав метод SetStyle()
.
Свойство ResizeRedraw установлено в значение true, поэтому форма Redr aws сама себя при изменении размера.
При этой настройке, чтобы получить цвет под положением курсора, вам просто нужно сделать снимок текущего экрана в один пиксель, используя растровое изображение размером (1, 1)
(нам нужен только этот один пиксель) и используйте (не очень быстрый, но функциональный) метод GetPixel()
для чтения цвета из растрового изображения.
При нажатии правой кнопки мыши цвет под курсором сохраняется в List<Color>
(который доступен с помощью общедоступного / доступного только для чтения свойства SavedColors
), а затем отрисовывается в PictureBox, используемом как канва для этого Палитра .
Чтобы построить этот пример:
- Создайте новую форму
- Добавьте 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();
this.ResizeRedraw = true;
this.DoubleBuffered = true;
this.TopMost = true;
this.BackColor = Color.Navy;
this.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);
this.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;
}
}
}
}
}
Вот как это работает:
![Transparent Form GetPixel](https://i.stack.imgur.com/AUnVP.gif)