У меня есть программа, в которой есть небольшая графическая часть, где вы можете посмотреть и сохранить цвет определенных пикселей экрана.
Проблема в том, что когда я извлекаю цвет, иногда я получаю нужный мне цвет ... иногда я просто получаю белый или какой-то другой случайный цвет (обычно белый, но я также использую белый фон для тестирования) ,
Можете ли вы определить причину, почему это будет? Я также полностью открыт для возможных улучшений.
У меня есть окно для картинок под названием Canvas, и я могу нажать «Захват изображения», чтобы сделать снимок экрана следующим образом:
private void CaptureImage_Click(object sender, EventArgs e)
{
this.Visible = false;
Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(bitmap as Image);
graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
Canvas.SizeMode = PictureBoxSizeMode.AutoSize;
Canvas.Image = bitmap;
graphics.Dispose();
this.Visible = true;
}
Или я могу загрузить файл изображения, хотя для этого теста я просто делаю захват.
Когда я щелкаю правой кнопкой мыши где-то на изображении, в моем событии mousedown я делаю:
if (e.Button == MouseButtons.Right)
{
pointPoint = e.Location;
Debug.WriteLine("right mouse: " + e.Location.ToString());
ContextMenuStrip cm = new ContextMenuStrip();
cm.Items.Add("Flag this as Point");
cm.Items.Add("Extract Color");
Canvas.ContextMenuStrip = cm;
cm.ItemClicked += new ToolStripItemClickedEventHandler(Cm2Click);
}
(pointPoint - это объект Point)
Как видите, я проверяю место, где щелкнул, используя окно отладки. В моем контекстном меню я также проверяю это снова, чтобы убедиться, что оно не изменилось перед вызовом. Контекстное меню делает:
private void Cm2Click(object sender, ToolStripItemClickedEventArgs e)
{
//var clickedMenuItem = sender as MenuItem;
ToolStripItem menuText = e.ClickedItem;
Debug.WriteLine(menuText);
if (menuText.ToString() == "Extract Color")
{
string input = "Default";
bool testBox = false;
do
{
if (InputBox.inputBox("ColorName", "You must provide a unique name for this color", ref input) == DialogResult.OK)
{
if (!String.IsNullOrWhiteSpace(input) && input != "Default")
{
Debug.WriteLine("location changed to: " + pointPoint);
colorExtractor = Functions.GetColorAt(pointPoint);
ColorData clr = new ColorData(input, colorExtractor);
string expression;
expression = $"Name = '{clr.Name}'";
DataRow[] foundRows;
DataTable dt = _allEventData.Tables["ColorData"];
foundRows = dt.Select(expression);
if (foundRows.Length > 0) {
testBox = false;
Debug.WriteLine("Color Found");
}
else {
dt.Rows.Add(clr.Name, clr.R, clr.G, clr.B);
dt.AcceptChanges();
testBox = true;
}
}
} else
{
return;
}
} while (testBox == false);
}
}
и ColorData - это просто класс, который я определил для хранения данных:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace EventClicker
{
public class ColorData : EventArgs
{
public string Name { get; set; }
public int R { get; set; }
public int G { get; set; }
public int B { get; set; }
public bool Found { get; set; }
public ColorData(String name, Color color)
{
this.Name = name;
this.R = color.R;
this.G = color.G;
this.B = color.B;
}
public ColorData(String name, String r, String g, String b)
{
this.Name = name;
this.R = Int32.Parse(r);
this.G = Int32.Parse(g);
this.B = Int32.Parse(b);
}
}
}
Последнее, но не менее важное, метод, который я вызываю (Functions.GetColorAt), определен здесь (и я определенно украл это у кого-то в сети). Редактировать: Это где-то здесь, Как прочитать Цвет экрана Pixel
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace EventClicker
{
public static class Functions
{
private static Bitmap screenPixel = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
[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 static 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);
}
}
}