diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..f34235a --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,60 @@ +# Hot Button Clicker - Architecture Overview + +This document provides a high-level overview of the technical architecture of the Hot Button Clicker application. It is intended for developers who want to understand how the application works internally. + +--- + +## Core Components + +The application is built around three main systems that work together to provide its functionality: + +1. **Hot Button Detection System** +2. **Idle Monitoring System** +3. **Cursor and Window Management System** + +Below is a detailed explanation of each component. + +--- + +### 1. Hot Button Detection System + +The core of the application is its ability to find and click predefined images on the screen. This system is responsible for the "hot button" functionality. + +- **Technology:** This system is primarily powered by AutoHotkey's `ImageSearch` command. +- **Process Flow:** + 1. **Image Definition:** The user captures a region of the screen using the "Add Hot Button" feature. This captured region is saved as a PNG image in the `hot_buttons/` directory. + 2. **Screen Scanning:** When monitoring is active, the `ScanForHotButtons` function iterates through each image file in the `HotButtons` array. + 3. **ImageSearch Execution:** For each image, `ImageSearch` scans the entire screen to find a matching region. + 4. **Shade Variation:** The `*n` (shade variation) option is used with `ImageSearch`. The `n` is a value from 0 to 255, controlled by the "Shade Variation" setting in the GUI. This allows for inexact matches, which is useful if the button's color or lighting changes slightly. A value of `*0` would require a pixel-perfect match. + 5. **Clicking:** If a match is found, the coordinates of the top-left corner of the image are returned. The application then calculates the center of the image (`FoundX + button.w/2`, `FoundY + button.h/2`) and programmatically clicks at that location. + +--- + +### 2. Idle Monitoring System + +To prevent the application from interfering with the user's work, it includes a system to detect user inactivity. + +- **Technology:** This system relies on AutoHotkey's built-in variable `A_TimeIdlePhysical`. +- **Process Flow:** + 1. **Idle Check:** At the beginning of each `ScanForHotButtons` cycle, the application checks the value of `A_TimeIdlePhysical`. This variable returns the number of milliseconds that have passed since the last physical keyboard or mouse input. + 2. **Pausing:** If the idle time is less than a set threshold (currently 30,000 ms), the application assumes the user is active. It then temporarily disables the main scanning timer (`SetTimer(ScanForHotButtons, "Off")`). + 3. **Resuming:** After pausing, a one-time, delayed timer is set using `SetTimer(EnableMonitoring, -10000)`. This timer calls the `EnableMonitoring` function after 10 seconds. + 4. **Re-activation:** The `EnableMonitoring` function checks if monitoring is still supposed to be active and, if so, re-enables the main `ScanForHotButtons` timer. This creates a loop where the application "sleeps" and wakes up to check for inactivity, ensuring it only runs when the user is away. + +--- + +### 3. Cursor and Window Management System + +To ensure that the automated clicks do not disrupt the user's current context, the application saves and restores the state of the mouse cursor and the active window. + +- **Technology:** This system uses AutoHotkey's `MouseGetPos`, `WinGetID`, `MouseMove`, and `WinActivate` commands. +- **Process Flow:** + 1. **State Saving:** Immediately before a click is performed on a found hot button, the application calls: + - `MouseGetPos(&origX, &origY)` to store the current X and Y coordinates of the mouse cursor. + - `WinGetID("A")` to get the unique ID of the currently active window. + 2. **Action Execution:** The application then moves the mouse to the center of the hot button and performs the click. + 3. **State Restoration:** Immediately after the click, the application: + - Calls `MouseMove(origX, origY)` to return the cursor to its original position. + - Calls `WinActivate("ahk_id " activeWin)` to re-activate the window that was active before the click. + +This ensures that the user's workflow is not interrupted, as the cursor and active window are restored to their original state almost instantly. \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..0b08982 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,121 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that are welcoming, inclusive, and +respectful. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interaction in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. + +[homepage]: https://www.contributor-covenant.org +[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3bbe883 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,84 @@ +# Contributing to Hot Button Clicker + +First off, thank you for considering contributing to Hot Button Clicker! Your help is greatly appreciated. This document provides a set of guidelines for contributing to the project. + +--- + +## Code of Conduct + +This project and everyone participating in it is governed by our [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior. + +--- + +## How Can I Contribute? + +There are many ways to contribute, from writing code and documentation to reporting bugs and suggesting new features. + +### Reporting Bugs + +If you find a bug, please ensure it hasn't already been reported by searching the open issues. If you can't find an existing issue, please open a new one. + +When filing a bug report, please include: + +- A clear and descriptive title. +- A detailed description of the problem, including steps to reproduce it. +- The version of AutoHotkey you are using. +- Any error messages you encountered. + +### Suggesting Enhancements + +If you have an idea for a new feature or an improvement to an existing one, please open an issue to discuss it. This allows us to coordinate our efforts and ensure the feature aligns with the project's goals. + +--- + +## Development Setup + +To get started with development, you'll need to have AutoHotkey v2 installed on your system. + +1. **Install AutoHotkey v2:** + - Download and install the latest version from the [official AutoHotkey website](https://www.autohotkey.com/v2/). + +2. **Fork the Repository:** + - Click the "Fork" button at the top right of this page to create your own copy of the repository. + +3. **Clone Your Fork:** + - Clone your forked repository to your local machine: + ```sh + git clone https://github.com/your-username/hot-button-click.git + cd hot-button-click + ``` + +4. **Run the Application:** + - You can run the application directly by executing `simple_ui.ahk` with AutoHotkey, or by using the provided `start.bat` script. + +--- + +## Pull Request Process + +1. **Create a New Branch:** + - Create a new branch for your changes: + ```sh + git checkout -b feature/your-feature-name + ``` + +2. **Make Your Changes:** + - Make your changes to the codebase. Ensure that your code follows the existing style and conventions. + - Add comments to any new functions or complex logic. + +3. **Commit Your Changes:** + - Commit your changes with a clear and descriptive commit message: + ```sh + git commit -m "Add: A brief description of your feature" + ``` + +4. **Push to Your Fork:** + - Push your changes to your forked repository: + ```sh + git push origin feature/your-feature-name + ``` + +5. **Submit a Pull Request:** + - Open a pull request from your forked repository to the main project repository. + - Provide a detailed description of the changes you've made and reference any related issues. + +Thank you for your contribution! \ No newline at end of file diff --git a/README.md b/README.md index 431a41b..5657590 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,110 @@ # Hot Button Clicker -## About +A simple AutoHotkey application to automate repetitive clicking tasks by identifying and clicking on-screen buttons from screenshots. -Hot Button Clicker is a simple AutoHotkey application that allows you to define "hot buttons" by taking screenshots of specific regions on your screen. The application can then monitor your screen and automatically click these buttons when they appear. This is useful for automating repetitive clicking tasks. +--- -## Requirements +## Table of Contents -- [AutoHotkey v2](httpshttps://www.autohotkey.com/v2/) must be installed on your system. +- [About The Project](#about-the-project) +- [Getting Started](#getting-started) + - [Prerequisites](#prerequisites) + - [Installation](#installation) +- [Usage](#usage) +- [How It Works](#how-it-works) +- [Contributing](#contributing) +- [License](#license) -## How to Use +--- -### Starting and Stopping the Application +## About The Project -- **To start the application:** Double-click on `start.bat`. This will launch the Hot Button Clicker GUI. -- **To stop the application:** Double-click on `stop.bat`. This will close the application. +Hot Button Clicker is a utility built with AutoHotkey v2 that allows users to automate clicks on specific UI elements. You can define these elements, or "hot buttons," by taking a screenshot of any region on your screen. -### Using the Application +The application then monitors the screen for these hot buttons to appear and automatically clicks them for you. It's designed to be "user-aware," meaning it will pause its monitoring if it detects that you are actively using the computer, preventing any interference with your work. -1. **Launch the application** using `start.bat`. -2. **Add a Hot Button:** - - Click the "Add Hot Button" button. The application window will hide. - - Click and drag your mouse to select a region of the screen you want to define as a button. - - Release the mouse button. A screenshot of the selected region will be saved in the `hot_buttons` folder, and the image path will be added to the list in the GUI. -3. **Start Monitoring:** - - Click the "Start Monitoring" button. The application will begin scanning the screen for any of the hot buttons you have added. - - The status bar will indicate that the application is "Monitoring...". - - If a hot button is found, the application will click on the center of it. - - To avoid interfering with your work, the monitoring will pause if you are actively using the computer. It will resume after a period of inactivity. -4. **Stop Monitoring:** - - Click the "Stop Monitoring" button to stop the screen scanning. -5. **Shade Variation:** - - The "Shade Variation" setting allows you to control how closely the image on the screen must match your hot button screenshot. A higher value allows for more variation in color and shading. The value can be between 0 and 255. +This tool is ideal for automating repetitive tasks in games, software testing, or any workflow that involves clicking the same buttons over and over. + +### Key Features + +- **Define Hot Buttons via Screenshots:** Easily capture any part of the screen to create a clickable hot button. +- **Automatic Clicking:** The application finds and clicks the hot buttons for you. +- **Idle Monitoring:** Smartly pauses when you are using your computer and resumes when you're idle. +- **Adjustable Match Tolerance:** Control the "shade variation" to find buttons even if their appearance changes slightly. +- **Simple GUI:** An intuitive interface to manage your hot buttons and control the monitoring process. + +--- + +## Getting Started + +Follow these simple steps to get the Hot Button Clicker up and running on your system. + +### Prerequisites + +You must have **AutoHotkey v2** installed. If you don't have it, you can download it from the official website: + +- [Download AutoHotkey v2](https://www.autohotkey.com/v2/) + +### Installation + +1. **Clone the repository or download the source code:** + ```sh + git clone https://github.com/your-username/hot-button-click.git + ``` +2. **Navigate to the project directory:** + ```sh + cd hot-button-click + ``` +3. That's it! No complex installation is required. + +--- + +## Usage + +### 1. Start the Application + +- Double-click `start.bat` to launch the application. The main GUI window will appear. + +### 2. Add a Hot Button + +- Click the **"Add Hot Button"** button. The application window will hide. +- Your cursor will change, indicating it's ready to capture. Click and drag your mouse to select the screen region you want to define as a hot button. +- Release the mouse. A screenshot of the selected area will be saved in the `hot_buttons/` folder, and its path will appear in the list view. + +### 3. Configure Shade Variation + +- The **"Shade Variation"** input allows you to control how strictly the application matches the hot button image. +- The value can range from `0` (exact match) to `255` (very loose match). A higher value can help find buttons that have slight variations in color or shading. The default is `10`. + +### 4. Start and Stop Monitoring + +- Click **"Start Monitoring"** to begin scanning the screen for your defined hot buttons. The status bar will update to "Monitoring...". +- If a hot button is found, the application will click it. +- The application will automatically pause if it detects mouse or keyboard activity and will resume after 30 seconds of inactivity. +- Click **"Stop Monitoring"** at any time to halt the process. + +### 5. Stop the Application + +- Double-click `stop.bat` to completely exit the application. + +--- + +## How It Works + +The application's logic is handled by `simple_ui.ahk` and relies on a few core concepts: + +- **Image Search:** It uses AutoHotkey's built-in `ImageSearch` command to scan the screen for the PNG images saved in the `hot_buttons/` directory. +- **Idle Time Monitoring:** It checks the `A_TimeIdlePhysical` built-in variable to determine if the user has been inactive. This prevents the script from interfering with the user's actions. +- **GDI+ Library:** The screenshot functionality is powered by the included `AHKv2_Screenshot_Tools.ahk` library, which provides advanced graphics and screen capture capabilities. + +--- + +## Contributing + +Contributions are welcome! Please read the `CONTRIBUTING.md` file for details on our code of conduct and the process for submitting pull requests. + +--- + +## License + +This project is licensed under the MIT License. See the `LICENSE.md` file for details. \ No newline at end of file diff --git a/lib/AHKv2_Screenshot_Tools.ahk b/lib/AHKv2_Screenshot_Tools.ahk index 7b8e8c4..66225ba 100644 --- a/lib/AHKv2_Screenshot_Tools.ahk +++ b/lib/AHKv2_Screenshot_Tools.ahk @@ -1,3 +1,11 @@ +; ====================================================================================================================== +; Library: AHKv2 GDI+ Screenshot Tools +; Description: A comprehensive GDI+ library for AutoHotkey v2, providing a wide range of functions for image +; manipulation, screen capturing, and drawing. This library is a general-purpose tool and is +; utilized by the Hot Button Clicker application for its screenshot and graphics functionalities. +; Version: 1.62 (as originally authored) +; ====================================================================================================================== + ; v1.62 ; ;############################################################################### @@ -53,8 +61,9 @@ ###### ; Function: UpdateLayeredWindow -; Description: Updates a layered window with the handle - to the DC of a gdi bitmap +; Description: Updates a layered window with the handle to the DC of a GDI bitmap. +; Note for Hot Button Clicker: Used to draw the semi-transparent selection rectangle on the screen +; when the user is adding a new hot button. ; ; hwnd Handle of the layered window to update ; hdc Handle to the DC of the GDI bitmap to up @@ -321,7 +330,9 @@ SetSysColorToControl(hwnd, SysColor:=15) ###### ; Function Gdip_BitmapFromScreen -; Description Gets a gdi+ bitmap from the screen +; Description Gets a GDI+ bitmap from a specified region of the screen. +; Note for Hot Button Clicker: This function is essential for capturing the user-selected region +; that defines a new hot button. ; ; Screen 0 = All screens ; Any numerical value = Just that @@ -1072,8 +1083,8 @@ ags, "ptr", str, "uint*", &length) ###### ; Function Gdip_DrawRectangle -; Description This function uses a pen to draw the outline of -a rectangle into the Graphics of a bitmap +; Description This function uses a pen to draw the outline of a rectangle into the Graphics of a bitmap. +; Note for Hot Button Clicker: This is the function that draws the red selection box on the screen overlay. ; ; pGraphics Pointer to the Graphics of a bitmap ; pPen Pointer to a pen @@ -1787,8 +1798,9 @@ Gdip_GraphicsFromImage(pBitmap) ###### ; Function Gdip_GraphicsFromHDC -; Description This function gets the graphics from the handle -to a device context +; Description This function gets the graphics from the handle to a device context. +; Note for Hot Button Clicker: Used to get a graphics context from the screen's Device Context (DC) +; so that the selection rectangle can be drawn on it. ; ; hdc This is the handle to the device context ; @@ -1916,8 +1928,8 @@ t) ###### ; Function: Gdip_SaveBitmapToFile -; Description: Saves a bitmap to a file in any supported format - onto disk +; Description: Saves a bitmap to a file in any supported format onto disk. +; Note for Hot Button Clicker: Used to save the captured hot button screenshot to the `hot_buttons` directory. ; ; pBitmap Pointer to a bitmap ; sOutput The name of the file that the bitmap wil @@ -2085,8 +2097,10 @@ Gdip_GetImageHeight(pBitmap) ;############################################################################### ###### -; Function Gdip_GetDimensions -; Description Gives the width and height of a bitmap +; Function Gdip_GetImageDimensions +; Description Gives the width and height of a bitmap. +; Note for Hot Button Clicker: Used to get the dimensions of a new hot button image, which is needed +; to calculate the center point for clicking. ; ; pBitmap Pointer to a bitmap ; Width ByRef variable. This variable will be se @@ -2558,6 +2572,13 @@ Gdip_CloneBitmapArea(pBitmap, x, y, w, h, Format:=0x26200A) ;############################################################################### ###### +/** + * Creates a GDI+ pen object with a specified color and width. + * Note for Hot Button Clicker: Used to create the red pen for drawing the selection rectangle. + * @param {Integer} ARGB The ARGB color value of the pen. + * @param {Float} w The width of the pen. + * @returns {UPtr} A pointer to the created pen object. + */ Gdip_CreatePen(ARGB, w) { DllCall("gdiplus\GdipCreatePen1", "UInt", ARGB, "Float", w, "Int", 2, "U @@ -2714,6 +2735,11 @@ Gdip_CloneBrush(pBrush) ;############################################################################### ###### +/** + * Deletes a GDI+ pen object, freeing its resources. + * @param {UPtr} pPen A pointer to the pen object to delete. + * @returns {Integer} Status enumeration result. + */ Gdip_DeletePen(pPen) { return DllCall("gdiplus\GdipDeletePen", "UPtr", pPen) @@ -2730,6 +2756,11 @@ Gdip_DeleteBrush(pBrush) ;############################################################################### ###### +/** + * Deletes a GDI+ bitmap object, freeing its resources. + * @param {UPtr} pBitmap A pointer to the bitmap object to delete. + * @returns {Integer} Status enumeration result. + */ Gdip_DisposeImage(pBitmap) { return DllCall("gdiplus\GdipDisposeImage", "UPtr", pBitmap) @@ -2738,6 +2769,11 @@ Gdip_DisposeImage(pBitmap) ;############################################################################### ###### +/** + * Deletes a GDI+ graphics object, freeing its resources. + * @param {UPtr} pGraphics A pointer to the graphics object to delete. + * @returns {Integer} Status enumeration result. + */ Gdip_DeleteGraphics(pGraphics) { return DllCall("gdiplus\GdipDeleteGraphics", "UPtr", pGraphics) @@ -3100,6 +3136,12 @@ Gdip_SetCompositingMode(pGraphics, CompositingMode:=0) ;############################################################################### ###### +/** + * Initializes the GDI+ library, returning a token that must be used to shut it down later. + * This function must be called before any other GDI+ operations are performed. + * Note for Hot Button Clicker: This is called once when the main script starts. + * @returns {UPtr} A token for the GDI+ session. + */ Gdip_Startup() { if (!DllCall("LoadLibrary", "str", "gdiplus", "UPtr")) { @@ -3120,6 +3162,12 @@ plus on your system") return pToken } +/** + * Shuts down the GDI+ library, releasing associated resources. + * Note for Hot Button Clicker: This is called when the GUI is closed. + * @param {UPtr} pToken The GDI+ session token returned by `Gdip_Startup`. + * @returns {Integer} 0 on success. + */ Gdip_Shutdown(pToken) { DllCall("gdiplus\GdipShutdown", "UPtr", pToken) @@ -3768,4 +3816,4 @@ WinGetRect( hwnd, &x:="", &y:="", &w:="", &h:="" ) { y := NumGet(winRect, 4, "UInt") w := NumGet(winRect, 8, "UInt") - x h := NumGet(winRect, 12, "UInt") - y -} +} \ No newline at end of file diff --git a/simple_ui.ahk b/simple_ui.ahk index a3f29cc..b633207 100644 --- a/simple_ui.ahk +++ b/simple_ui.ahk @@ -1,62 +1,88 @@ +; ====================================================================================================================== +; Title: Hot Button Clicker +; Description: An AutoHotkey v2 application that allows users to define "hot buttons" by screenshotting +; screen regions and then automatically clicking them when they appear. +; Author: Your Name +; Version: 1.0.0 +; Requires: AutoHotkey v2.0, GDI+ Library (included) +; ====================================================================================================================== + #Requires AutoHotkey v2.0 #Include ; --- Global Variables --- -global pToken := Gdip_Startup() -global HotButtons := [] -global isMonitoring := false -global shadeVariation := 10 -FileCreateDir("hot_buttons") +global pToken := Gdip_Startup() ; Initialize GDI+ library and store the token. +global HotButtons := [] ; Array to store hot button objects {path, w, h}. +global isMonitoring := false ; Flag to track if the application is currently scanning. +global shadeVariation := 10 ; Default shade variation for ImageSearch. +FileCreateDir("hot_buttons") ; Ensure the directory for storing button images exists. -; Create the GUI window +; --- GUI Definition --- +; Create the main application window. MyGui := Gui(, "Hot Button Clicker") MyGui.SetFont("s10", "Segoe UI") -; Add buttons +; Add control buttons. MyGui.Add("Button", "w120", "Add Hot Button").OnEvent("Click", AddHotButton) MyGui.Add("Button", "w120 yp x+10", "Start Monitoring").OnEvent("Click", StartMonitoring) MyGui.Add("Button", "w120 yp x+10", "Stop Monitoring").OnEvent("Click", StopMonitoring) -; Add a list view for hot buttons +; Add a list view to display the paths of captured hot buttons. global HotButtonList := MyGui.Add("ListView", "w380 r10", ["Image Path"]) -HotButtonList.ModifyCol(1, "AutoHdr") +HotButtonList.ModifyCol(1, "AutoHdr") ; Auto-size the column. -; Add shade variation option +; Add controls for adjusting the shade variation. MyGui.Add("Text",, "Shade Variation (0-255):") MyGui.Add("Edit", "w50 vshadeVariation", shadeVariation).OnEvent("Change", UpdateShadeVariation) -; Add a status bar +; Add a status bar to display application status. global MyStatusBar := MyGui.Add("StatusBar") MyStatusBar.SetText("Stopped") -; Show the GUI +; Show the GUI. MyGui.Show("w400") -; --- Event Handlers --- +; --- Functions and Event Handlers --- + +/** + * Updates the global `shadeVariation` variable when the user changes the value in the Edit control. + * @param {Gui.Edit} control The Edit control that triggered the event. + * @param {Any} info Additional information about the event. + */ UpdateShadeVariation(control, info) { global shadeVariation := control.Value } +/** + * Initiates the process of adding a new hot button. Hides the main GUI and prepares a full-screen overlay + * for region selection. + */ AddHotButton(*) { MyGui.Hide() MyStatusBar.SetText("Click and drag to select a region...") + ; Create a transparent, full-screen GUI for selection. global SelectionGui := Gui("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs") SelectionGui.Show("x0 y0 w" A_ScreenWidth " h" A_ScreenHeight, "NA") + ; Set up GDI+ resources for drawing the selection rectangle. global hbm := CreateDIBSection(A_ScreenWidth, A_ScreenHeight) global hdc := CreateCompatibleDC() global obm := SelectObject(hdc, hbm) global G := Gdip_GraphicsFromHDC(hdc) + global pPen := Gdip_CreatePen(0xFFFF0000, 2) ; Red pen for the rectangle. - global pPen := Gdip_CreatePen(0xFFFF0000, 2) - + ; Set up message handlers to capture mouse events. global startX, startY, endX, endY - OnMessage(0x201, WM_LBUTTONDOWN) - OnMessage(0x202, WM_LBUTTONUP) + OnMessage(0x201, WM_LBUTTONDOWN) ; WM_LBUTTONDOWN + OnMessage(0x202, WM_LBUTTONUP) ; WM_LBUTTONUP } +/** + * Message handler for when the left mouse button is pressed down during region selection. + * Records the starting coordinates and starts a timer to draw the selection rectangle. + */ WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) { if (hwnd = SelectionGui.Hwnd) { MouseGetPos(&startX, &startY) @@ -64,34 +90,43 @@ WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) { } } +/** + * Message handler for when the left mouse button is released, completing the region selection. + * It captures the selected screen area, saves it as an image, and adds it to the hot button list. + */ WM_LBUTTONUP(wParam, lParam, msg, hwnd) { if (hwnd = SelectionGui.Hwnd) { + ; Stop the drawing timer and unregister message handlers. SetTimer(UpdateSelection, "Off") OnMessage(0x201, "") OnMessage(0x202, "") MouseGetPos(&endX, &endY) + ; Clean up GDI+ resources. Gdip_DeletePen(pPen) SelectObject(hdc, obm) DeleteObject(hbm) DeleteDC(hdc) Gdip_DeleteGraphics(G) + ; Destroy the selection GUI. SelectionGui.Destroy() + ; Calculate the dimensions of the selected rectangle. x := Min(startX, endX) y := Min(startY, endY) w := Abs(startX - endX) h := Abs(startY - endY) + ; If the selection has a valid size, capture and save the image. if (w > 0 && h > 0) { pBitmap := Gdip_BitmapFromScreen(x "|" y "|" w "|" h) imagePath := "hot_buttons\" A_TickCount ".png" Gdip_SaveBitmapToFile(pBitmap, imagePath) + ; Store button info and update the GUI list. Gdip_GetImageDimensions(pBitmap, &imgW, &imgH) HotButtons.Push({path: imagePath, w: imgW, h: imgH}) - HotButtonList.Add(, imagePath) Gdip_DisposeImage(pBitmap) MyStatusBar.SetText("Button added.") @@ -99,14 +134,18 @@ WM_LBUTTONUP(wParam, lParam, msg, hwnd) { MyStatusBar.SetText("Invalid region selected.") } + ; Show the main GUI again. MyGui.Show() } } - +/** + * Timer function that continuously updates the selection rectangle on the screen as the user + * drags the mouse. + */ UpdateSelection() { MouseGetPos(&currX, &currY) - Gdip_GraphicsClear(G) + Gdip_GraphicsClear(G) ; Clear the previous rectangle. w := Abs(startX - currX) h := Abs(startY - currY) x := Min(startX, currX) @@ -115,52 +154,72 @@ UpdateSelection() { UpdateLayeredWindow(SelectionGui.Hwnd, hdc) } - +/** + * Starts the monitoring process. Sets the `isMonitoring` flag and starts a recurring timer + * that calls `ScanForHotButtons`. + */ StartMonitoring(*) { if (isMonitoring) { return } isMonitoring := true MyStatusBar.SetText("Monitoring...") - SetTimer(ScanForHotButtons, 1000) + SetTimer(ScanForHotButtons, 1000) ; Scan every 1 second. } +/** + * Stops the monitoring process. Clears the `isMonitoring` flag and disables the timer. + */ StopMonitoring(*) { isMonitoring := false MyStatusBar.SetText("Stopped") SetTimer(ScanForHotButtons, "Off") } +/** + * The core scanning function. It checks for user inactivity and then searches the screen for + * each defined hot button. If a button is found, it is clicked. + */ ScanForHotButtons() { if (!isMonitoring) { return } - if (A_TimeIdlePhysical < 30000) { + ; Pause monitoring if the user is active to avoid interference. + if (A_TimeIdlePhysical < 30000) { ; 30 seconds idle threshold. MyStatusBar.SetText("User active. Pausing for 10 seconds...") SetTimer(ScanForHotButtons, "Off") - SetTimer(EnableMonitoring, -10000) ; one-time timer + SetTimer(EnableMonitoring, -10000) ; Check again after 10 seconds. return } MyStatusBar.SetText("Scanning for hot buttons...") for button in HotButtons { + ; Search for the button image on the screen. ImageSearch(&FoundX, &FoundY, 0, 0, A_ScreenWidth, A_ScreenHeight, "*" shadeVariation " " button.path) + + ; If the image is found... if (FoundX != "") { + ; Save original mouse position and active window. MouseGetPos(&origX, &origY) activeWin := WinGetID("A") + ; Click in the center of the found button. Click(FoundX + button.w/2, FoundY + button.h/2) Sleep(100) + ; Restore original mouse position and activate the previous window. MouseMove(origX, origY) WinActivate("ahk_id " activeWin) - break + break ; Stop scanning after finding one button. } } MyStatusBar.SetText("Monitoring...") } +/** + * Re-enables the monitoring timer after it has been paused due to user activity. + */ EnableMonitoring() { if (isMonitoring) { MyStatusBar.SetText("Monitoring...") @@ -168,4 +227,7 @@ EnableMonitoring() { } } -MyGui.OnEvent("Close", (*) => Gdip_Shutdown(pToken) & ExitApp()) +/** + * Handles the GUI's close event. Shuts down the GDI+ library and exits the application. + */ +MyGui.OnEvent("Close", (*) => Gdip_Shutdown(pToken) & ExitApp()) \ No newline at end of file