From 2ab923e084f2736680985fd4bf94199ba728106c Mon Sep 17 00:00:00 2001 From: messenils Date: Tue, 4 Nov 2025 19:30:04 +0100 Subject: [PATCH] DrawCursorFix V2: added scan for symmetric cursors + Corrected mousewheel scroll coordinates --- src/ProtoInput/ProtoInputHooks/FakeCursor.cpp | 57 +++++++++++++++--- src/ProtoInput/ProtoInputHooks/FakeCursor.h | 59 ++++++++++--------- src/ProtoInput/ProtoInputHooks/RawInput.cpp | 12 +++- 3 files changed, 88 insertions(+), 40 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp index 377962c..63b76e0 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp @@ -52,7 +52,7 @@ void FakeCursor::DrawCursor() oldHadShowCursor = showCursor; - POINT pos = { FakeMouseKeyboard::GetMouseState().x,FakeMouseKeyboard::GetMouseState().y }; + POINT pos = { FakeMouseKeyboard::GetMouseState().x,FakeMouseKeyboard::GetMouseState().y }; ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &pos); ScreenToClient(pointerWindow, &pos); @@ -68,39 +68,77 @@ void FakeCursor::DrawCursor() { if (DrawIconEx(hdc, pos.x, pos.y, hCursor, cursorWidth, cursorHeight, 0, transparencyBrush, DI_NORMAL)) { + if (hCursor != oldhCursor && offsetSET > 1 && nochange == false) + { + offsetSET = 0; + } if (offsetSET == 1 && hCursor != LoadCursorW(NULL, IDC_ARROW) && IsWindowVisible(pointerWindow)) //offset setting { HDC hdcMem = CreateCompatibleDC(hdc); HBITMAP hbmScreen = CreateCompatibleBitmap(hdc, cursorWidth, cursorHeight); SelectObject(hdcMem, hbmScreen); BitBlt(hdcMem, 0, 0, cursorWidth, cursorHeight, hdc, pos.x, pos.y, SRCCOPY); - // Scan within the cursor screenshot pixel area cursoroffsetx = -1; cursoroffsety = -1; + int leftcursoroffsetx = 0; + int leftcursoroffsety = -1; + int rightcursoroffsetx = 0; + // Scanning for (int y = 0; y < cursorHeight; y++) { for (int x = 0; x < cursorWidth; x++) { - COLORREF pixelColor = GetPixel(hdcMem, x, y); // Get copied pixel color + COLORREF pixelColor = GetPixel(hdcMem, x, y); // scan from left and find common y to use in next scan also if (pixelColor != transparencyKey) { - cursoroffsetx = x; - cursoroffsety = y; + leftcursoroffsetx = x; + leftcursoroffsety = y; break; } } - if (cursoroffsetx != -1) break; + if (leftcursoroffsetx != -1) break; } - if (cursoroffsetx < 2) cursoroffsetx = 0; - if (cursoroffsety < 2) cursoroffsety = 0; - offsetSET ++; //offset set to 2 should do drawing only now + + + for (int x = cursorWidth - 1; x >= 0; x--) + { + COLORREF pixelColor = GetPixel(hdcMem, x, leftcursoroffsety); // scan from right + if (pixelColor != transparencyKey) + { + rightcursoroffsetx = cursorWidth - x; + break; + } + } + //Adjusting possible here if symmetric cursor is not found + if (leftcursoroffsetx == rightcursoroffsetx - 1 || leftcursoroffsetx == rightcursoroffsetx + 1 || leftcursoroffsetx == rightcursoroffsetx) //check for symmetric first only if Y offset is small + { + cursoroffsety = cursorHeight / 2; + cursoroffsetx = cursorWidth / 2; + } + else if (leftcursoroffsety > 2 || leftcursoroffsetx > 2) //is there any other offsets? + { + cursoroffsetx = leftcursoroffsetx; + cursoroffsety = leftcursoroffsety; + nochange = true; + } + + else { //no offsets + cursoroffsetx = 0; + cursoroffsety = 0; + } + offsetSET++; //offset set to 2 should do drawing only now DeleteDC(hdcMem); DeleteObject(hbmScreen); + + + } if (offsetSET == 0 && hCursor != LoadCursorW(NULL, IDC_ARROW) && IsWindowVisible(pointerWindow)) //size setting { ICONINFO ii; BITMAP bitmap; + cursoroffsetx = 0; + cursoroffsety = 0; if (GetIconInfo(hCursor, &ii)) { if (GetObject(ii.hbmMask, sizeof(BITMAP), &bitmap)) @@ -121,6 +159,7 @@ void FakeCursor::DrawCursor() } offsetSET++; //size set, doing offset next run } + oldhCursor = hCursor; } } } diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.h b/src/ProtoInput/ProtoInputHooks/FakeCursor.h index 0574f66..564874d 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.h +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.h @@ -5,39 +5,42 @@ namespace Proto { -class FakeCursor -{ - std::mutex mutex{}; - std::condition_variable conditionvar{}; - - HWND pointerWindow = nullptr; - HDC hdc; - HBRUSH transparencyBrush; - HCURSOR hCursor; - static constexpr auto transparencyKey = RGB(0, 0, 1); - - int oldX, oldY; - bool oldHadShowCursor = true; - //TODO: width/height probably needs to change + class FakeCursor + { + std::mutex mutex{}; + std::condition_variable conditionvar{}; + HWND pointerWindow = nullptr; + HDC hdc; + HBRUSH transparencyBrush; + HCURSOR hCursor; - // DrawFakeCursorFix. cursor offset scan and cursor size fix - int cursoroffsetx, cursoroffsety; - int offsetSET; //0:sizing 1:offset 2:done - int cursorWidth = 40; - int cursorHeight = 40; + static constexpr auto transparencyKey = RGB(0, 0, 1); - // This is either on or off for a given game (ie. it doesn't change) - bool drawingEnabled = false; + int oldX, oldY; + bool oldHadShowCursor = true; + //TODO: width/height probably needs to change - // This changes when the hook detects SetCursor/ShowCursor - bool showCursor = true; - bool toggleVisilbityShorcutEnabled = false; - unsigned int toggleVisibilityVkey = VK_HOME; - - void DrawCursor(); - + // DrawFakeCursorFix. cursor offset scan and cursor size fix + int cursoroffsetx, cursoroffsety; + int offsetSET = 0; //0:sizing 1:scanning 2:done, only drawing until cursor change, or nochange + int cursorWidth = 40; //was constant + int cursorHeight = 40;//was constant + bool nochange = false; //if normal offset was found at first then assume all cursors got same offset + HCURSOR oldhCursor = NULL; + + // This is either on or off for a given game (ie. it doesn't change) + bool drawingEnabled = false; + + // This changes when the hook detects SetCursor/ShowCursor + bool showCursor = true; + + bool toggleVisilbityShorcutEnabled = false; + unsigned int toggleVisibilityVkey = VK_HOME; + + void DrawCursor(); + public: static FakeCursor state; bool DrawFakeCursorFix; diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.cpp b/src/ProtoInput/ProtoInputHooks/RawInput.cpp index a05f0d1..b5286ad 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.cpp +++ b/src/ProtoInput/ProtoInputHooks/RawInput.cpp @@ -114,14 +114,20 @@ void RawInput::ProcessMouseInput(const RAWMOUSE& data, HANDLE deviceHandle) // Send mouse wheel if (rawInputState.sendMouseWheelMessages) { - if((data.usButtonFlags & RI_MOUSE_WHEEL) != 0) + if ((data.usButtonFlags & RI_MOUSE_WHEEL) != 0) { + //mousewheel messages use screen coordinates instead of client coordinates + POINT screen; + screen.x = FakeMouseKeyboard::GetMouseState().x; + screen.y = FakeMouseKeyboard::GetMouseState().y; + ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &screen); + LPARAM newmousePoint = MAKELPARAM(screen.x, screen.y); + const unsigned int wparam = (data.usButtonData << 16) | MouseWheelFilter::protoInputSignature | mouseMkFlags; - - PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_MOUSEWHEEL, wparam, mousePointLparam); + PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_MOUSEWHEEL, wparam, newmousePoint); } }