Untitled

 avatar
unknown
c_cpp
a year ago
4.7 kB
15
Indexable
#include <windows.h>
#include <atomic>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
#include <chrono>

// Define the target color (RGB values)
const int target_red = 255;
const int target_green = 102;
const int target_blue = 102;

// Define the maximum number of threads
#define MAX_THREADS 4

// Define the screen dimensions
const int screen_width = 2560;
const int screen_height = 1600;

// Structure to hold potential click locations and color information
struct ClickCandidate {
    int x;
    int y;
    bool valid; // Indicates if a candidate was found
    std::atomic<bool> found; // Atomic flag to avoid race conditions
};

// Mutex for thread-safe access to the best candidate
std::mutex click_mutex;

// Function to check if colors are similar
bool isColorSimilar(const COLORREF& color, int threshold) {
    int red_diff = abs(GetRValue(color) - target_red);
    int green_diff = abs(GetGValue(color) - target_green);
    int blue_diff = abs(GetBValue(color) - target_blue);
    return (red_diff + green_diff + blue_diff) <= threshold;
}

// Function to capture a screenshot of a specific area and scan for the target color
ClickCandidate captureAndScanArea(HDC hdc_screen, int x_start, int y_start, int width, int height, int threshold) {
    ClickCandidate best_candidate;
    best_candidate.x = -1;
    best_candidate.y = -1;
    best_candidate.valid = false;
    best_candidate.found.store(false);

    // Error handling: check if DC is obtained successfully
    if (!hdc_screen) {
        std::cerr << "Error: Failed to obtain screen DC." << std::endl;
        return best_candidate;
    }

    // Efficiently store pixel data in a vector
    std::vector<COLORREF> pixels(width * height);
    if (BitBlt(NULL, 0, 0, width, height, hdc_screen, x_start, y_start, SRCCOPY) == 0) {
        std::cerr << "Error: Failed to capture screenshot." << std::endl;
        ReleaseDC(NULL, hdc_screen);
        return best_candidate;
    }

    // Loop through each pixel and find the best candidate
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            COLORREF color = pixels[y * width + x];
            if (isColorSimilar(color, threshold)) {
                click_mutex.lock();
                if (!best_candidate.valid || y > best_candidate.y) {
                    best_candidate.x = x_start + x;
                    best_candidate.y = y_start + y;
                    best_candidate.valid = true;
                    best_candidate.found.store(true);
                }
                click_mutex.unlock();
            }
        }
    }

    // Release resources
    ReleaseDC(NULL, hdc_screen);

    return best_candidate;
}

// Function to perform a left mouse click at a specific location
void performClick(int x, int y) {
    // Move mouse cursor to the target position
    SetCursorPos(x, y);
    // Simulate a left mouse button click
    mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, x, y, 0, 0);
}

// Function to continuously scan the screen for the target color
void scanScreen() {
    while (true) {
        HDC hdc_screen = GetDC(NULL);
        if (!hdc_screen) {
            std::cerr << "Error: Failed to obtain screen DC." << std::endl;
            return;
        }
        ClickCandidate candidate = captureAndScanArea(hdc_screen, 0, 0, screen_width, screen_height, 25); // Change the threshold here
        ReleaseDC(NULL, hdc_screen);
        if (candidate.valid) {
            performClick(candidate.x, candidate.y);
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 150)); // Adjust scan rate here
    }
}

int main() {
    // Start multiple threads for scanning
    std::vector<std::thread> threads;
    const int num_threads = std::min(MAX_THREADS, std::thread::hardware_concurrency());

    // Divide the screen into segments for each thread
    const int segment_height = screen_height / num_threads;

    for (int i = 0; i < num_threads; ++i) {
        int segment_y_start = i * segment_height;
        int segment_y_end = (i + 1) * segment_height;

        // The last thread may cover the remaining area
        if (i == num_threads - 1) {
            segment_y_end = screen_height;
        }

        // Start a thread to scan its segment of the screen
        threads.emplace_back([segment_y_start, segment_y_end]() {
            while (true) {
                HDC hdc_screen = GetDC(NULL);
                if (!hdc_screen) {
                    std::cerr << "Error: Failed to obtain screen DC." << std::endl;
                    return;
                }

                ClickCandidate candidate = captureAndScanArea(hdc_screen, 0, segment_y_start, screen_width, segment_y_end -
Leave a Comment