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.
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
andmain.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
- Download the latest release from Releases
- Extract
Hover-Bug_v2.3.zip
- 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.