C# 如何读取屏幕像素的颜色
好的,我正在寻找一个功能或东西,可以读取显示器上某个像素的颜色,当检测到该颜色时,另一个功能将被启用。我想使用RGB。谢谢你的帮助。谢谢。据我所知,最简单的方法是:C# 如何读取屏幕像素的颜色,c#,winforms,gdi+,pixel,C#,Winforms,Gdi+,Pixel,好的,我正在寻找一个功能或东西,可以读取显示器上某个像素的颜色,当检测到该颜色时,另一个功能将被启用。我想使用RGB。谢谢你的帮助。谢谢。据我所知,最简单的方法是: 查看位图并获得像素颜色 编辑 在像素变为某种颜色之前,可能无法“等待”。您的程序可能需要经常循环并检查它,直到它看到颜色为止 例如: while(!IsPixelColor(x, y, color)) { //probably best to add a sleep here so your program doesn't
while(!IsPixelColor(x, y, color))
{
//probably best to add a sleep here so your program doesn't use too much CPU
}
DoAction();
编辑2
下面是一些可以修改的示例代码。此代码只是基于给定像素中的当前颜色更改标签的颜色。此代码避免了前面提到的句柄泄漏
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
Thread t;
int x, y;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
x = 20;
y = 50;
t = new Thread(update);
t.Start();
}
private void update()
{
Bitmap screenCopy = new Bitmap(1, 1);
using (Graphics gdest = Graphics.FromImage(screenCopy))
{
while (true)
{
//g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(256, 256));
using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero))
{
IntPtr hSrcDC = gsrc.GetHdc();
IntPtr hDC = gdest.GetHdc();
int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, x, y, (int)CopyPixelOperation.SourceCopy);
gdest.ReleaseHdc();
gsrc.ReleaseHdc();
}
Color c = Color.FromArgb(screenCopy.GetPixel(0, 0).ToArgb());
label1.ForeColor = c;
}
}
}
}
}这是最有效的:它在光标位置捕获一个像素,并且不依赖于只有一个监视器
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;
namespace FormTest
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern bool GetCursorPos(ref Point lpPoint);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
public Form1()
{
InitializeComponent();
}
private void MouseMoveTimer_Tick(object sender, EventArgs e)
{
Point cursor = new Point();
GetCursorPos(ref cursor);
var c = GetColorAt(cursor);
this.BackColor = c;
if (c.R == c.G && c.G < 64 && c.B > 128)
{
MessageBox.Show("Blue");
}
}
Bitmap screenPixel = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
public Color GetColorAt(Point location)
{
using (Graphics gdest = Graphics.FromImage(screenPixel))
{
using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero))
{
IntPtr hSrcDC = gsrc.GetHdc();
IntPtr hDC = gdest.GetHdc();
int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, location.X, location.Y, (int)CopyPixelOperation.SourceCopy);
gdest.ReleaseHdc();
gsrc.ReleaseHdc();
}
}
return screenPixel.GetPixel(0, 0);
}
}
}
如果需要,您可以将其包装在线程中,或者从控制台应用程序执行它。“随便你喜欢什么,”我想。请检查我在以前的一个项目中使用过的两个不同功能: 1) 此函数用于拍摄桌面的快照
private void CaptureScreenAndSave(string strSavePath)
{
//SetTitle("Capturing Screen...");
Bitmap bmpScreenshot;
Graphics gfxScreenshot;
bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height,System.Drawing.Imaging.PixelFormat.Format32bppArgb);
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
MemoryStream msIn = new MemoryStream();
bmpScreenshot.Save(msIn, System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[0], null);
msIn.Close();
byte[] buf = msIn.ToArray();
MemoryStream msOut = new MemoryStream();
msOut.Write(buf, 0, buf.Length);
msOut.Position = 0;
Bitmap bmpOut = new Bitmap(msOut);
try
{
bmpOut.Save(strSavePath, System.Drawing.Imaging.ImageFormat.Bmp);
//SetTitle("Capturing Screen Image Saved...");
}
catch (Exception exp)
{
}
finally
{
msOut.Close();
}
}
2) 此函数在输入中获取图像,并计算给定像素范围的RGB平均值
double GetRGBAverageForPixelRange( int istartRange, int iEndRange, Bitmap oBitmap )
{
double dRetnVal = 0 ;
Color oTempColor ;
int i, j ;
for( int iCounter = istartRange ; iCounter < iEndRange ; iCounter++ )
{
i = (iCounter % (oBitmap.Width));
j = ( iCounter / ( oBitmap.Width ) ) ;
if (i >= 0 && j >= 0 && i < oBitmap.Width && j < oBitmap.Height )
{
oTempColor = oBitmap.GetPixel(i, j);
dRetnVal = dRetnVal + oTempColor.ToArgb();
}
}
return dRetnVal ;
}
double GetRGBAverageForPixelRange(int-istartRange、int-iEndRange、位图oBitmap)
{
双德雷特瓦尔=0;
颜色和颜色;
int i,j;
for(int-iCounter=istartRange;iCounter=0&&j>=0&&i
这两个功能结合在一起可能会解决您的问题。快乐编码:)
编辑:请注意GetPixel的功能非常慢。在使用它之前,我会三思而后行。这里的大多数答案都使用相同的像素源(桌面dc)。
关键功能是 我认为这是最干净、最快捷的方法 注意:
如果修改了Windows上显示设置中的默认文本大小,以提高高分辨率显示的可读性,则需要以相同的方式调整GetPixel()的坐标参数。例如,在Windows 7上,如果光标位置为(x,y)且文本大小为150%,则需要调用GetPixel(x*1.5,y*1.5)以获取光标下像素的颜色。此函数较短,并且可以使用
System.Drawing
,而不使用Pinvoke获得相同的结果
Bitmap bmp = new Bitmap(1, 1);
Color GetColorAt(int x, int y)
{
Rectangle bounds = new Rectangle(x, y, 1, 1);
using (Graphics g = Graphics.FromImage(bmp))
g.CopyFromScreen(bounds.Location, Point.Empty, bounds.Size);
return bmp.GetPixel(0, 0);
}
这条线大约用10毫秒
int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, location.X, location.Y, (int)CopyPixelOperation.SourceCopy);
是否要监视整个桌面或特定应用程序的像素更改?特定像素。比如说125130的像素,我需要它等到它检测到这个像素的RGB变成某个RGB,为什么要这样做?似乎有某种潜在的原因,如果你给我们多一点信息,我们可能会给你一个更好的方法来实现同样的目标。你正在写一个游戏,需要确定两个物体何时碰撞?你想知道某个程序是否已经启动了吗?这是一个游戏,需要两次检查它是否在某个屏幕上,当它在某个屏幕上时,它会启动一个函数。但是你应该知道游戏在哪个屏幕上,因为你控制着代码……我不想这样做,我已经考虑过了,但这不是一个选项。像素必须不断地被观察,因为它会在不到一分钟的时间内不断地找到它要找的像素。然后不要睡觉。在最坏的情况下,此循环可能需要花费所有的.1秒来循环。请注意,您不应该运行.CopyFromScreen,它有一个句柄泄漏,最好是使用Win32 API
Bitmap.GetPixel()
返回一个颜色
,因此我认为没有理由调用ToArgb()
并将其传递到Color.FromArgb()
+1中,以指出CopyFromScreen可用于仅捕获屏幕的一小部分。但请注意,CopyFormScreen每次调用时都会泄漏一个句柄。谢谢John,这非常有效,这是另一个快速问题。如果我想让它持续搜索像素,我该如何实现呢?我知道这已经晚了10年,但如果有人对@Brandon的问题的答案感兴趣:我使用了一个计时器,每250毫秒设置一个间隔(或者你希望它搜索的速度有多快),然后在计时器上打勾进行实际读取。哈比卜,你加的字条不是我答案的一部分。这不是我的技术,是你的。如果可以的话,请发表评论。然后你可以在评论上获得投票。此外,我认为在GetPixel上调整x和y是错误的。最好在GetColorAt方法之外的某个地方检查分辨率调整和光标位置。+1用于显示文本大小的注释。如果文本大小不同于100%,且未正确调整,则该方法将从错误的像素获取颜色。
Bitmap bmp = new Bitmap(1, 1);
Color GetColorAt(int x, int y)
{
Rectangle bounds = new Rectangle(x, y, 1, 1);
using (Graphics g = Graphics.FromImage(bmp))
g.CopyFromScreen(bounds.Location, Point.Empty, bounds.Size);
return bmp.GetPixel(0, 0);
}
int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, location.X, location.Y, (int)CopyPixelOperation.SourceCopy);