C# Поиск изображения в приложении, работающем в фоновом режиме | AutoIT ImageSearch.DLL - PullRequest
0 голосов
/ 14 июля 2020

Я пытаюсь написать бота для игры. Сейчас все работает нормально. Но он запускается только тогда, когда Игра находится в полноэкранном режиме на переднем плане. Но я хочу использовать бота, занимаясь другими делами. Поэтому я хочу запустить его в фоновом режиме.

Я использую ImageSearch DLL из AutoIT. Из этого руководства

C# ImageSearch DLL

Я также хочу, чтобы щелчок выполнялся в фоновом режиме, но сначала давайте сосредоточимся на ImageScan, потому что я думаю, что это сложнее.

Вот как я вызываю ImageSearch и делаю Click.

coordinates = UseImageSearch(@"skipdialog.PNG", "30");

if (coordinates != null)
{
    LeftMouseClick(Convert.ToInt32(coordinates[1]), Convert.ToInt32(coordinates[2]));                    
}

И это метод ImageSearch с ImageSearch DLL из AutoIT

[DllImport(@"C:\ImageSearchDLL.dll")]

public static extern IntPtr ImageSearch(int x, int y, int right, int bottom, [MarshalAs(UnmanagedType.LPStr)] string imagePath);
public static string[] UseImageSearch(string imgPath, string tolerance)
{
    imgPath = "*" + tolerance + " " + imgPath;

    IntPtr result = ImageSearch(0, 0, 1920, 1080, imgPath);
    string res = Marshal.PtrToStringAnsi(result);

    if (res[0] == '0') return null;

    string[] data = res.Split('|');

    int x; int y;
    int.TryParse(data[1], out x);
    int.TryParse(data[2], out y);

    return data;
}       

Надеюсь, вы, ребята, можете Помогите мне, потому что я просто не нашел хорошего учебника в Интернете. Я ищу это годами ... Это помогло бы многим людям, я бы отредактировал Решение в этой теме, чтобы каждый мог его использовать!

Если есть другие Решения без ImageSearch.DLL из AutoIT также дайте мне знать, пожалуйста!

Happy Botting!

BR

1 Ответ

0 голосов
/ 15 июля 2020

Я нашел ответ и делюсь им со всеми.

Я знал, что должно быть решение, чтобы поймать неотображаемое изображение из приложения.

Это единственное найденное мной решение, которое все еще работает.

Сохранение снимка экрана с помощью C#, WPF и DWM

Вместо поиска весь экран и сравните его с изображением. Я делаю снимок экрана окна (также работает, когда окно находится в фоновом режиме с помощью этого метода), а затем сравниваю снимок экрана с изображением.

Сначала вам нужно создать эту переменную и это struct.

public const int SRCCOPY = 13369376;

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;
}

Затем вам нужно создать 3 класса.

    public static class Utilities
    {
        public static Image CaptureScreen()
        {
            return CaptureWindow(User32.GetDesktopWindow());
        }

        public static Image CaptureWindow(IntPtr handle)
        {

            IntPtr hdcSrc = User32.GetWindowDC(handle);

            RECT windowRect = new RECT();
            User32.GetWindowRect(handle, ref windowRect);

            int width = windowRect.right - windowRect.left;
            int height = windowRect.bottom - windowRect.top;

            IntPtr hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height);

            IntPtr hOld = Gdi32.SelectObject(hdcDest, hBitmap);
            Gdi32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, SRCCOPY);
            Gdi32.SelectObject(hdcDest, hOld);
            Gdi32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);

            Image image = Image.FromHbitmap(hBitmap);
            Gdi32.DeleteObject(hBitmap);

            return image;
        }
    }

    public class Gdi32
    {
        [DllImport("gdi32.dll")]
        public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjectSource, int nXSrc, int nYSrc, int dwRop);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);
        [DllImport("gdi32.dll")]
        public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
    }

    public static class User32
    {
        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
        [DllImport("user32.dll")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
    }

А для ImageSearch.DLL вы добавляете дополнительный параметр для снимка экрана.

[DllImport(@"ImageSearchDLL.dll")]
public static extern IntPtr ImageSearch(int x, int y, int right, int bottom, [MarshalAs(UnmanagedType.LPStr)] string imagePath, Image image);

Затем вы изменяете метод UseImageSearch, чтобы также отправить снимок экрана в метод ImageSearch.

public static string[] UseImageSearch(string imgPath, string tolerance)
{
imgPath = "*" + tolerance + " " + imgPath;
Process p = Process.GetProcessesByName("ProcessName").FirstOrDefault();
IntPtr h = p.MainWindowHandle;
Image image = Utilities.CaptureWindow(h);

IntPtr result = ImageSearch(0, 0, 1920, 1080, imgPath, image);
string res = Marshal.PtrToStringAnsi(result);

if (res[0] == '0') return null;

string[] data = res.Split('|');

int x; int y;
int.TryParse(data[1], out x);
int.TryParse(data[2], out y);

return data;
}

И вызов все еще такой же, как указано выше:

coordinates = UseImageSearch(@"Main.PNG", "30");
if (coordinates != null)
{
LeftMouseClick(Convert.ToInt32(coordinates[1]), Convert.ToInt32(coordinates[2]));
}

Теперь пришло время выяснить фоновые щелчки мышью и фоновые клавиши отправки ...

Наслаждайтесь ботами в фоновом режиме!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...