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