0

У меня есть код, который представлен ниже. Помогите сделать так, что бы отслеживание цвета происходила самостоятельно в определённой области, без нажатия на мышь. Если что то будет не понятно постараюсь объяснить.

using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Gma.System.MouseKeyHook;

public class ColorTracker : Form { private const int VK_A = 0x41; private const int VK_D = 0x44; private const int KEY_DOWN = 0x8000;

private int tolerance = 5;
private Color targetColorMin = Color.FromArgb(0, 255, 0);
private Color targetColorMax = Color.FromArgb(255, 255, 255);
private bool scriptActivated = false;
private Button startStopButton;
private IKeyboardMouseEvents globalHook;

[DllImport("user32.dll")]
private static extern short GetAsyncKeyState(int vKey);

public ColorTracker()
{
    SetupUI();

    // Инициализация глобальных хуков
    globalHook = Hook.GlobalEvents();

    // Подписываемся на события перемещения мыши и ввода с клавиатуры
    globalHook.MouseDownExt += GlobalHookMouseDownExt;
    globalHook.KeyPress += GlobalHookKeyPress;
}

private void SetupUI()
{
    startStopButton = new Button();
    startStopButton.Text = "Запустить";
    startStopButton.Click += StartStopButton_Click;

    this.Controls.Add(startStopButton);
}

private void StartStopButton_Click(object sender, EventArgs e)
{
    scriptActivated = !scriptActivated;
    startStopButton.Text = scriptActivated ? "Остановить" : "Запустить";
}

private void GlobalHookMouseDownExt(object sender, MouseEventExtArgs e)
{
    // При нажатии мыши проверяем цвет в текущей позиции курсора
    if (scriptActivated)
    {
        Color pixelColor = GetPixelColor(e.X, e.Y);

        if (IsColorInRange(pixelColor, targetColorMin, targetColorMax))
        {
            // Делаем что-то на основе совпадения цвета
            // Например:
            if (IsColorCloseToWhite(pixelColor))
            {
                SendKeys.SendWait("d");
            }
            else
            {
                SendKeys.SendWait("a");
            }
        }
    }
}

private void GlobalHookKeyPress(object sender, KeyPressEventArgs e)
{
    // При нажатии клавиши можно обработать это глобально, если необходимо
    // Например, можно остановить скрипт при нажатии определенной клавиши
    if (e.KeyChar == 'x')
    {
        scriptActivated = false;
        startStopButton.Text = "Запустить";
    }
}

private Color GetPixelColor(int x, int y)
{
    using (Bitmap bmp = new Bitmap(1, 1))
    {
        using (Graphics g = Graphics.FromImage(bmp))
        {
            g.CopyFromScreen(new Point(x, y), Point.Empty, new Size(1, 1));
        }
        return bmp.GetPixel(0, 0);
    }
}

private bool IsColorInRange(Color color, Color min, Color max)
{
    return color.R >= min.R - tolerance && color.R <= max.R + tolerance
        && color.G >= min.G - tolerance && color.G <= max.G + tolerance
        && color.B >= min.B - tolerance && color.B <= max.B + tolerance;
}

private bool IsColorCloseToWhite(Color color)
{
    return color.R >= 230 && color.G >= 230 && color.B >= 230;
}

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.Run(new ColorTracker());
}

}

aepot
  • 49,560
Rasal
  • 3
  • 2
    Для начала расскажите, что этот код делает, и вообще зачем он нужен. И что значит "определённая область". Про самостоятельно тоже непонятно - как именно? – aepot Jul 25 '23 at 23:09
  • Этот код нужен что бы отслеживать цветовой диапазон от белого до зелёного, окончательный результат зелёный цвет и что бы его добиться надо зажимать a и d. "определённая область", то есть есть область на экране, например 150x150 в который будет работать этот скрипт. Самостоятельно в смысле по включению он сам понимает какой цвет в данный момент и прожимает кнопки, а в данный момент этот скрипт работает, если только нажать по цвету. – Rasal Jul 25 '23 at 23:40
  • Можно сказать, что это некий бот – Rasal Jul 25 '23 at 23:41

1 Answers1

0

Можно по тыку мышкой запустить цикл, скажем раз в секунду.

private bool isWorking;

private async void GlobalHookMouseDownExt(object sender, MouseEventExtArgs e) { if (isWorking) { isWorking = false; return; } if (!scriptActivated) return; isWorking = true;

while (isWorking && scriptActivated)
{
    Color pixelColor = GetPixelColor(e.Location);

    if (IsColorInRange(pixelColor, targetColorMin, targetColorMax))
    {
        if (IsColorCloseToWhite(pixelColor))
        {
            SendKeys.SendWait("d");
        }
        else
        {
            SendKeys.SendWait("a");
        }
    }
    await Task.Delay(1000); // пауза 1 секунда
}
isWorking = false;

}

То есть нажал на мышь, начало работать раз в секунду. Нажал еще раз - прекратило.

По-хорошему, сюда бы CancellationToken прикрутить для верности, пример здесь, это позволит прерывать Delay немедленно. Но вы уж сами решайте, как лучше.

И взятие цвета можно слегка оптимизировать

private readonly Bitmap bufferBmp = new Bitmap(1, 1);

private Color GetPixelColor(Point location) { using (Graphics g = Graphics.FromImage(bufferBmp)) { g.CopyFromScreen(location, Point.Empty, bufferBmp.Size); } return bufferBmp.GetPixel(0, 0); }

Незачем создавать новый битмап на каждый пиксель, это ресурсозатратное занятие.

aepot
  • 49,560