#ifndef UNICODE #define UNICODE #endif #ifndef _UN...
تم الإنشاء في: ١٣ مايو ٢٠٢٦
تمت الإجابة باستخدام GPT-5.5 Thinking بواسطة Chat01
تم الإنشاء في: ١٣ مايو ٢٠٢٦
تمت الإجابة باستخدام GPT-5.5 Thinking بواسطة Chat01
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <shellapi.h>
#include <mmsystem.h>
#include <thread>
#include <atomic>
#include <vector>
#include <string>
#include <sstream>
#include <mutex>
#include <algorithm>
#include <cwchar>
#include <cstdint>
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Winmm.lib")
// =====================================================
// Settings
// =====================================================
static constexpr int APP_W = 1020;
static constexpr int APP_H = 760;
static constexpr COLORREF CLR_BG = RGB(8, 8, 10);
static constexpr COLORREF CLR_PANEL = RGB(14, 14, 17);
static constexpr COLORREF CLR_PANEL_2 = RGB(21, 21, 25);
static constexpr COLORREF CLR_BORDER = RGB(120, 0, 15);
static constexpr COLORREF CLR_ACCENT = RGB(235, 25, 40);
static constexpr COLORREF CLR_ACCENT_2 = RGB(165, 15, 25);
static constexpr COLORREF CLR_TEXT = RGB(235, 235, 235);
static constexpr COLORREF CLR_MUTED = RGB(165, 165, 165);
static constexpr unsigned long long MAX_CPS = 10000042ULL;
// Layout
static constexpr int CPS_Y_WINDOWS = 616;
static constexpr int CPS_Y_SCREEN = 196;
static constexpr int VIRTUAL_Y_WINDOWS = 694;
static constexpr int VIRTUAL_Y_SCREEN = 274;
// =====================================================
// Globals
// =====================================================
struct WindowItem {
HWND hwnd;
std::wstring title;
HICON icon;
};
enum class ClickMode {
Windows,
Screen
};
std::vector<WindowItem> g_windowList;
std::vector<HWND> g_selectedWindows;
std::mutex g_windowsMutex;
std::atomic<bool> g_clicking(false);
std::atomic<unsigned long long> g_cps(42);
std::atomic<bool> g_useVirtualMouse(false);
std::atomic<long> g_virtualX(0);
std::atomic<long> g_virtualY(0);
std::atomic<int> g_mode((int)ClickMode::Windows);
HWND g_mainHwnd = nullptr;
HFONT g_font = nullptr;
HFONT g_fontBold = nullptr;
HFONT g_fontTitle = nullptr;
HFONT g_fontMenu = nullptr;
HFONT g_fontEdit = nullptr;
HBRUSH g_brBg = nullptr;
HBRUSH g_brPanel = nullptr;
HBRUSH g_brEdit = nullptr;
HIMAGELIST g_imgList = nullptr;
// =====================================================
// UI
// =====================================================
HWND hBtnRefresh = nullptr;
HWND hBtnApplyWindows = nullptr;
HWND hStaticApplied = nullptr;
HWND hListView = nullptr;
HWND hEditCPS = nullptr;
HWND hBtnApplyCPS = nullptr;
HWND hStaticCPS = nullptr;
HWND hChkVirtual = nullptr;
HWND hLblVirtual = nullptr;
HWND hStaticHint = nullptr;
HWND hTabWindows = nullptr;
HWND hTabScreen = nullptr;
HWND hBtnMin = nullptr;
HWND hBtnMax = nullptr;
HWND hBtnClose = nullptr;
// =====================================================
// IDs
// =====================================================
enum {
ID_BTN_REFRESH = 101,
ID_LISTVIEW = 102,
ID_EDIT_CPS = 103,
ID_BTN_APPLY_CPS = 104,
ID_STATIC_CPS = 105,
ID_CHK_VIRTUAL = 106,
ID_BTN_APPLY_WINDOWS = 107,
ID_HOTKEY_F6 = 108,
ID_STATIC_APPLIED = 109,
textID_TAB_WINDOWS = 120, ID_TAB_SCREEN = 121, ID_BTN_MIN = 201, ID_BTN_MAX = 202, ID_BTN_CLOSE = 203
};
// =====================================================
// Prototypes
// =====================================================
void RefreshWindowList();
void UpdateSelectedWindows();
void ClickLoop();
void SetVirtualMouseFromCursor();
void UpdateCpsText();
void UpdateAppliedText();
void UpdateModeUi();
static inline POINT GetVirtualPoint()
{
return POINT{ g_virtualX.load(), g_virtualY.load() };
}
static inline unsigned long long ClampUll(unsigned long long v, unsigned long long lo, unsigned long long hi)
{
return std::min(std::max(v, lo), hi);
}
// =====================================================
// GDI helpers
// =====================================================
void FillRound(HDC hdc, RECT rc, COLORREF fill, COLORREF border, int radius)
{
HBRUSH br = CreateSolidBrush(fill);
HPEN pen = CreatePen(PS_SOLID, 1, border);
textHGDIOBJ oldBr = SelectObject(hdc, br); HGDIOBJ oldPen = SelectObject(hdc, pen); RoundRect(hdc, rc.left, rc.top, rc.right, rc.bottom, radius, radius); SelectObject(hdc, oldBr); SelectObject(hdc, oldPen); DeleteObject(br); DeleteObject(pen);
}
void DrawTitleLogo(HDC hdc)
{
HPEN redPen = CreatePen(PS_SOLID, 3, CLR_ACCENT);
HGDIOBJ oldPen = SelectObject(hdc, redPen);
HGDIOBJ oldBr = SelectObject(hdc, GetStockObject(NULL_BRUSH));
textEllipse(hdc, 28, 24, 64, 60); Ellipse(hdc, 38, 34, 54, 50); MoveToEx(hdc, 46, 42, nullptr); LineTo(hdc, 70, 66); SelectObject(hdc, oldBr); SelectObject(hdc, oldPen); DeleteObject(redPen); SetBkMode(hdc, TRANSPARENT); HFONT oldFont = (HFONT)SelectObject(hdc, g_fontTitle); SetTextColor(hdc, CLR_ACCENT); TextOutW(hdc, 84, 27, L"Red", 3); SetTextColor(hdc, CLR_TEXT); TextOutW(hdc, 130, 27, L"Clicer", 6); SelectObject(hdc, oldFont);
}
void DrawWindowChrome(HDC hdc)
{
RECT full{ 0, 0, APP_W, APP_H };
HBRUSH bg = CreateSolidBrush(CLR_BG);
FillRect(hdc, &full, bg);
DeleteObject(bg);
textRECT outer{ 0, 0, APP_W, APP_H }; FillRound(hdc, outer, CLR_BG, CLR_BORDER, 18); RECT topLine{ 0, 74, APP_W, 75 }; HBRUSH brLine = CreateSolidBrush(RGB(40, 20, 23)); FillRect(hdc, &topLine, brLine); DeleteObject(brLine); DrawTitleLogo(hdc); RECT modePanel{ 28, 90, 988, 164 }; FillRound(hdc, modePanel, CLR_PANEL, RGB(45, 45, 50), 8); ClickMode mode = (ClickMode)g_mode.load(); bool windowsMode = mode == ClickMode::Windows; SetBkMode(hdc, TRANSPARENT); HFONT oldFont = (HFONT)SelectObject(hdc, g_fontBold); if (windowsMode) { RECT appliedPanel{ 28, 180, 988, 230 }; FillRound(hdc, appliedPanel, CLR_PANEL, RGB(45, 45, 50), 8); RECT listPanel{ 28, 244, 988, 588 }; FillRound(hdc, listPanel, CLR_BG, CLR_BORDER, 8); SetTextColor(hdc, CLR_ACCENT); TextOutW(hdc, 50, 260, L"Список окон", 11); RECT cpsPanel{ 28, 604, 988, 734 }; FillRound(hdc, cpsPanel, CLR_PANEL, RGB(45, 45, 50), 8); } else { RECT cpsPanel{ 28, 180, 988, 330 }; FillRound(hdc, cpsPanel, CLR_PANEL, RGB(45, 45, 50), 8); SetTextColor(hdc, CLR_ACCENT); TextOutW(hdc, 50, 182, L"Настройки кликов", 16); } SelectObject(hdc, oldFont);
}
// =====================================================
// Owner-draw buttons
// =====================================================
void DrawOwnerButton(const DRAWITEMSTRUCT* dis)
{
HDC hdc = dis->hDC;
RECT rc = dis->rcItem;
UINT id = dis->CtlID;
textbool pressed = (dis->itemState & ODS_SELECTED) != 0; bool hot = (dis->itemState & ODS_HOTLIGHT) != 0; COLORREF fill = CLR_PANEL_2; COLORREF border = RGB(55, 55, 60); COLORREF text = CLR_TEXT; HFONT font = g_fontBold; if (id == ID_TAB_WINDOWS || id == ID_TAB_SCREEN) { ClickMode mode = (ClickMode)g_mode.load(); bool active = (id == ID_TAB_WINDOWS && mode == ClickMode::Windows) || (id == ID_TAB_SCREEN && mode == ClickMode::Screen); fill = active ? CLR_ACCENT : (hot ? RGB(30, 30, 36) : CLR_PANEL_2); border = active ? RGB(255, 65, 78) : RGB(60, 60, 66); text = active ? RGB(255, 255, 255) : CLR_MUTED; font = g_fontMenu; } if (id == ID_BTN_APPLY_WINDOWS || id == ID_BTN_APPLY_CPS) { fill = pressed ? CLR_ACCENT_2 : CLR_ACCENT; border = RGB(255, 60, 75); text = RGB(255, 255, 255); } if (id == ID_BTN_CLOSE) { fill = pressed ? RGB(130, 15, 25) : CLR_BG; border = CLR_BG; text = CLR_TEXT; } if (id == ID_BTN_MIN || id == ID_BTN_MAX) { fill = CLR_BG; border = CLR_BG; text = CLR_TEXT; } if (hot && id != ID_BTN_APPLY_WINDOWS && id != ID_BTN_APPLY_CPS && id != ID_BTN_CLOSE && id != ID_BTN_MIN && id != ID_BTN_MAX && id != ID_TAB_WINDOWS && id != ID_TAB_SCREEN) { fill = RGB(26, 26, 31); } FillRound(hdc, rc, fill, border, 10); wchar_t textBuf[128]{}; GetWindowTextW(dis->hwndItem, textBuf, 128); SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, text); HFONT oldFont = (HFONT)SelectObject(hdc, font); DrawTextW(hdc, textBuf, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); SelectObject(hdc, oldFont);
}
// =====================================================
// Window icons
// =====================================================
HICON GetWindowSmallIcon(HWND hwnd)
{
HICON icon = (HICON)SendMessageW(hwnd, WM_GETICON, ICON_SMALL2, 0);
if (!icon)
icon = (HICON)SendMessageW(hwnd, WM_GETICON, ICON_SMALL, 0);
if (!icon)
icon = (HICON)SendMessageW(hwnd, WM_GETICON, ICON_BIG, 0);
textif (!icon) { LONG_PTR clsIcon = GetClassLongPtrW(hwnd, GCLP_HICONSM); if (clsIcon) icon = (HICON)clsIcon; } if (!icon) { LONG_PTR clsIcon = GetClassLongPtrW(hwnd, GCLP_HICON); if (clsIcon) icon = (HICON)clsIcon; } if (!icon) icon = LoadIconW(nullptr, IDI_APPLICATION); return icon;
}
// =====================================================
// Window enum
// =====================================================
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM)
{
if (!IsWindowVisible(hwnd))
return TRUE;
textif (hwnd == g_mainHwnd) return TRUE; wchar_t title[512]{}; GetWindowTextW(hwnd, title, 512); if (wcslen(title) == 0) return TRUE; LONG_PTR exStyle = GetWindowLongPtrW(hwnd, GWL_EXSTYLE); if (exStyle & WS_EX_TOOLWINDOW) return TRUE; g_windowList.push_back(WindowItem{ hwnd, title, GetWindowSmallIcon(hwnd) }); return TRUE;
}
void RefreshWindowList()
{
g_windowList.clear();
EnumWindows(EnumWindowsProc, 0);
textstd::sort(g_windowList.begin(), g_windowList.end(), [](const WindowItem& a, const WindowItem& b) { return a.title < b.title; }); ListView_DeleteAllItems(hListView); if (g_imgList) { ImageList_Destroy(g_imgList); g_imgList = nullptr; } g_imgList = ImageList_Create(24, 24, ILC_COLOR32 | ILC_MASK, 16, 16); ListView_SetImageList(hListView, g_imgList, LVSIL_SMALL); LVCOLUMNW col{}; col.mask = LVCF_TEXT | LVCF_WIDTH; col.pszText = const_cast<LPWSTR>(L"Окна"); col.cx = 850; if (Header_GetItemCount(ListView_GetHeader(hListView)) == 0) ListView_InsertColumn(hListView, 0, &col); else ListView_SetColumn(hListView, 0, &col); for (int i = 0; i < (int)g_windowList.size(); ++i) { int img = ImageList_AddIcon(g_imgList, g_windowList[i].icon); LVITEMW item{}; item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; item.iItem = i; item.iSubItem = 0; item.pszText = const_cast<LPWSTR>(g_windowList[i].title.c_str()); item.lParam = reinterpret_cast<LPARAM>(g_windowList[i].hwnd); item.iImage = img; ListView_InsertItem(hListView, &item); } { std::lock_guard<std::mutex> lock(g_windowsMutex); g_selectedWindows.clear(); } UpdateAppliedText();
}
void UpdateAppliedText()
{
size_t count = 0;
text{ std::lock_guard<std::mutex> lock(g_windowsMutex); count = g_selectedWindows.size(); } std::wstringstream ss; ss << L"Выбрано окон: " << count; SetWindowTextW(hStaticApplied, ss.str().c_str());
}
void UpdateSelectedWindows()
{
std::vector<HWND> picked;
textint count = ListView_GetItemCount(hListView); for (int i = 0; i < count; ++i) { UINT state = ListView_GetItemState(hListView, i, LVIS_STATEIMAGEMASK); if (state == INDEXTOSTATEIMAGEMASK(2)) { LVITEMW item{}; item.mask = LVIF_PARAM; item.iItem = i; if (ListView_GetItem(hListView, &item)) { HWND hwnd = reinterpret_cast<HWND>(item.lParam); if (IsWindow(hwnd)) picked.push_back(hwnd); } } } { std::lock_guard<std::mutex> lock(g_windowsMutex); g_selectedWindows = picked; } UpdateAppliedText();
}
// =====================================================
// CPS
// =====================================================
void UpdateCpsText()
{
std::wstringstream ss;
ss << L"КПС: " << g_cps.load();
SetWindowTextW(hStaticCPS, ss.str().c_str());
}
void ApplyCpsFromEdit()
{
wchar_t buf[64]{};
GetWindowTextW(hEditCPS, buf, 64);
textunsigned long long value = _wcstoui64(buf, nullptr, 10); if (value < 1) value = 1; if (value > MAX_CPS) value = MAX_CPS; g_cps.store(value); std::wstringstream ss; ss << value; SetWindowTextW(hEditCPS, ss.str().c_str()); UpdateCpsText();
}
// =====================================================
// Clicks
// =====================================================
void SendGlobalClickBatch(unsigned long long clicks)
{
const unsigned long long MAX_BATCH = 4096;
textwhile (clicks > 0) { unsigned long long batch64 = std::min(clicks, MAX_BATCH); int batch = (int)batch64; std::vector<INPUT> inputs(batch * 2); for (int i = 0; i < batch; ++i) { inputs[i * 2].type = INPUT_MOUSE; inputs[i * 2].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; inputs[i * 2 + 1].type = INPUT_MOUSE; inputs[i * 2 + 1].mi.dwFlags = MOUSEEVENTF_LEFTUP; } SendInput((UINT)inputs.size(), inputs.data(), sizeof(INPUT)); clicks -= batch64; }
}
void SendVirtualClickBatch(POINT p, unsigned long long clicks)
{
const unsigned long long MAX_BATCH = 4096;
textint screenW = GetSystemMetrics(SM_CXSCREEN); int screenH = GetSystemMetrics(SM_CYSCREEN); if (screenW <= 1 || screenH <= 1) return; LONG xAbs = (LONG)((double)p.x * 65535.0 / (screenW - 1)); LONG yAbs = (LONG)((double)p.y * 65535.0 / (screenH - 1)); while (clicks > 0) { unsigned long long batch64 = std::min(clicks, MAX_BATCH); int batch = (int)batch64; std::vector<INPUT> inputs(1 + batch * 2); inputs[0].type = INPUT_MOUSE; inputs[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; inputs[0].mi.dx = xAbs; inputs[0].mi.dy = yAbs; for (int i = 0; i < batch; ++i) { inputs[1 + i * 2].type = INPUT_MOUSE; inputs[1 + i * 2].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; inputs[1 + i * 2 + 1].type = INPUT_MOUSE; inputs[1 + i * 2 + 1].mi.dwFlags = MOUSEEVENTF_LEFTUP; } SendInput((UINT)inputs.size(), inputs.data(), sizeof(INPUT)); clicks -= batch64; }
}
LPARAM MakeMouseLParam(POINT clientPoint)
{
return MAKELPARAM((SHORT)clientPoint.x, (SHORT)clientPoint.y);
}
void PostWindowClick(HWND hwnd, POINT screenPoint)
{
if (!IsWindow(hwnd))
return;
textPOINT clientPoint = screenPoint; ScreenToClient(hwnd, &clientPoint); LPARAM lp = MakeMouseLParam(clientPoint); PostMessageW(hwnd, WM_MOUSEMOVE, 0, lp); PostMessageW(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, lp); PostMessageW(hwnd, WM_LBUTTONUP, 0, lp);
}
void DoClickBurst(unsigned long long amount)
{
if (amount == 0)
return;
textClickMode mode = (ClickMode)g_mode.load(); bool virtualMode = g_useVirtualMouse.load(); POINT realPos{}; GetCursorPos(&realPos); POINT virtualPos = GetVirtualPoint(); POINT effectivePos = virtualMode ? virtualPos : realPos; if (mode == ClickMode::Screen) { if (virtualMode) SendVirtualClickBatch(effectivePos, amount); else SendGlobalClickBatch(amount); return; } std::vector<HWND> targets; { std::lock_guard<std::mutex> lock(g_windowsMutex); targets = g_selectedWindows; } if (targets.empty()) return; for (unsigned long long i = 0; i < amount; ++i) { for (HWND hwnd : targets) { PostWindowClick(hwnd, effectivePos); } }
}
void WaitBeforeNextClick(unsigned long long cps, long double accumulator, unsigned long long preferredBatch, int& idleSpins)
{
if (cps < 1)
cps = 1;
textlong double need = (long double)preferredBatch - accumulator; if (need < 1.0L) need = 1.0L; long double secondsToBatch = need / (long double)cps; if (secondsToBatch > 0.0025L) { Sleep(1); idleSpins = 0; } else { if (++idleSpins < 300) { YieldProcessor(); } else { Sleep(0); idleSpins = 0; } }
}
void ClickLoop()
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
timeBeginPeriod(1);
textLARGE_INTEGER freq{}; LARGE_INTEGER last{}; LARGE_INTEGER now{}; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&last); long double accumulator = 0.0L; int idleSpins = 0; unsigned long long lastCps = g_cps.load(std::memory_order_relaxed); while (g_clicking.load(std::memory_order_relaxed)) { QueryPerformanceCounter(&now); long double elapsed = (long double)(now.QuadPart - last.QuadPart) / (long double)freq.QuadPart; last = now; // Не даём старому лагу копиться и потом выдавать лишний большой залп. if (elapsed > 0.10L) elapsed = 0.10L; unsigned long long localCps = g_cps.load(std::memory_order_relaxed); if (localCps < 1) localCps = 1; // При смене КПС сбрасываем остаток, чтобы старый темп не давал скачок. if (localCps != lastCps) { accumulator = 0.0L; lastCps = localCps; } accumulator += elapsed * (long double)localCps; // До 30к КПС делаем маленькие ровные пачки примерно на 1 мс. // Так меньше разброс: 3000 не должен превращаться в 8000 на тестерах CPS. unsigned long long preferredBatch = ClampUll(localCps / 1000ULL, 1ULL, 30ULL); if (accumulator < (long double)preferredBatch) { WaitBeforeNextClick(localCps, accumulator, preferredBatch, idleSpins); continue; } unsigned long long due = (unsigned long long)accumulator; ClickMode mode = (ClickMode)g_mode.load(std::memory_order_relaxed); unsigned long long maxBurst = 0; if (localCps <= 30000ULL) { maxBurst = ClampUll(preferredBatch * 2ULL, 1ULL, 64ULL); } else { maxBurst = (mode == ClickMode::Screen) ? 2048ULL : 512ULL; } if (due > maxBurst) due = maxBurst; accumulator -= (long double)due; // Ограничиваем догоняющий хвост, чтобы после зависания не было резкого перелёта КПС. long double maxBacklog = (long double)maxBurst * 2.0L; if (accumulator > maxBacklog) accumulator = maxBacklog; DoClickBurst(due); idleSpins = 0; } timeEndPeriod(1);
}
void ToggleClicking()
{
bool now = !g_clicking.load();
textg_clicking.store(now); if (now) { std::thread(ClickLoop).detach(); SetWindowTextW(hStaticHint, L"F6: стоп"); } else { SetWindowTextW(hStaticHint, L"F6: старт / стоп"); }
}
// =====================================================
// Virtual mouse
// =====================================================
void SetVirtualMouseFromCursor()
{
POINT p{};
GetCursorPos(&p);
textg_virtualX.store(p.x); g_virtualY.store(p.y);
}
// =====================================================
// Mode
// =====================================================
void UpdateModeUi()
{
ClickMode mode = (ClickMode)g_mode.load();
bool windowsMode = mode == ClickMode::Windows;
textShowWindow(hBtnRefresh, windowsMode ? SW_SHOW : SW_HIDE); ShowWindow(hBtnApplyWindows, windowsMode ? SW_SHOW : SW_HIDE); ShowWindow(hStaticApplied, windowsMode ? SW_SHOW : SW_HIDE); ShowWindow(hListView, windowsMode ? SW_SHOW : SW_HIDE); int cpsY = windowsMode ? CPS_Y_WINDOWS : CPS_Y_SCREEN; int virtualY = windowsMode ? VIRTUAL_Y_WINDOWS : VIRTUAL_Y_SCREEN; MoveWindow(hEditCPS, 50, cpsY, 180, 54, TRUE); MoveWindow(hBtnApplyCPS, 252, cpsY, 255, 54, TRUE); MoveWindow(hStaticCPS, 532, cpsY + 14, 280, 32, TRUE); MoveWindow(hChkVirtual, 50, virtualY, 22, 22, TRUE); MoveWindow(hLblVirtual, 80, virtualY, 260, 30, TRUE); MoveWindow(hStaticHint, 360, virtualY + 2, 500, 28, TRUE); InvalidateRect(hTabWindows, nullptr, TRUE); InvalidateRect(hTabScreen, nullptr, TRUE); InvalidateRect(g_mainHwnd, nullptr, TRUE);
}
// =====================================================
// Main window
// =====================================================
LRESULT CALLBACK MainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_CREATE:
{
g_brBg = CreateSolidBrush(CLR_BG);
g_brPanel = CreateSolidBrush(CLR_PANEL);
g_brEdit = CreateSolidBrush(CLR_PANEL_2);
textg_font = CreateFontW( 21, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Segoe UI Variable Display" ); g_fontBold = CreateFontW( 21, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Segoe UI Variable Display" ); g_fontTitle = CreateFontW( 30, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Segoe UI Variable Display" ); g_fontMenu = CreateFontW( 27, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Segoe UI Variable Display" ); g_fontEdit = CreateFontW( 26, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Segoe UI Variable Display" ); hBtnMin = CreateWindowW( L"BUTTON", L"—", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, APP_W - 198, 22, 54, 38, hwnd, (HMENU)ID_BTN_MIN, GetModuleHandleW(nullptr), nullptr ); hBtnMax = CreateWindowW( L"BUTTON", L"□", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, APP_W - 134, 22, 54, 38, hwnd, (HMENU)ID_BTN_MAX, GetModuleHandleW(nullptr), nullptr ); hBtnClose = CreateWindowW( L"BUTTON", L"×", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, APP_W - 70, 22, 54, 38, hwnd, (HMENU)ID_BTN_CLOSE, GetModuleHandleW(nullptr), nullptr ); hTabWindows = CreateWindowW( L"BUTTON", L"1 Окна", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 50, 100, 280, 54, hwnd, (HMENU)ID_TAB_WINDOWS, GetModuleHandleW(nullptr), nullptr ); hTabScreen = CreateWindowW( L"BUTTON", L"2 Экран", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 350, 100, 280, 54, hwnd, (HMENU)ID_TAB_SCREEN, GetModuleHandleW(nullptr), nullptr ); hBtnRefresh = CreateWindowW( L"BUTTON", L"Обновить список", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 650, 100, 150, 54, hwnd, (HMENU)ID_BTN_REFRESH, GetModuleHandleW(nullptr), nullptr ); hBtnApplyWindows = CreateWindowW( L"BUTTON", L"Применить", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 818, 100, 142, 54, hwnd, (HMENU)ID_BTN_APPLY_WINDOWS, GetModuleHandleW(nullptr), nullptr ); hStaticApplied = CreateWindowW( L"STATIC", L"Выбрано окон: 0", WS_CHILD | WS_VISIBLE, 50, 194, 420, 28, hwnd, (HMENU)ID_STATIC_APPLIED, GetModuleHandleW(nullptr), nullptr ); hListView = CreateWindowW( WC_LISTVIEWW, nullptr, WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER, 52, 292, 910, 276, hwnd, (HMENU)ID_LISTVIEW, GetModuleHandleW(nullptr), nullptr ); ListView_SetExtendedListViewStyle( hListView, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_DOUBLEBUFFER ); ListView_SetBkColor(hListView, CLR_PANEL); ListView_SetTextBkColor(hListView, CLR_PANEL); ListView_SetTextColor(hListView, CLR_TEXT); hEditCPS = CreateWindowW( L"EDIT", L"42", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER, 50, CPS_Y_WINDOWS, 180, 54, hwnd, (HMENU)ID_EDIT_CPS, GetModuleHandleW(nullptr), nullptr ); hBtnApplyCPS = CreateWindowW( L"BUTTON", L"Применить КПС", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 252, CPS_Y_WINDOWS, 255, 54, hwnd, (HMENU)ID_BTN_APPLY_CPS, GetModuleHandleW(nullptr), nullptr ); hStaticCPS = CreateWindowW( L"STATIC", L"КПС: 42", WS_CHILD | WS_VISIBLE, 532, CPS_Y_WINDOWS + 14, 280, 32, hwnd, (HMENU)ID_STATIC_CPS, GetModuleHandleW(nullptr), nullptr ); hChkVirtual = CreateWindowW( L"BUTTON", L"", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 50, VIRTUAL_Y_WINDOWS, 22, 22, hwnd, (HMENU)ID_CHK_VIRTUAL, GetModuleHandleW(nullptr), nullptr ); hLblVirtual = CreateWindowW( L"STATIC", L"Виртуальная мышь", WS_CHILD | WS_VISIBLE, 80, VIRTUAL_Y_WINDOWS, 260, 30, hwnd, nullptr, GetModuleHandleW(nullptr), nullptr ); hStaticHint = CreateWindowW( L"STATIC", L"F6: старт / стоп", WS_CHILD | WS_VISIBLE, 360, VIRTUAL_Y_WINDOWS + 2, 500, 28, hwnd, nullptr, GetModuleHandleW(nullptr), nullptr ); HWND controls[] = { hBtnMin, hBtnMax, hBtnClose, hTabWindows, hTabScreen, hBtnRefresh, hBtnApplyWindows, hStaticApplied, hListView, hEditCPS, hBtnApplyCPS, hStaticCPS, hChkVirtual, hLblVirtual, hStaticHint }; for (HWND c : controls) SendMessageW(c, WM_SETFONT, (WPARAM)g_font, TRUE); SendMessageW(hTabWindows, WM_SETFONT, (WPARAM)g_fontMenu, TRUE); SendMessageW(hTabScreen, WM_SETFONT, (WPARAM)g_fontMenu, TRUE); SendMessageW(hEditCPS, WM_SETFONT, (WPARAM)g_fontEdit, TRUE); SendMessageW(hStaticApplied, WM_SETFONT, (WPARAM)g_fontBold, TRUE); SendMessageW(hStaticCPS, WM_SETFONT, (WPARAM)g_fontBold, TRUE); RefreshWindowList(); RegisterHotKey(hwnd, ID_HOTKEY_F6, 0, VK_F6); POINT center{ GetSystemMetrics(SM_CXSCREEN) / 2, GetSystemMetrics(SM_CYSCREEN) / 2 }; g_virtualX.store(center.x); g_virtualY.store(center.y); UpdateModeUi(); return 0; } case WM_ERASEBKGND: return 1; case WM_PAINT: { PAINTSTRUCT ps{}; HDC hdc = BeginPaint(hwnd, &ps); DrawWindowChrome(hdc); EndPaint(hwnd, &ps); return 0; } case WM_NCHITTEST: { POINT p{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; ScreenToClient(hwnd, &p); if (p.y >= 0 && p.y <= 75) { if (p.x >= APP_W - 220) return HTCLIENT; return HTCAPTION; } return HTCLIENT; } case WM_CTLCOLORSTATIC: { HDC hdc = (HDC)wParam; SetBkMode(hdc, TRANSPARENT); HWND ctl = (HWND)lParam; if (ctl == hStaticApplied || ctl == hStaticCPS) SetTextColor(hdc, CLR_TEXT); else SetTextColor(hdc, CLR_MUTED); return (LRESULT)g_brPanel; } case WM_CTLCOLORBTN: { HDC hdc = (HDC)wParam; SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, CLR_TEXT); return (LRESULT)g_brPanel; } case WM_CTLCOLOREDIT: { HDC hdc = (HDC)wParam; SetBkColor(hdc, CLR_PANEL_2); SetTextColor(hdc, CLR_TEXT); return (LRESULT)g_brEdit; } case WM_DRAWITEM: { DrawOwnerButton((DRAWITEMSTRUCT*)lParam); return TRUE; } case WM_NOTIFY: { LPNMHDR hdr = (LPNMHDR)lParam; if (hdr->idFrom == ID_LISTVIEW && hdr->code == NM_CUSTOMDRAW) { LPNMLVCUSTOMDRAW cd = (LPNMLVCUSTOMDRAW)lParam; if (cd->nmcd.dwDrawStage == CDDS_PREPAINT) { SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW); return TRUE; } if (cd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) { cd->clrText = CLR_TEXT; cd->clrTextBk = CLR_PANEL; SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, CDRF_DODEFAULT); return TRUE; } } return 0; } case WM_HOTKEY: { if (wParam == ID_HOTKEY_F6) ToggleClicking(); return 0; } case WM_COMMAND: { switch (LOWORD(wParam)) { case ID_BTN_REFRESH: RefreshWindowList(); break; case ID_BTN_APPLY_WINDOWS: UpdateSelectedWindows(); break; case ID_BTN_APPLY_CPS: ApplyCpsFromEdit(); break; case ID_TAB_WINDOWS: g_mode.store((int)ClickMode::Windows); UpdateModeUi(); break; case ID_TAB_SCREEN: g_mode.store((int)ClickMode::Screen); UpdateModeUi(); break; case ID_CHK_VIRTUAL: { LRESULT state = SendMessageW(hChkVirtual, BM_GETCHECK, 0, 0); bool enabled = state == BST_CHECKED; g_useVirtualMouse.store(enabled); if (enabled) SetVirtualMouseFromCursor(); break; } case ID_BTN_MIN: ShowWindow(hwnd, SW_MINIMIZE); break; case ID_BTN_MAX: if (IsZoomed(hwnd)) ShowWindow(hwnd, SW_RESTORE); else ShowWindow(hwnd, SW_MAXIMIZE); break; case ID_BTN_CLOSE: DestroyWindow(hwnd); break; } return 0; } case WM_DESTROY: { g_clicking.store(false); UnregisterHotKey(hwnd, ID_HOTKEY_F6); if (g_imgList) ImageList_Destroy(g_imgList); if (g_font) DeleteObject(g_font); if (g_fontBold) DeleteObject(g_fontBold); if (g_fontTitle) DeleteObject(g_fontTitle); if (g_fontMenu) DeleteObject(g_fontMenu); if (g_fontEdit) DeleteObject(g_fontEdit); if (g_brBg) DeleteObject(g_brBg); if (g_brPanel) DeleteObject(g_brPanel); if (g_brEdit) DeleteObject(g_brEdit); PostQuitMessage(0); return 0; } } return DefWindowProcW(hwnd, msg, wParam, lParam);
}
// =====================================================
// Entry point
// =====================================================
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
{
SetProcessDPIAware();
textINITCOMMONCONTROLSEX icex{}; icex.dwSize = sizeof(icex); icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_STANDARD_CLASSES; InitCommonControlsEx(&icex); WNDCLASSW wc{}; wc.lpfnWndProc = MainProc; wc.hInstance = hInstance; wc.lpszClassName = L"RedClicerMainWindow"; wc.hCursor = LoadCursorW(nullptr, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); if (!RegisterClassW(&wc)) { MessageBoxW(nullptr, L"Не удалось зарегистрировать класс окна.", L"Ошибка", MB_OK | MB_ICONERROR); return 0; } int x = (GetSystemMetrics(SM_CXSCREEN) - APP_W) / 2; int y = (GetSystemMetrics(SM_CYSCREEN) - APP_H) / 2; g_mainHwnd = CreateWindowExW( WS_EX_APPWINDOW, L"RedClicerMainWindow", L"RedClicer", WS_POPUP | WS_MINIMIZEBOX, x, y, APP_W, APP_H, nullptr, nullptr, hInstance, nullptr ); if (!g_mainHwnd) { MessageBoxW(nullptr, L"Не удалось создать окно.", L"Ошибка", MB_OK | MB_ICONERROR); return 0; } HRGN rgn = CreateRoundRectRgn(0, 0, APP_W + 1, APP_H + 1, 18, 18); SetWindowRgn(g_mainHwnd, rgn, TRUE); ShowWindow(g_mainHwnd, nCmdShow); UpdateWindow(g_mainHwnd); MSG msg{}; while (GetMessageW(&msg, nullptr, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); } return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
return wWinMain(hInstance, hPrevInstance, GetCommandLineW(), nCmdShow);
}
компилил - g++ -std=c++17 12.cpp -O2 -municode -mwindows -lcomctl32 -lgdi32 -luser32 -lshell32 -lwinmm -o RedClicker.exe
надо исправит
итог скинь готовый код в виде файла сюда и как компилить
pythonfrom pathlib import Path code = r'''#ifndef UNICODE #define UNICODE #endif #ifndef _UNICODE #define _UNICODE #endif #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include <shellapi.h> #include <mmsystem.h> #include <thread> #include <atomic> #include <vector> #include <string> #include <sstream> #include <mutex> #include <algorithm> #include <cwchar> #include <cstdint> #pragma comment(lib, "Comctl32.lib") #pragma comment(lib, "Shell32.lib") #pragma comment(lib, "Winmm.lib") // ===================================================== // Settings // ===================================================== static constexpr int APP_W = 1020; static constexpr int APP_H = 760; static constexpr COLORREF CLR_BG = RGB(8, 8, 10); static constexpr COLORREF CLR_PANEL = RGB(14, 14, 17); static constexpr COLORREF CLR_PANEL_2 = RGB(21, 21, 25); static constexpr COLORREF CLR_BORDER = RGB(120, 0, 15); static constexpr COLORREF CLR_ACCENT = RGB(235, 25, 40); static constexpr COLORREF CLR_ACCENT_2 = RGB(165, 15, 25); static constexpr COLORREF CLR_TEXT = RGB(235, 235, 235); static constexpr COLORREF CLR_MUTED = RGB(165, 165, 165); static constexpr unsigned long long MAX_CPS = 10000042ULL; // Layout static constexpr int CPS_Y_WINDOWS = 616; static constexpr int CPS_Y_SCREEN = 210; static constexpr int VIRTUAL_Y_WINDOWS = 694; static constexpr int VIRTUAL_Y_SCREEN = 286; // ===================================================== // Globals // ===================================================== struct WindowItem { HWND hwnd; std::wstring title; HICON icon; }; struct SavedVirtualPoint { HWND hwnd; POINT clientPoint; }; enum class ClickMode { Windows, Screen }; std::vector<WindowItem> g_windowList; std::vector<HWND> g_selectedWindows; std::vector<SavedVirtualPoint> g_virtualClientPoints; std::mutex g_windowsMutex; std::atomic<bool> g_clicking(false); std::atomic<unsigned long long> g_cps(42); std::atomic<bool> g_useVirtualMouse(false); std::atomic<long> g_virtualX(0); std::atomic<long> g_virtualY(0); std::atomic<int> g_mode((int)ClickMode::Windows); HWND g_mainHwnd = nullptr; HFONT g_font = nullptr; HFONT g_fontBold = nullptr; HFONT g_fontTitle = nullptr; HFONT g_fontMenu = nullptr; HFONT g_fontEdit = nullptr; HBRUSH g_brBg = nullptr; HBRUSH g_brPanel = nullptr; HBRUSH g_brEdit = nullptr; HIMAGELIST g_imgList = nullptr; // ===================================================== // UI // ===================================================== HWND hBtnRefresh = nullptr; HWND hBtnApplyWindows = nullptr; HWND hStaticApplied = nullptr; HWND hListView = nullptr; HWND hEditCPS = nullptr; HWND hBtnApplyCPS = nullptr; HWND hStaticCPS = nullptr; HWND hChkVirtual = nullptr; HWND hLblVirtual = nullptr; HWND hStaticHint = nullptr; HWND hTabWindows = nullptr; HWND hTabScreen = nullptr; HWND hBtnMin = nullptr; HWND hBtnMax = nullptr; HWND hBtnClose = nullptr; // ===================================================== // IDs // ===================================================== enum { ID_BTN_REFRESH = 101, ID_LISTVIEW = 102, ID_EDIT_CPS = 103, ID_BTN_APPLY_CPS = 104, ID_STATIC_CPS = 105, ID_CHK_VIRTUAL = 106, ID_BTN_APPLY_WINDOWS = 107, ID_HOTKEY_F6 = 108, ID_STATIC_APPLIED = 109, ID_TAB_WINDOWS = 120, ID_TAB_SCREEN = 121, ID_BTN_MIN = 201, ID_BTN_MAX = 202, ID_BTN_CLOSE = 203 }; // ===================================================== // Prototypes // ===================================================== void RefreshWindowList(); void UpdateSelectedWindows(); void ClickLoop(); void SetVirtualMouseFromCursor(); void UpdateCpsText(); void UpdateAppliedText(); void UpdateModeUi(); static inline POINT GetVirtualPoint() { return POINT{ g_virtualX.load(), g_virtualY.load() }; } static inline unsigned long long ClampUll(unsigned long long v, unsigned long long lo, unsigned long long hi) { return std::min(std::max(v, lo), hi); } static inline LONG ClampLong(LONG v, LONG lo, LONG hi) { return std::min(std::max(v, lo), hi); } // ===================================================== // GDI helpers // ===================================================== void FillRound(HDC hdc, RECT rc, COLORREF fill, COLORREF border, int radius) { HBRUSH br = CreateSolidBrush(fill); HPEN pen = CreatePen(PS_SOLID, 1, border); HGDIOBJ oldBr = SelectObject(hdc, br); HGDIOBJ oldPen = SelectObject(hdc, pen); RoundRect(hdc, rc.left, rc.top, rc.right, rc.bottom, radius, radius); SelectObject(hdc, oldBr); SelectObject(hdc, oldPen); DeleteObject(br); DeleteObject(pen); } void DrawTitleLogo(HDC hdc) { HPEN redPen = CreatePen(PS_SOLID, 3, CLR_ACCENT); HGDIOBJ oldPen = SelectObject(hdc, redPen); HGDIOBJ oldBr = SelectObject(hdc, GetStockObject(NULL_BRUSH)); Ellipse(hdc, 28, 24, 64, 60); Ellipse(hdc, 38, 34, 54, 50); MoveToEx(hdc, 46, 42, nullptr); LineTo(hdc, 70, 66); SelectObject(hdc, oldBr); SelectObject(hdc, oldPen); DeleteObject(redPen); SetBkMode(hdc, TRANSPARENT); HFONT oldFont = (HFONT)SelectObject(hdc, g_fontTitle); SetTextColor(hdc, CLR_ACCENT); TextOutW(hdc, 84, 27, L"Red", 3); SetTextColor(hdc, CLR_TEXT); TextOutW(hdc, 130, 27, L"Clicer", 6); SelectObject(hdc, oldFont); } void DrawWindowChrome(HDC hdc) { RECT full{ 0, 0, APP_W, APP_H }; HBRUSH bg = CreateSolidBrush(CLR_BG); FillRect(hdc, &full, bg); DeleteObject(bg); RECT outer{ 0, 0, APP_W, APP_H }; FillRound(hdc, outer, CLR_BG, CLR_BORDER, 18); RECT topLine{ 0, 74, APP_W, 75 }; HBRUSH brLine = CreateSolidBrush(RGB(40, 20, 23)); FillRect(hdc, &topLine, brLine); DeleteObject(brLine); DrawTitleLogo(hdc); RECT modePanel{ 28, 90, 988, 164 }; FillRound(hdc, modePanel, CLR_PANEL, RGB(45, 45, 50), 8); ClickMode mode = (ClickMode)g_mode.load(); bool windowsMode = mode == ClickMode::Windows; SetBkMode(hdc, TRANSPARENT); HFONT oldFont = (HFONT)SelectObject(hdc, g_fontBold); if (windowsMode) { RECT appliedPanel{ 28, 180, 988, 230 }; FillRound(hdc, appliedPanel, CLR_PANEL, RGB(45, 45, 50), 8); RECT listPanel{ 28, 244, 988, 588 }; FillRound(hdc, listPanel, CLR_BG, CLR_BORDER, 8); SetTextColor(hdc, CLR_ACCENT); TextOutW(hdc, 50, 260, L"Список окон", 11); RECT cpsPanel{ 28, 604, 988, 734 }; FillRound(hdc, cpsPanel, CLR_PANEL, RGB(45, 45, 50), 8); } else { // В режиме "Экран" убран обрезанный заголовок и выровнены элементы. RECT cpsPanel{ 28, 180, 988, 348 }; FillRound(hdc, cpsPanel, CLR_PANEL, RGB(45, 45, 50), 8); } SelectObject(hdc, oldFont); } // ===================================================== // Owner-draw buttons // ===================================================== void DrawOwnerButton(const DRAWITEMSTRUCT* dis) { HDC hdc = dis->hDC; RECT rc = dis->rcItem; UINT id = dis->CtlID; bool pressed = (dis->itemState & ODS_SELECTED) != 0; bool hot = (dis->itemState & ODS_HOTLIGHT) != 0; COLORREF fill = CLR_PANEL_2; COLORREF border = RGB(55, 55, 60); COLORREF text = CLR_TEXT; HFONT font = g_fontBold; if (id == ID_TAB_WINDOWS || id == ID_TAB_SCREEN) { ClickMode mode = (ClickMode)g_mode.load(); bool active = (id == ID_TAB_WINDOWS && mode == ClickMode::Windows) || (id == ID_TAB_SCREEN && mode == ClickMode::Screen); fill = active ? CLR_ACCENT : (hot ? RGB(30, 30, 36) : CLR_PANEL_2); border = active ? RGB(255, 65, 78) : RGB(60, 60, 66); text = active ? RGB(255, 255, 255) : CLR_MUTED; font = g_fontMenu; } if (id == ID_BTN_APPLY_WINDOWS || id == ID_BTN_APPLY_CPS) { fill = pressed ? CLR_ACCENT_2 : CLR_ACCENT; border = RGB(255, 60, 75); text = RGB(255, 255, 255); } if (id == ID_BTN_CLOSE) { fill = pressed ? RGB(130, 15, 25) : CLR_BG; border = CLR_BG; text = CLR_TEXT; } if (id == ID_BTN_MIN || id == ID_BTN_MAX) { fill = CLR_BG; border = CLR_BG; text = CLR_TEXT; } if (hot && id != ID_BTN_APPLY_WINDOWS && id != ID_BTN_APPLY_CPS && id != ID_BTN_CLOSE && id != ID_BTN_MIN && id != ID_BTN_MAX && id != ID_TAB_WINDOWS && id != ID_TAB_SCREEN) { fill = RGB(26, 26, 31); } FillRound(hdc, rc, fill, border, 10); wchar_t textBuf[128]{}; GetWindowTextW(dis->hwndItem, textBuf, 128); SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, text); HFONT oldFont = (HFONT)SelectObject(hdc, font); DrawTextW(hdc, textBuf, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); SelectObject(hdc, oldFont); } // ===================================================== // Window icons // ===================================================== HICON GetWindowSmallIcon(HWND hwnd) { HICON icon = (HICON)SendMessageW(hwnd, WM_GETICON, ICON_SMALL2, 0); if (!icon) icon = (HICON)SendMessageW(hwnd, WM_GETICON, ICON_SMALL, 0); if (!icon) icon = (HICON)SendMessageW(hwnd, WM_GETICON, ICON_BIG, 0); if (!icon) { LONG_PTR clsIcon = GetClassLongPtrW(hwnd, GCLP_HICONSM); if (clsIcon) icon = (HICON)clsIcon; } if (!icon) { LONG_PTR clsIcon = GetClassLongPtrW(hwnd, GCLP_HICON); if (clsIcon) icon = (HICON)clsIcon; } if (!icon) icon = LoadIconW(nullptr, IDI_APPLICATION); return icon; } // ===================================================== // Window enum // ===================================================== BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM) { if (!IsWindowVisible(hwnd)) return TRUE; if (hwnd == g_mainHwnd) return TRUE; wchar_t title[512]{}; GetWindowTextW(hwnd, title, 512); if (wcslen(title) == 0) return TRUE; LONG_PTR exStyle = GetWindowLongPtrW(hwnd, GWL_EXSTYLE); if (exStyle & WS_EX_TOOLWINDOW) return TRUE; g_windowList.push_back(WindowItem{ hwnd, title, GetWindowSmallIcon(hwnd) }); return TRUE; } void RefreshWindowList() { g_windowList.clear(); EnumWindows(EnumWindowsProc, 0); std::sort(g_windowList.begin(), g_windowList.end(), [](const WindowItem& a, const WindowItem& b) { return a.title < b.title; }); ListView_DeleteAllItems(hListView); if (g_imgList) { ImageList_Destroy(g_imgList); g_imgList = nullptr; } g_imgList = ImageList_Create(24, 24, ILC_COLOR32 | ILC_MASK, 16, 16); ListView_SetImageList(hListView, g_imgList, LVSIL_SMALL); LVCOLUMNW col{}; col.mask = LVCF_TEXT | LVCF_WIDTH; col.pszText = const_cast<LPWSTR>(L"Окна"); col.cx = 850; if (Header_GetItemCount(ListView_GetHeader(hListView)) == 0) ListView_InsertColumn(hListView, 0, &col); else ListView_SetColumn(hListView, 0, &col); for (int i = 0; i < (int)g_windowList.size(); ++i) { int img = ImageList_AddIcon(g_imgList, g_windowList[i].icon); LVITEMW item{}; item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; item.iItem = i; item.iSubItem = 0; item.pszText = const_cast<LPWSTR>(g_windowList[i].title.c_str()); item.lParam = reinterpret_cast<LPARAM>(g_windowList[i].hwnd); item.iImage = img; ListView_InsertItem(hListView, &item); } { std::lock_guard<std::mutex> lock(g_windowsMutex); g_selectedWindows.clear(); g_virtualClientPoints.clear(); } UpdateAppliedText(); } void UpdateAppliedText() { size_t count = 0; { std::lock_guard<std::mutex> lock(g_windowsMutex); count = g_selectedWindows.size(); } std::wstringstream ss; ss << L"Выбрано окон: " << count; SetWindowTextW(hStaticApplied, ss.str().c_str()); } void UpdateSelectedWindows() { std::vector<HWND> picked; int count = ListView_GetItemCount(hListView); for (int i = 0; i < count; ++i) { UINT state = ListView_GetItemState(hListView, i, LVIS_STATEIMAGEMASK); if (state == INDEXTOSTATEIMAGEMASK(2)) { LVITEMW item{}; item.mask = LVIF_PARAM; item.iItem = i; if (ListView_GetItem(hListView, &item)) { HWND hwnd = reinterpret_cast<HWND>(item.lParam); if (IsWindow(hwnd)) picked.push_back(hwnd); } } } { std::lock_guard<std::mutex> lock(g_windowsMutex); g_selectedWindows = picked; g_virtualClientPoints.clear(); } // Если виртуальная мышь уже включена, сразу пересохраняем точку // относительно выбранных окон. if (g_useVirtualMouse.load()) SetVirtualMouseFromCursor(); UpdateAppliedText(); } // ===================================================== // CPS // ===================================================== void UpdateCpsText() { std::wstringstream ss; ss << L"КПС: " << g_cps.load(); SetWindowTextW(hStaticCPS, ss.str().c_str()); } void ApplyCpsFromEdit() { wchar_t buf[64]{}; GetWindowTextW(hEditCPS, buf, 64); unsigned long long value = _wcstoui64(buf, nullptr, 10); if (value < 1) value = 1; if (value > MAX_CPS) value = MAX_CPS; g_cps.store(value); std::wstringstream ss; ss << value; SetWindowTextW(hEditCPS, ss.str().c_str()); UpdateCpsText(); } // ===================================================== // Clicks // ===================================================== void SendGlobalClickBatch(unsigned long long clicks) { const unsigned long long MAX_BATCH = 4096; while (clicks > 0) { unsigned long long batch64 = std::min(clicks, MAX_BATCH); int batch = (int)batch64; std::vector<INPUT> inputs(batch * 2); for (int i = 0; i < batch; ++i) { inputs[i * 2].type = INPUT_MOUSE; inputs[i * 2].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; inputs[i * 2 + 1].type = INPUT_MOUSE; inputs[i * 2 + 1].mi.dwFlags = MOUSEEVENTF_LEFTUP; } SendInput((UINT)inputs.size(), inputs.data(), sizeof(INPUT)); clicks -= batch64; } } void SendVirtualClickBatch(POINT p, unsigned long long clicks) { const unsigned long long MAX_BATCH = 4096; int virtualLeft = GetSystemMetrics(SM_XVIRTUALSCREEN); int virtualTop = GetSystemMetrics(SM_YVIRTUALSCREEN); int virtualW = GetSystemMetrics(SM_CXVIRTUALSCREEN); int virtualH = GetSystemMetrics(SM_CYVIRTUALSCREEN); if (virtualW <= 1 || virtualH <= 1) return; LONG xAbs = (LONG)(((long double)(p.x - virtualLeft) * 65535.0L) / (long double)(virtualW - 1)); LONG yAbs = (LONG)(((long double)(p.y - virtualTop) * 65535.0L) / (long double)(virtualH - 1)); xAbs = ClampLong(xAbs, 0, 65535); yAbs = ClampLong(yAbs, 0, 65535); while (clicks > 0) { unsigned long long batch64 = std::min(clicks, MAX_BATCH); int batch = (int)batch64; std::vector<INPUT> inputs(1 + batch * 2); inputs[0].type = INPUT_MOUSE; inputs[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK; inputs[0].mi.dx = xAbs; inputs[0].mi.dy = yAbs; for (int i = 0; i < batch; ++i) { inputs[1 + i * 2].type = INPUT_MOUSE; inputs[1 + i * 2].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; inputs[1 + i * 2 + 1].type = INPUT_MOUSE; inputs[1 + i * 2 + 1].mi.dwFlags = MOUSEEVENTF_LEFTUP; } SendInput((UINT)inputs.size(), inputs.data(), sizeof(INPUT)); clicks -= batch64; } } LPARAM MakeMouseLParam(POINT clientPoint) { return MAKELPARAM((SHORT)clientPoint.x, (SHORT)clientPoint.y); } void PostWindowClickClient(HWND hwnd, POINT clientPoint) { if (!IsWindow(hwnd)) return; LPARAM lp = MakeMouseLParam(clientPoint); PostMessageW(hwnd, WM_MOUSEMOVE, 0, lp); PostMessageW(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, lp); PostMessageW(hwnd, WM_LBUTTONUP, 0, lp); } void PostWindowClick(HWND hwnd, POINT screenPoint) { if (!IsWindow(hwnd)) return; POINT clientPoint = screenPoint; ScreenToClient(hwnd, &clientPoint); PostWindowClickClient(hwnd, clientPoint); } bool GetSavedClientPointFor(HWND hwnd, const std::vector<SavedVirtualPoint>& savedPoints, POINT& outPoint) { for (const SavedVirtualPoint& item : savedPoints) { if (item.hwnd == hwnd && IsWindow(item.hwnd)) { outPoint = item.clientPoint; return true; } } return false; } void DoClickBurst(unsigned long long amount) { if (amount == 0) return; ClickMode mode = (ClickMode)g_mode.load(); bool virtualMode = g_useVirtualMouse.load(); POINT realPos{}; GetCursorPos(&realPos); POINT virtualPos = GetVirtualPoint(); POINT effectivePos = virtualMode ? virtualPos : realPos; if (mode == ClickMode::Screen) { if (virtualMode) SendVirtualClickBatch(effectivePos, amount); else SendGlobalClickBatch(amount); return; } std::vector<HWND> targets; std::vector<SavedVirtualPoint> savedPoints; { std::lock_guard<std::mutex> lock(g_windowsMutex); targets = g_selectedWindows; if (virtualMode) savedPoints = g_virtualClientPoints; } if (targets.empty()) return; for (unsigned long long i = 0; i < amount; ++i) { for (HWND hwnd : targets) { if (virtualMode) { POINT clientPoint{}; if (GetSavedClientPointFor(hwnd, savedPoints, clientPoint)) PostWindowClickClient(hwnd, clientPoint); else PostWindowClick(hwnd, effectivePos); } else { PostWindowClick(hwnd, realPos); } } } } void WaitBeforeNextClick(unsigned long long cps, long double accumulator, unsigned long long preferredBatch, int& idleSpins) { if (cps < 1) cps = 1; long double need = (long double)preferredBatch - accumulator; if (need < 1.0L) need = 1.0L; long double secondsToBatch = need / (long double)cps; if (secondsToBatch > 0.0025L) { Sleep(1); idleSpins = 0; } else { if (++idleSpins < 300) { YieldProcessor(); } else { Sleep(0); idleSpins = 0; } } } void ClickLoop() { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); timeBeginPeriod(1); LARGE_INTEGER freq{}; LARGE_INTEGER last{}; LARGE_INTEGER now{}; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&last); long double accumulator = 0.0L; int idleSpins = 0; unsigned long long lastCps = g_cps.load(std::memory_order_relaxed); while (g_clicking.load(std::memory_order_relaxed)) { QueryPerformanceCounter(&now); long double elapsed = (long double)(now.QuadPart - last.QuadPart) / (long double)freq.QuadPart; last = now; // Не даём старому лагу копиться и потом выдавать лишний большой залп. if (elapsed > 0.10L) elapsed = 0.10L; unsigned long long localCps = g_cps.load(std::memory_order_relaxed); if (localCps < 1) localCps = 1; // При смене КПС сбрасываем остаток, чтобы старый темп не давал скачок. if (localCps != lastCps) { accumulator = 0.0L; lastCps = localCps; } accumulator += elapsed * (long double)localCps; // До 30к КПС делаем маленькие ровные пачки примерно на 1 мс. // Так меньше разброс: 3000 не должен превращаться в 8000 на тестерах CPS. unsigned long long preferredBatch = ClampUll(localCps / 1000ULL, 1ULL, 30ULL); if (accumulator < (long double)preferredBatch) { WaitBeforeNextClick(localCps, accumulator, preferredBatch, idleSpins); continue; } unsigned long long due = (unsigned long long)accumulator; ClickMode mode = (ClickMode)g_mode.load(std::memory_order_relaxed); unsigned long long maxBurst = 0; if (localCps <= 30000ULL) { maxBurst = ClampUll(preferredBatch * 2ULL, 1ULL, 64ULL); } else { maxBurst = (mode == ClickMode::Screen) ? 2048ULL : 512ULL; } if (due > maxBurst) due = maxBurst; accumulator -= (long double)due; // Ограничиваем догоняющий хвост, чтобы после зависания не было резкого перелёта КПС. long double maxBacklog = (long double)maxBurst * 2.0L; if (accumulator > maxBacklog) accumulator = maxBacklog; DoClickBurst(due); idleSpins = 0; } timeEndPeriod(1); } void ToggleClicking() { bool now = !g_clicking.load(); g_clicking.store(now); if (now) { if (g_useVirtualMouse.load()) SetVirtualMouseFromCursor(); std::thread(ClickLoop).detach(); SetWindowTextW(hStaticHint, L"F6: стоп"); } else { SetWindowTextW(hStaticHint, L"F6: старт / стоп"); } } // ===================================================== // Virtual mouse // ===================================================== void SetVirtualMouseFromCursor() { POINT p{}; GetCursorPos(&p); g_virtualX.store(p.x); g_virtualY.store(p.y); std::lock_guard<std::mutex> lock(g_windowsMutex); g_virtualClientPoints.clear(); for (HWND hwnd : g_selectedWindows) { if (!IsWindow(hwnd)) continue; POINT clientPoint = p; ScreenToClient(hwnd, &clientPoint); g_virtualClientPoints.push_back(SavedVirtualPoint{ hwnd, clientPoint }); } } // ===================================================== // Mode // ===================================================== void UpdateModeUi() { ClickMode mode = (ClickMode)g_mode.load(); bool windowsMode = mode == ClickMode::Windows; ShowWindow(hBtnRefresh, windowsMode ? SW_SHOW : SW_HIDE); ShowWindow(hBtnApplyWindows, windowsMode ? SW_SHOW : SW_HIDE); ShowWindow(hStaticApplied, windowsMode ? SW_SHOW : SW_HIDE); ShowWindow(hListView, windowsMode ? SW_SHOW : SW_HIDE); int cpsY = windowsMode ? CPS_Y_WINDOWS : CPS_Y_SCREEN; int virtualY = windowsMode ? VIRTUAL_Y_WINDOWS : VIRTUAL_Y_SCREEN; MoveWindow(hEditCPS, 50, cpsY, 180, 54, TRUE); MoveWindow(hBtnApplyCPS, 252, cpsY, 255, 54, TRUE); MoveWindow(hStaticCPS, 532, cpsY + 14, 280, 32, TRUE); MoveWindow(hChkVirtual, 50, virtualY, 22, 22, TRUE); MoveWindow(hLblVirtual, 80, virtualY, 260, 30, TRUE); MoveWindow(hStaticHint, 360, virtualY + 2, 500, 28, TRUE); InvalidateRect(hTabWindows, nullptr, TRUE); InvalidateRect(hTabScreen, nullptr, TRUE); InvalidateRect(g_mainHwnd, nullptr, TRUE); } // ===================================================== // Main window // ===================================================== LRESULT CALLBACK MainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: { g_brBg = CreateSolidBrush(CLR_BG); g_brPanel = CreateSolidBrush(CLR_PANEL); g_brEdit = CreateSolidBrush(CLR_PANEL_2); g_font = CreateFontW( 21, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Segoe UI Variable Display" ); g_fontBold = CreateFontW( 21, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Segoe UI Variable Display" ); g_fontTitle = CreateFontW( 30, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Segoe UI Variable Display" ); g_fontMenu = CreateFontW( 27, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Segoe UI Variable Display" ); g_fontEdit = CreateFontW( 26, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Segoe UI Variable Display" ); hBtnMin = CreateWindowW( L"BUTTON", L"—", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, APP_W - 198, 22, 54, 38, hwnd, (HMENU)ID_BTN_MIN, GetModuleHandleW(nullptr), nullptr ); hBtnMax = CreateWindowW( L"BUTTON", L"□", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, APP_W - 134, 22, 54, 38, hwnd, (HMENU)ID_BTN_MAX, GetModuleHandleW(nullptr), nullptr ); hBtnClose = CreateWindowW( L"BUTTON", L"×", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, APP_W - 70, 22, 54, 38, hwnd, (HMENU)ID_BTN_CLOSE, GetModuleHandleW(nullptr), nullptr ); hTabWindows = CreateWindowW( L"BUTTON", L"1 Окна", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 50, 100, 280, 54, hwnd, (HMENU)ID_TAB_WINDOWS, GetModuleHandleW(nullptr), nullptr ); hTabScreen = CreateWindowW( L"BUTTON", L"2 Экран", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 350, 100, 280, 54, hwnd, (HMENU)ID_TAB_SCREEN, GetModuleHandleW(nullptr), nullptr ); hBtnRefresh = CreateWindowW( L"BUTTON", L"Обновить список", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 650, 100, 150, 54, hwnd, (HMENU)ID_BTN_REFRESH, GetModuleHandleW(nullptr), nullptr ); hBtnApplyWindows = CreateWindowW( L"BUTTON", L"Применить", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 818, 100, 142, 54, hwnd, (HMENU)ID_BTN_APPLY_WINDOWS, GetModuleHandleW(nullptr), nullptr ); hStaticApplied = CreateWindowW( L"STATIC", L"Выбрано окон: 0", WS_CHILD | WS_VISIBLE, 50, 194, 420, 28, hwnd, (HMENU)ID_STATIC_APPLIED, GetModuleHandleW(nullptr), nullptr ); hListView = CreateWindowW( WC_LISTVIEWW, nullptr, WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER, 52, 292, 910, 276, hwnd, (HMENU)ID_LISTVIEW, GetModuleHandleW(nullptr), nullptr ); ListView_SetExtendedListViewStyle( hListView, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_DOUBLEBUFFER ); ListView_SetBkColor(hListView, CLR_PANEL); ListView_SetTextBkColor(hListView, CLR_PANEL); ListView_SetTextColor(hListView, CLR_TEXT); hEditCPS = CreateWindowW( L"EDIT", L"42", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER, 50, CPS_Y_WINDOWS, 180, 54, hwnd, (HMENU)ID_EDIT_CPS, GetModuleHandleW(nullptr), nullptr ); hBtnApplyCPS = CreateWindowW( L"BUTTON", L"Применить КПС", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 252, CPS_Y_WINDOWS, 255, 54, hwnd, (HMENU)ID_BTN_APPLY_CPS, GetModuleHandleW(nullptr), nullptr ); hStaticCPS = CreateWindowW( L"STATIC", L"КПС: 42", WS_CHILD | WS_VISIBLE, 532, CPS_Y_WINDOWS + 14, 280, 32, hwnd, (HMENU)ID_STATIC_CPS, GetModuleHandleW(nullptr), nullptr ); hChkVirtual = CreateWindowW( L"BUTTON", L"", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 50, VIRTUAL_Y_WINDOWS, 22, 22, hwnd, (HMENU)ID_CHK_VIRTUAL, GetModuleHandleW(nullptr), nullptr ); hLblVirtual = CreateWindowW( L"STATIC", L"Виртуальная мышь", WS_CHILD | WS_VISIBLE, 80, VIRTUAL_Y_WINDOWS, 260, 30, hwnd, nullptr, GetModuleHandleW(nullptr), nullptr ); hStaticHint = CreateWindowW( L"STATIC", L"F6: старт / стоп", WS_CHILD | WS_VISIBLE, 360, VIRTUAL_Y_WINDOWS + 2, 500, 28, hwnd, nullptr, GetModuleHandleW(nullptr), nullptr ); HWND controls[] = { hBtnMin, hBtnMax, hBtnClose, hTabWindows, hTabScreen, hBtnRefresh, hBtnApplyWindows, hStaticApplied, hListView, hEditCPS, hBtnApplyCPS, hStaticCPS, hChkVirtual, hLblVirtual, hStaticHint }; for (HWND c : controls) SendMessageW(c, WM_SETFONT, (WPARAM)g_font, TRUE); SendMessageW(hTabWindows, WM_SETFONT, (WPARAM)g_fontMenu, TRUE); SendMessageW(hTabScreen, WM_SETFONT, (WPARAM)g_fontMenu, TRUE); SendMessageW(hEditCPS, WM_SETFONT, (WPARAM)g_fontEdit, TRUE); SendMessageW(hStaticApplied, WM_SETFONT, (WPARAM)g_fontBold, TRUE); SendMessageW(hStaticCPS, WM_SETFONT, (WPARAM)g_fontBold, TRUE); RefreshWindowList(); RegisterHotKey(hwnd, ID_HOTKEY_F6, 0, VK_F6); POINT center{ GetSystemMetrics(SM_XVIRTUALSCREEN) + GetSystemMetrics(SM_CXVIRTUALSCREEN) / 2, GetSystemMetrics(SM_YVIRTUALSCREEN) + GetSystemMetrics(SM_CYVIRTUALSCREEN) / 2 }; g_virtualX.store(center.x); g_virtualY.store(center.y); UpdateModeUi(); return 0; } case WM_ERASEBKGND: return 1; case WM_PAINT: { PAINTSTRUCT ps{}; HDC hdc = BeginPaint(hwnd, &ps); DrawWindowChrome(hdc); EndPaint(hwnd, &ps); return 0; } case WM_NCHITTEST: { POINT p{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; ScreenToClient(hwnd, &p); if (p.y >= 0 && p.y <= 75) { if (p.x >= APP_W - 220) return HTCLIENT; return HTCAPTION; } return HTCLIENT; } case WM_CTLCOLORSTATIC: { HDC hdc = (HDC)wParam; SetBkMode(hdc, TRANSPARENT); HWND ctl = (HWND)lParam; if (ctl == hStaticApplied || ctl == hStaticCPS) SetTextColor(hdc, CLR_TEXT); else SetTextColor(hdc, CLR_MUTED); return (LRESULT)g_brPanel; } case WM_CTLCOLORBTN: { HDC hdc = (HDC)wParam; SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, CLR_TEXT); return (LRESULT)g_brPanel; } case WM_CTLCOLOREDIT: { HDC hdc = (HDC)wParam; SetBkColor(hdc, CLR_PANEL_2); SetTextColor(hdc, CLR_TEXT); return (LRESULT)g_brEdit; } case WM_DRAWITEM: { DrawOwnerButton((DRAWITEMSTRUCT*)lParam); return TRUE; } case WM_NOTIFY: { LPNMHDR hdr = (LPNMHDR)lParam; if (hdr->idFrom == ID_LISTVIEW && hdr->code == NM_CUSTOMDRAW) { LPNMLVCUSTOMDRAW cd = (LPNMLVCUSTOMDRAW)lParam; if (cd->nmcd.dwDrawStage == CDDS_PREPAINT) { SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW); return TRUE; } if (cd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) { cd->clrText = CLR_TEXT; cd->clrTextBk = CLR_PANEL; SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, CDRF_DODEFAULT); return TRUE; } } return 0; } case WM_HOTKEY: { if (wParam == ID_HOTKEY_F6) ToggleClicking(); return 0; } case WM_COMMAND: { switch (LOWORD(wParam)) { case ID_BTN_REFRESH: RefreshWindowList(); break; case ID_BTN_APPLY_WINDOWS: UpdateSelectedWindows(); break; case ID_BTN_APPLY_CPS: ApplyCpsFromEdit(); break; case ID_TAB_WINDOWS: g_mode.store((int)ClickMode::Windows); UpdateModeUi(); break; case ID_TAB_SCREEN: g_mode.store((int)ClickMode::Screen); UpdateModeUi(); break; case ID_CHK_VIRTUAL: { LRESULT state = SendMessageW(hChkVirtual, BM_GETCHECK, 0, 0); bool enabled = state == BST_CHECKED; g_useVirtualMouse.store(enabled); if (enabled) SetVirtualMouseFromCursor(); break; } case ID_BTN_MIN: ShowWindow(hwnd, SW_MINIMIZE); break; case ID_BTN_MAX: if (IsZoomed(hwnd)) ShowWindow(hwnd, SW_RESTORE); else ShowWindow(hwnd, SW_MAXIMIZE); break; case ID_BTN_CLOSE: DestroyWindow(hwnd); break; } return 0; } case WM_DESTROY: { g_clicking.store(false); UnregisterHotKey(hwnd, ID_HOTKEY_F6); if (g_imgList) ImageList_Destroy(g_imgList); if (g_font) DeleteObject(g_font); if (g_fontBold) DeleteObject(g_fontBold); if (g_fontTitle) DeleteObject(g_fontTitle); if (g_fontMenu) DeleteObject(g_fontMenu); if (g_fontEdit) DeleteObject(g_fontEdit); if (g_brBg) DeleteObject(g_brBg); if (g_brPanel) DeleteObject(g_brPanel); if (g_brEdit) DeleteObject(g_brEdit); PostQuitMessage(0); return 0; } } return DefWindowProcW(hwnd, msg, wParam, lParam); } // ===================================================== // Entry point // ===================================================== int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow) { SetProcessDPIAware(); INITCOMMONCONTROLSEX icex{}; icex.dwSize = sizeof(icex); icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_STANDARD_CLASSES; InitCommonControlsEx(&icex); WNDCLASSW wc{}; wc.lpfnWndProc = MainProc; wc.hInstance = hInstance; wc.lpszClassName = L"RedClicerMainWindow"; wc.hCursor = LoadCursorW(nullptr, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); if (!RegisterClassW(&wc)) { MessageBoxW(nullptr, L"Не удалось зарегистрировать класс окна.", L"Ошибка", MB_OK | MB_ICONERROR); return 0; } int x = (GetSystemMetrics(SM_CXSCREEN) - APP_W) / 2; int y = (GetSystemMetrics(SM_CYSCREEN) - APP_H) / 2; g_mainHwnd = CreateWindowExW( WS_EX_APPWINDOW, L"RedClicerMainWindow", L"RedClicer", WS_POPUP | WS_MINIMIZEBOX, x, y, APP_W, APP_H, nullptr, nullptr, hInstance, nullptr ); if (!g_mainHwnd) { MessageBoxW(nullptr, L"Не удалось создать окно.", L"Ошибка", MB_OK | MB_ICONERROR); return 0; } HRGN rgn = CreateRoundRectRgn(0, 0, APP_W + 1, APP_H + 1, 18, 18); SetWindowRgn(g_mainHwnd, rgn, TRUE); ShowWindow(g_mainHwnd, nCmdShow); UpdateWindow(g_mainHwnd); MSG msg{}; while (GetMessageW(&msg, nullptr, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { return wWinMain(hInstance, hPrevInstance, GetCommandLineW(), nCmdShow); } ''' path = Path("/mnt/data/RedClicker_fixed.cpp") path.write_text(code, encoding="utf-8") print(f"Готово: {path}")
Готовый файл: RedClicker_fixed.cpp
Что исправил:
SM_XVIRTUALSCREEN.Компиляция:
bashg++ -std=c++17 RedClicker_fixed.cpp -O2 -municode -mwindows -finput-charset=UTF-8 -fexec-charset=UTF-8 -lcomctl32 -lgdi32 -luser32 -lshell32 -lwinmm -o RedClicker.exe
Если целевое окно запущено от администратора, то и кликер лучше запускать от администратора, иначе Windows может блокировать отправку кликов.