C# 如何获取椭圆内指定颜色的坐标?

C# 如何获取椭圆内指定颜色的坐标?,c#,winforms,graphics,drawing,gdi+,C#,Winforms,Graphics,Drawing,Gdi+,小免责声明:这是我第一次在表单中处理图形,因此我对这里的概念不太熟悉 好的,我一直在尝试制作一个应用程序,跟踪光标在整个屏幕上的位置,并在其周围绘制一个椭圆。我借用的代码来自于问题(我更改了椭圆的X和Y位置,以便在光标周围自动调整自身,而不管其大小),到目前为止,一切都很正常。以下是迄今为止的代码: public static float width; public static float height; public Main(float w

小免责声明:这是我第一次在表单中处理图形,因此我对这里的概念不太熟悉

好的,我一直在尝试制作一个应用程序,跟踪光标在整个屏幕上的位置,并在其周围绘制一个椭圆。我借用的代码来自于问题(我更改了椭圆的X和Y位置,以便在光标周围自动调整自身,而不管其大小),到目前为止,一切都很正常。以下是迄今为止的代码:

        public static float width;
        public static float height;

        public Main(float w, float h)
        {
            InitializeComponent();
            this.DoubleBuffered = true;
            width = w;
            height = h;
            BackColor = Color.White;
            FormBorderStyle = FormBorderStyle.None;
            Bounds = Screen.PrimaryScreen.Bounds;
            TopMost = true;
            TransparencyKey = BackColor;
            this.ShowInTaskbar = false;
            timer1.Tick += timer1_Tick;
        }

        Timer timer1 = new Timer() { Interval = 1, Enabled = true };

        protected override void OnPaint(PaintEventArgs e)
        {
            DrawTest(e.Graphics);
            base.OnPaint(e);
        }

        private void DrawTest(Graphics g)
        {
            var p = PointToClient(Cursor.Position);
            g.DrawEllipse(Pens.DeepSkyBlue, p.X - (width / 2), p.Y - (height / 2), width, height);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Invalidate();
        }
现在,我希望应用程序检查椭圆区域内是否存在预先指定的颜色,如果存在,则获取距离具有该颜色的光标最近的像素的位置。我到处都找遍了,没有找到做这件事的方法

我知道它背后的逻辑是获取椭圆内的所有像素,检查颜色是否存在,并找到一个最靠近光标的像素,但我还没有实现它


任何帮助都将不胜感激。

这是一种简化的方法(不需要PInvoking、鼠标跟踪/挂钩或其他低级操作)。
如果您不需要对窗口后面发生的事情进行太多控制,也不想录制动画图像,只需执行问题描述中的操作即可:捕获鼠标指针下当前外部窗口/桌面元素的颜色

这里使用了一个技巧:表单的
背景色
及其
透明键
设置为淡蓝色(
color.Navy
)。这允许有一个透明但坚实的形式。
实际上,即使表单是完全透明的,也会引发
MouseMove
事件,尽管可以单击

另一个准技巧是使用标准属性,而不是调用
SetStyle()
方法启用的
OptimizedDoubleBuffer
,对表单进行双重缓冲

属性设置为true,因此在调整大小时表单会重新绘制自身

使用此设置,要获得光标位置下的颜色,您只需使用大小为
(1,1)
(我们只需要这一个像素)的位图拍摄当前屏幕的一个像素快照,并使用(不是很快,但功能正常)方法从位图读取颜色

单击鼠标右键时,光标下的颜色保存在
列表中(可使用公共/只读
SavedColors
属性访问),然后在用作此调色板画布的PictureBox中绘制

要构建此示例,请执行以下操作:

  • 创建一个新表单
  • 添加一个PictureBox(在这里,名为
    picColor
    )并将其锚定在右上角。此控件用于在鼠标指针移动时显示光标下的当前颜色
  • 在前一个PictureBox下添加第二个PictureBox(此处名为
    picPalette
    ),并将其固定在右上角和右下角。这用于绘制保存颜色的当前调色板。
    在设计器中,使用“事件”面板,使用您可以在此代码中找到的处理程序方法订阅绘制事件(即,不要添加另一个)

使用System.Collections.Generic;
使用系统图;
使用System.Drawing.Drawing2D;
使用System.Windows.Forms;
公共部分类frmColorPicker:表单
{
Color m_CurrentColor=Color.Empty;
List m_SavedColors=新列表();
公共frmColorPicker()
{
初始化组件();
this.ResizeRedraw=true;
this.DoubleBuffered=true;
this.TopMost=true;
this.BackColor=Color.Navy;
this.TransparencyKey=Color.Navy;
}
公共颜色CursorEllipseColor{get;set;}=Color.Orange;
public List SavedColors=>m_SavedColors;
受保护的覆盖无效OnPaint(PaintEventArgs e)
{
基础漆(e);
getColorUndersor();
e、 Graphics.SmoothingMode=SmoothingMode.AntiAlias;
var rect=GetCursorEllipse();
使用(var笔=新笔(CursorEllipseColor,2)){
e、 图形学.抽屉式(钢笔,矩形);
}
}
MouseEventArgs e上的受保护覆盖无效(MouseEventArgs e)
{
base.OnMouseDown(e);
if(e.Button==MouseButtons.Right){
m_SavedColors.Add(m_CurrentColor);
picpalete.Invalidate();
}
}
MouseMove上的受保护覆盖无效(MouseEventArgs e)
{
基地移动(e);
这个。使无效();
}
私有矩形GetCursorEllipse()
{
var cursorEllipse=新矩形(指向客户端(Cursor.Position)、Cursor.Size);
cursorEllipse.Offset(-cursorEllipse.Width/2,-cursorEllipse.Height/2);
返回光标;
}
私有void getColorUndersor()
{
使用(var bmp=新位图(1,1))
使用(var g=Graphics.FromImage(bmp)){
g、 CopyFromScreen(Cursor.Position,Point.Empty,新大小(1,1));
m_CurrentColor=bmp.GetPixel(0,0);
picColor.BackColor=m_CurrentColor;
}
}
私有void picpalete_Paint(对象发送器,PaintEventArgs e)
{
int rectcont=0;
int矩形线=0;
int rectsPerLine=picpalete.Width/20;
foreach(以m_保存的颜色表示的变量颜色){
使用(var笔刷=新的SolidBrush(颜色)){
var rect=新矩形(新点(rectsunt*20,矩形线*20),新大小(20,20));
e、 图形。填充矩形(画笔,矩形);
e、 图形.DrawRectangle(Pens.DarkGray,rect);
rectroscont+=1;
if(RectScont==rectsPerLine){
rectroscont=0;
直肠线+=1;
}
}
}
}
}

这就是它的工作原理:

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;
                }
            }
        }
    }
}