gpt4 book ai didi

c# - 如何使用半透明选择器在屏幕上的任意位置选择颜色?

转载 作者:行者123 更新时间:2023-12-04 09:38:45 24 4
gpt4 key购买 nike

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

好的,所以我一直在尝试制作一个应用程序来跟踪光标在整个屏幕中的位置并在其周围绘制一个椭圆。我借用的代码来自this问题(我更改了 Ellipse 的 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、鼠标跟踪/ Hook 或其他低级操作)。
如果您不需要过多控制 Window 后面发生的事情,您不想录制动画图像,它可以很好地工作,只需执行问题描述中的操作:捕获当前位于鼠标指针。
这里使用了一个技巧:表单的 BackColor及其TransparencyKey设置为蓝色( Color.Navy )。这允许具有透明但实心的形式。
在实践中,MouseMove即使表单完全透明并且可以点击,也会引发事件。
另一个准技巧是使用标准 DoubleBuffer 对表单进行双缓冲。属性,而不是 OptimizedDoubleBuffer可以通过调用 SetStyle() 启用方法。
ResizeRedraw属性设置为 true,因此窗体在调整大小时会自行重绘。
使用此设置,要获得光标位置下的颜色,您只需使用大小为 (1, 1) 的位图拍摄当前屏幕的单像素快照。 (我们只需要一个像素)并使用(不是很快但功能强大) GetPixel() 从位图中读取颜色的方法。
单击鼠标右键时,光标下的颜色保存在 List<Color> 中。 (可使用公共(public)/只读 SavedColors 属性访问),然后在用作此调色板的 Canvas 的 PictureBox 中进行绘制。
要构建此示例:

  • 新建表格
  • 添加一个 PictureBox(此处命名为 picColor )并将其锚定在右上角。此控件用于在鼠标指针移动时显示光标下的当前颜色。
  • 在前一个图片框下添加第二个图片框(此处命名为 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;
    }
    }
    }
    }
    }

    这是它的工作原理:
    Transparent Form GetPixel

    关于c# - 如何使用半透明选择器在屏幕上的任意位置选择颜色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62428888/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com