Hey folks!

I recently finished a fun little C++ project that simulates a butterfly flying around your desktop — but with a twist: it does so in a controlled environment for custom text input! Remember the DVD logo that people love when it touches the corner based on a fixed path, this one is unpredictable as its movement is random.


Demo

Give it a try by downloading the Github Release: Hover_Bug


🧠 What It Does:

  • Spawns a entered text that "hovers" on top of all windows.
  • Almost like a DVD logo that people love when it touches the corner.
  • Runs seamlessly on Windows — think of it like a lightweight desktop companion.

🔧 Tech Stack:

  • Language: C++
  • Framework: Win32 API for desktop-level rendering and layering
  • Executable Output: Hover_Bug.exe and main.exe
  • Release Build: Available under the release branch on GitHub — only 2.exe files.

📦 Use Case: (For fun only)

  • A desktop pet that displays motivational quotes or reminders.
  • A customizable visual toy to demonstrate Win32 overlay capabilities.

🛠️ Features

Dynamic Floating Text

  • Smooth movement patterns (3-7 sec per direction)
  • Starts centered on any screen

Eye-Catching Effects

  • 🌈 Smooth color fading (rainbow mode)
  • 🎯 Always-on-top display

Easy Control

  • Simple launcher for text updates
  • System tray friendly (low resource usage)

Additional:

  • The overlay doesn’t interfere with mouse events or system focus.
  • Controlling CPU usage by limiting it to only 1 instance.
  • Clean and minimal without background threads going wild.

👨‍💻 Code

main.cpp — Hover-Bug Launcher

This file creates a simple Windows GUI app using the Win32 API. It allows the user to input text and launch/stop a floating text overlay (Hover_Bug.exe).

FindHoverBugProcess — Finds if Hover_Bug.exe is already running

DWORD FindHoverBugProcess() {
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnap == INVALID_HANDLE_VALUE) return 0;

    PROCESSENTRY32 pe;
    pe.dwSize = sizeof(PROCESSENTRY32);

    if (Process32First(hSnap, &pe)) {
        do {
            if (_wcsicmp(pe.szExeFile, L"Hover_Bug.exe") == 0) {
                CloseHandle(hSnap);
                return pe.th32ProcessID;
            }
        } while (Process32Next(hSnap, &pe));
    }

    CloseHandle(hSnap);
    return 0;
}

Explanation:

  • Takes a snapshot of all running processes.
  • Loops through each using Process32First/Next.
  • Compares the process name (case-insensitive) with Hover_Bug.exe.
  • If found, returns its Process ID (PID).

✅ TerminateHoverBug — Kills Hover_Bug.exe if running

Copy code
void TerminateHoverBug() {
    DWORD pid = FindHoverBugProcess();
    if (pid) {
        HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
        if (hProcess) {
            TerminateProcess(hProcess, 0);
            CloseHandle(hProcess);
        }
    }
}

Explanation:

  • Calls FindHoverBugProcess() to check if it's running.
  • Opens the process with permission to terminate it.
  • Calls TerminateProcess().

✅ LaunchHoverBug — Starts Hover_Bug.exe with user text

Copy code
void LaunchHoverBug(const std::string& text) {
    TerminateHoverBug(); // Ensure only one instance

    std::string command = "Hover_Bug.exe \"" + text + "\"";
    STARTUPINFOA si = { sizeof(si) };
    PROCESS_INFORMATION pi;
    CreateProcessA(NULL, const_cast<LPSTR>(command.c_str()), NULL, NULL, FALSE,
                   CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

Explanation:

  • Terminates any existing instance.
  • Creates the command: Hover_Bug.exe "user text".
  • Uses CreateProcessA() to launch it silently (CREATE_NO_WINDOW).

✅ WindowProc — Main GUI Event Handler

Copy code
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    static HWND hEdit, hStartButton, hStopButton;

    switch (uMsg) {
    case WM_CREATE:
        CreateWindow("STATIC", "Enter text:", WS_VISIBLE | WS_CHILD,
                     20, 20, 80, 20, hwnd, (HMENU)ID_LABEL, NULL, NULL);

        hEdit = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER,
                             110, 20, 250, 20, hwnd, (HMENU)ID_EDIT, NULL, NULL);

        hStartButton = CreateWindow("BUTTON", "Start", WS_VISIBLE | WS_CHILD,
                                    110, 60, 100, 30, hwnd, (HMENU)ID_START_BUTTON, NULL, NULL);

        hStopButton = CreateWindow("BUTTON", "Stop", WS_VISIBLE | WS_CHILD,
                                   220, 60, 100, 30, hwnd, (HMENU)ID_STOP_BUTTON, NULL, NULL);
        break;

    case WM_COMMAND:
        if (LOWORD(wParam) == ID_START_BUTTON) {
            char buffer[256];
            GetWindowTextA(hEdit, buffer, 256);
            std::string text(buffer);
            if (!text.empty()) {
                LaunchHoverBug(text);
            } else {
                MessageBox(hwnd, "Please enter text.", "Error", MB_OK | MB_ICONERROR);
            }
        }
        else if (LOWORD(wParam) == ID_STOP_BUTTON) {
            TerminateHoverBug();
        }
        break;

    case WM_DESTROY:
        TerminateHoverBug(); // Clean up
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }

    return 0;
}

Explanation:

  • On WM_CREATE: Creates input field and Start/Stop buttons.
  • On WM_COMMAND: If Start is clicked, gets input and calls LaunchHoverBug. If Stop is clicked, terminates.

- On WM_DESTROY: Kills Hover_Bug before quitting.

✅ WinMain — Entry Point

Copy code
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
    const char CLASS_NAME[] = "HoverBugLauncher";

    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(
        0, CLASS_NAME, "Hover-Bug Launcher",
        WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ WS_MAXIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT, 400, 150,
        NULL, NULL, hInstance, NULL
    );

    if (!hwnd) return 0;

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

Explanation:

  • Defines and registers a window class.
  • Creates the main window.
  • Shows it and enters the message loop to handle UI events.

hover_bug.cpp — Floating Overlay Window (Full Explanation)

This file creates a transparent, always-on-top, click-through window that displays floating text passed via command-line arguments. It uses the GDI+ library to draw smooth text with a blur/glow effect.


✅ Globals and Setup

#pragma comment(lib, "gdiplus.lib")

#include 
#include 
#include 

using namespace Gdiplus;

ULONG_PTR gdiplusToken;
std::wstring g_text;

Explanation:

  • Links gdiplus.lib to use GDI+ for graphics.
  • Declares g_text to hold the overlay text.
  • gdiplusToken manages the GDI+ session.

✅ DrawTextWithBlur — Draws Text with Shadow/Glow

Copy code
void DrawTextWithBlur(HDC hdc, const std::wstring& text, RECT rect) {
    Graphics graphics(hdc);
    graphics.SetSmoothingMode(SmoothingModeAntiAlias);
    graphics.SetTextRenderingHint(TextRenderingHintClearTypeGridFit);

    FontFamily fontFamily(L"Segoe UI");
    Font font(&fontFamily, 36, FontStyleBold, UnitPixel);
    PointF origin(rect.left, rect.top);

    SolidBrush shadowBrush(Color(128, 0, 0, 0)); // semi-transparent black
    for (int dx = -2; dx <= 2; ++dx) {
        for (int dy = -2; dy <= 2; ++dy) {
            PointF shadowOrigin(origin.X + dx, origin.Y + dy);
            graphics.DrawString(text.c_str(), -1, &font, shadowOrigin, &shadowBrush);
        }
    }

    SolidBrush textBrush(Color(255, 255, 255, 255)); // white text
    graphics.DrawString(text.c_str(), -1, &font, &origin, &textBrush);
}

Explanation:

  • Uses GDI+ to draw high-quality text.
  • First, it draws shadows by looping through offsets.
  • Then, it draws solid white text on top.

- Creates a blur/glow effect using offset rendering.

✅ WindowProc — Message Handler for Overlay Window

Copy code
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        RECT rect;
        GetClientRect(hwnd, &rect);
        DrawTextWithBlur(hdc, g_text, rect);
        EndPaint(hwnd, &ps);
        return 0;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

Explanation:

  • On WM_PAINT, it draws the blurred text inside the window.
  • On WM_DESTROY, posts quit message.
  • Default handling for other messages.

✅ wWinMain — Entry Point for the Hover Bug Overlay

Copy code
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int) {
    GdiplusStartupInput gdiplusStartupInput;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    g_text = pCmdLine;

Explanation:

  • Starts GDI+ graphics session.
  • Retrieves the overlay text passed via command line (from main.cpp).

✅ Register Window Class

Copy code
    const wchar_t CLASS_NAME[] = L"HoverBugWindowClass";
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

    RegisterClass(&wc);

Explanation:

  • Defines the look and behavior of the overlay window.
  • Sets background to black (for blending).
  • Uses the earlier WindowProc.

✅ Create Transparent, Click-through Window

Copy code
    HWND hwnd = CreateWindowEx(
        WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
        CLASS_NAME, L"Hover Bug",
        WS_POPUP,
        100, 100, 800, 200,
        NULL, NULL, hInstance, NULL
    );

Explanation:

  • WS_EX_LAYERED: Allows transparency.
  • WS_EX_TRANSPARENT: Mouse click passes through it.
  • WS_EX_TOPMOST: Always on top.
  • WS_EX_TOOLWINDOW: Hides from taskbar.
  • WS_POPUP: No border/titlebar.

✅ Set Layered Transparency & Show Window

Copy code
    SetLayeredWindowAttributes(hwnd, 0, 255, LWA_ALPHA);
    ShowWindow(hwnd, SW_SHOW);

Explanation:

  • Makes the window fully visible (alpha = 255), still layered for potential opacity.
  • Shows the window after creation.

✅ Message Loop

Copy code
    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    GdiplusShutdown(gdiplusToken);
    return 0;
}

Explanation:

  • Runs standard Win32 message loop.
  • Cleans up GDI+ before exit.

📥 Installation

  1. Download the latest release from Releases
  2. Extract Hover-Bug_v2.3.zip
  3. Run main.exe

No admin rights required!


🖥️ Usage

Basic Controls

Type your text in the launcher

Click "Start" to launch floating text

Use "Stop" to remove it

Advanced Options

  • Command Line:
Hover_Bug.exe "Your Text Here"

🛠️ Building from Source

Requires:

  • MinGW/GCC (Windows)
  • Win32 API development headers
g++ -std=c++11 -O2 -mwindows hover_bug.cpp -o Hover_Bug.exe -static -lgdi32 -lwinmm
g++ main.cpp -o main.exe -mwindows

📎 GitHub:

🔗 Repo
⬇️ Release v2.3.2

If you're into desktop UI tweaks, C++ visual projects, or just need some zen in your workspace, check it out!

Feedback and suggestions are all welcome. BTW i will be adding a Input for desired image over the text to make it more cool.