Skip to content

Instantly share code, notes, and snippets.

@EAirPeter
Last active May 2, 2018 09:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EAirPeter/117e00f26ed7df6516d031741039eb9a to your computer and use it in GitHub Desktop.
Save EAirPeter/117e00f26ed7df6516d031741039eb9a to your computer and use it in GitHub Desktop.
按CTRL-ALT-Q,自动点击鼠标下窗口的相对坐标,间隔200ms。再次按CTRL-ALT-Q停止。https://enza.fun/game/1?code=f85c45f2-c7c7-4e7c-a17a-eb282c7c5f78&openExternalBrowser=1
#include <Windows.h>
#include <math.h>
#include <stdio.h>
void ErrorExit(const char *pszWhat) {
auto dwError = GetLastError();
char *pBuf;
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &pBuf, 0, nullptr
);
fprintf(stderr, "%s failed: %s\n", pszWhat, pBuf);
LocalFree(pBuf);
fprintf(stderr, "Press Enter to exit...");
getchar();
ExitProcess(dwError);
}
int main() {
if (!RegisterHotKey(nullptr, 0, MOD_CONTROL | MOD_ALT, 'Q'))
ErrorExit("RegisterHotKey");
bool bActive = false;
UINT_PTR uTimer {};
MSG vMsg {};
HWND hWndActive {};
POINT vPointActive {};
while (GetMessageA(&vMsg, nullptr, 0, 0)) {
switch (vMsg.message) {
case WM_HOTKEY: {
if (bActive) {
if (!KillTimer(nullptr, uTimer))
ErrorExit("KillTimer");
printf("Stopped\n");
bActive = false;
break;
}
struct Info {
HWND hWnd;
RECT vRect;
POINT vPoint;
double dDist;
} vInfo {nullptr, {}, {}, 0.0};
if (!GetCursorPos(&vInfo.vPoint))
ErrorExit("GetCursorPos");
auto hWnd = WindowFromPoint(vInfo.vPoint);
EnumChildWindows(hWnd, [] (HWND hWnd, LPARAM lPar) -> BOOL {
auto pInfo = (Info *) lPar;
if (!IsWindowVisible(hWnd)/* || !IsWindowEnabled(hWnd)*/)
return TRUE;
RECT vRect;
if (!GetWindowRect(hWnd, &vRect))
return TRUE;
auto &vPoint = pInfo->vPoint;
if (vPoint.x < vRect.left || vPoint.x > vRect.right)
return TRUE;
if (vPoint.y < vRect.top || vPoint.y > vRect.bottom)
return TRUE;
auto dX = (double) (vRect.left + vRect.right) / 2.0;
auto dY = (double) (vRect.top + vRect.bottom) / 2.0;
auto dDist = hypot(dX - vPoint.x, dY - vPoint.y);
bool bUpdate = !pInfo->hWnd;
if (!bUpdate) {
bUpdate = true;
bUpdate &= vRect.left >= pInfo->vRect.left && vRect.right <= pInfo->vRect.right;
bUpdate &= vRect.top >= pInfo->vRect.top && vRect.bottom <= pInfo->vRect.bottom;
if (!bUpdate) {
bUpdate |= vRect.left > pInfo->vRect.left || vRect.right < pInfo->vRect.right;
bUpdate |= vRect.top > pInfo->vRect.top || vRect.bottom < pInfo->vRect.bottom;
bUpdate &= dDist < pInfo->dDist;
}
}
if (bUpdate) {
pInfo->hWnd = hWnd;
pInfo->vRect = vRect;
pInfo->dDist = dDist;
}
return TRUE;
}, (LPARAM) &vInfo);
hWndActive = vInfo.hWnd ? vInfo.hWnd : hWnd;
vPointActive = vInfo.vPoint;
char aBuf[4096];
GetWindowTextA(hWndActive, aBuf, 4096);
if (!ScreenToClient(hWndActive, &vPointActive))
ErrorExit("ScreenToClient");
uTimer = SetTimer(nullptr, 0, 200, nullptr);
if (!uTimer)
ErrorExit("SetTimer");
printf("Started [%p] [%s]: x = %ld, y = %ld\n", (void *) hWndActive, aBuf, vPointActive.x, vPointActive.y);
bActive = true;
break;
}
case WM_TIMER: {
if (!PostMessageA(hWndActive, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(vPointActive.x, vPointActive.y)))
ErrorExit("PostMessage WM_LBUTTONDOWN");
if (!PostMessageA(hWndActive, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(vPointActive.x, vPointActive.y)))
ErrorExit("PostMessage WM_LBUTTONUP");
break;
}
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment