From 2ab923e084f2736680985fd4bf94199ba728106c Mon Sep 17 00:00:00 2001 From: messenils Date: Tue, 4 Nov 2025 19:30:04 +0100 Subject: [PATCH 01/20] 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); } } From 800dc8c4d196c9db115b39f3e018e637f37c77d6 Mon Sep 17 00:00:00 2001 From: messenils Date: Tue, 27 Jan 2026 18:07:04 +0100 Subject: [PATCH 02/20] Rearranged tunell and put it first in order on inject. Added option TranslateXtoMKB that when enabled polls Xinput and translates to MKB data if mouse or keyboard handle is missing from tunell. still some work left, mostly arranging it a little, and maybe re-use some more protoinput hooks instead of using all new ones --- src/ProtoInput/ProtoInputHooks/FakeCursor.cpp | 405 +- src/ProtoInput/ProtoInputHooks/FakeCursor.h | 3 +- .../ProtoInputHooks/GetRawInputDataHook.cpp | 1 + .../ProtoInputHooks/HookManager.cpp | 79 +- .../ProtoInputHooks/HwndSelector.cpp | 4 +- .../ProtoInputHooks/PipeCommunication.cpp | 77 +- .../ProtoInputHooks/ProtoInputHooks.vcxproj | 2 + .../ProtoInputHooks.vcxproj.filters | 9 + src/ProtoInput/ProtoInputHooks/RawInput.cpp | 43 +- src/ProtoInput/ProtoInputHooks/RawInput.h | 1 + .../ProtoInputHooks/RegisterRawInputHook.cpp | 28 +- .../ProtoInputHooks/TranslateXtoMKB.cpp | 4094 +++++++++++++++++ .../ProtoInputHooks/TranslateXtoMKB.h | 41 + src/ProtoInput/ProtoInputHooks/XinputHook.h | 62 +- src/ProtoInput/ProtoInputHooks/dllmain.cpp | 42 +- .../ProtoInputHooks/pipeinclude/pipeinclude.h | 19 +- src/ProtoInput/ProtoInputHost/Gui.cpp | 24 +- src/ProtoInput/ProtoInputHost/Profiles.h | 4 +- src/ProtoInput/ProtoInputLoader/Inject.cpp | 69 +- .../ProtoInputLoader/include/protoloader.h | 6 +- src/ProtoInput/ProtoInputUtil/InputLocker.cpp | 4 +- 21 files changed, 4662 insertions(+), 355 deletions(-) create mode 100644 src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp create mode 100644 src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp index 377962c..3db5561 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp @@ -8,255 +8,294 @@ namespace Proto { -FakeCursor FakeCursor::state{}; + FakeCursor FakeCursor::state{}; -LRESULT WINAPI FakeCursorWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) + LRESULT WINAPI FakeCursorWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - case WM_DESTROY: - PostQuitMessage(0); - return 0; - default: - break; - } + switch (msg) + { + case WM_DESTROY: + PostQuitMessage(0); + return 0; + default: + break; + } - return DefWindowProc(hWnd, msg, wParam, lParam); -} + return DefWindowProc(hWnd, msg, wParam, lParam); + } -LONG fakeCursorMinX = 0, fakeCursorMaxX = 0, fakeCursorMinY = 0, fakeCursorMaxY = 0; + LONG fakeCursorMinX = 0, fakeCursorMaxX = 0, fakeCursorMinY = 0, fakeCursorMaxY = 0; -BOOL CALLBACK EnumWindowsProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -{ - MONITORINFO info = { sizeof(info) }; - if (GetMonitorInfo(hMonitor, &info)) + BOOL CALLBACK EnumWindowsProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + MONITORINFO info = { sizeof(info) }; + if (GetMonitorInfo(hMonitor, &info)) + { #undef min // Thanks Windows.h #undef max - fakeCursorMinX = std::min(fakeCursorMinX, info.rcMonitor.left); - fakeCursorMinY = std::min(fakeCursorMinY, info.rcMonitor.top); - fakeCursorMaxX = std::max(fakeCursorMaxX, info.rcMonitor.right); - fakeCursorMaxY = std::max(fakeCursorMaxY, info.rcMonitor.bottom); + fakeCursorMinX = std::min(fakeCursorMinX, info.rcMonitor.left); + fakeCursorMinY = std::min(fakeCursorMinY, info.rcMonitor.top); + fakeCursorMaxX = std::max(fakeCursorMaxX, info.rcMonitor.right); + fakeCursorMaxY = std::max(fakeCursorMaxY, info.rcMonitor.bottom); + } + return true; } - return true; -} -void FakeCursor::DrawCursor() -{ - - if (oldHadShowCursor) //erase cursor + void FakeCursor::DrawCursor() { - RECT fill{ oldX, oldY, oldX + cursorWidth, oldY + cursorHeight }; - FillRect(hdc, &fill, transparencyBrush); // Note: window, not screen coordinates! - } - - oldHadShowCursor = showCursor; + if (oldHadShowCursor) //erase cursor + { + RECT fill{ oldX, oldY, oldX + cursorWidth, oldY + cursorHeight }; + FillRect(hdc, &fill, transparencyBrush); // Note: window, not screen coordinates! - POINT pos = { FakeMouseKeyboard::GetMouseState().x,FakeMouseKeyboard::GetMouseState().y }; - ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &pos); - ScreenToClient(pointerWindow, &pos); + } - if (DrawFakeCursorFix) - { - pos.x -= cursoroffsetx; - pos.y -= cursoroffsety; + oldHadShowCursor = showCursor; - if (pos.x < 0) pos.x = 0; - if (pos.y < 0) pos.y = 0; + POINT pos = { FakeMouseKeyboard::GetMouseState().x,FakeMouseKeyboard::GetMouseState().y }; + ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &pos); + ScreenToClient(pointerWindow, &pos); - if (showCursor)// && hdc && hCursor + if (DrawFakeCursorFix) { - if (DrawIconEx(hdc, pos.x, pos.y, hCursor, cursorWidth, cursorHeight, 0, transparencyBrush, DI_NORMAL)) + pos.x -= cursoroffsetx; + pos.y -= cursoroffsety; + + if (pos.x < 0) pos.x = 0; + if (pos.y < 0) pos.y = 0; + + if (showCursor)// && hdc && hCursor { - if (offsetSET == 1 && hCursor != LoadCursorW(NULL, IDC_ARROW) && IsWindowVisible(pointerWindow)) //offset setting + if (DrawIconEx(hdc, pos.x, pos.y, hCursor, cursorWidth, cursorHeight, 0, transparencyBrush, DI_NORMAL)) { - 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; - for (int y = 0; y < cursorHeight; y++) + if (hCursor != oldhCursor && offsetSET > 1 && nochange == false) { - for (int x = 0; x < cursorWidth; x++) + 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); + cursoroffsetx = -1; + cursoroffsety = -1; + int leftcursoroffsetx = 0; + int leftcursoroffsety = -1; + int rightcursoroffsetx = 0; + // Scanning + for (int y = 0; y < cursorHeight; y++) { - COLORREF pixelColor = GetPixel(hdcMem, x, y); // Get copied pixel color + for (int x = 0; x < cursorWidth; x++) + { + COLORREF pixelColor = GetPixel(hdcMem, x, y); // scan from left and find common y to use in next scan also + if (pixelColor != transparencyKey) + { + leftcursoroffsetx = x; + leftcursoroffsety = y; + break; + } + } + if (leftcursoroffsetx != -1) break; + } + + + for (int x = cursorWidth - 1; x >= 0; x--) + { + COLORREF pixelColor = GetPixel(hdcMem, x, leftcursoroffsety); // scan from right if (pixelColor != transparencyKey) { - cursoroffsetx = x; - cursoroffsety = y; + rightcursoroffsetx = cursorWidth - x; break; } } - if (cursoroffsetx != -1) 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 (cursoroffsetx < 2) cursoroffsetx = 0; - if (cursoroffsety < 2) 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; - if (GetIconInfo(hCursor, &ii)) + if (offsetSET == 0 && hCursor != LoadCursorW(NULL, IDC_ARROW) && IsWindowVisible(pointerWindow)) //size setting { - if (GetObject(ii.hbmMask, sizeof(BITMAP), &bitmap)) + ICONINFO ii; + BITMAP bitmap; + cursoroffsetx = 0; + cursoroffsety = 0; + if (GetIconInfo(hCursor, &ii)) { - cursorWidth = bitmap.bmWidth; - if (ii.hbmColor == NULL) - {//For monochrome icons, the hbmMask is twice the height of the icon and hbmColor is NULL - cursorHeight = bitmap.bmHeight / 2; - } - else + if (GetObject(ii.hbmMask, sizeof(BITMAP), &bitmap)) { - cursorHeight = bitmap.bmHeight; + cursorWidth = bitmap.bmWidth; + if (ii.hbmColor == NULL) + {//For monochrome icons, the hbmMask is twice the height of the icon and hbmColor is NULL + cursorHeight = bitmap.bmHeight / 2; + } + else + { + cursorHeight = bitmap.bmHeight; + } + DeleteObject(ii.hbmColor); + DeleteObject(ii.hbmMask); } - DeleteObject(ii.hbmColor); - DeleteObject(ii.hbmMask); - } + } + offsetSET++; //size set, doing offset next run } - offsetSET++; //size set, doing offset next run + oldhCursor = hCursor; } } } + else if (showCursor) + DrawIcon(hdc, pos.x, pos.y, hCursor); + oldX = pos.x; + oldY = pos.y; } - else if (showCursor) - DrawIcon(hdc, pos.x, pos.y, hCursor); - oldX = pos.x; - oldY = pos.y; -} -DWORD WINAPI FakeCursorDrawLoopThread(LPVOID lpParameter) -{ - printf("Fake cursor draw loop thread start\n"); - Proto::AddThreadToACL(GetCurrentThreadId()); - FakeCursor::state.StartDrawLoopInternal(); + DWORD WINAPI FakeCursorDrawLoopThread(LPVOID lpParameter) + { + printf("Fake cursor draw loop thread start\n"); + Proto::AddThreadToACL(GetCurrentThreadId()); + FakeCursor::state.StartDrawLoopInternal(); - return 0; -} + return 0; + } -void FakeCursor::StartDrawLoopInternal() -{ - int tick = 0; + void FakeCursor::StartDrawLoopInternal() + { + int tick = 0; - while (true) - { - std::unique_lock lock(mutex); - conditionvar.wait(lock); + while (true) + { + std::unique_lock lock(mutex); + conditionvar.wait(lock); - DrawCursor(); + DrawCursor(); - //TODO: is this ok? (might eat cpu) - Sleep(drawingEnabled ? 12 : 500); + //TODO: is this ok? (might eat cpu) + Sleep(drawingEnabled ? 12 : 500); - tick = (tick + 1) % 200; + tick = (tick + 1) % 200; - if (tick == 0) - // Nucleus can put the game window above the pointer without this - SetWindowPos(pointerWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE); - } -} + if (tick == 0) + // Nucleus can put the game window above the pointer without this + SetWindowPos(pointerWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE); + } + } -void FakeCursor::StartInternal() -{ - Proto::AddThreadToACL(GetCurrentThreadId()); + void FakeCursor::StartInternal() + { + Proto::AddThreadToACL(GetCurrentThreadId()); - const auto hInstance = GetModuleHandle(NULL); + const auto hInstance = GetModuleHandle(NULL); - // Like a green screen - transparencyBrush = (HBRUSH)CreateSolidBrush(transparencyKey); + // Like a green screen + transparencyBrush = (HBRUSH)CreateSolidBrush(transparencyKey); - WNDCLASS wc = { 0 }; - wc.lpfnWndProc = FakeCursorWndProc; - wc.hInstance = hInstance; - wc.hbrBackground = transparencyBrush; + WNDCLASS wc = { 0 }; + wc.lpfnWndProc = FakeCursorWndProc; + wc.hInstance = hInstance; + wc.hbrBackground = transparencyBrush; - std::srand(std::time(nullptr)); - const std::wstring classNameStr = std::wstring{ L"ProtoInputPointer" } + std::to_wstring(std::rand()); - const wchar_t* className = classNameStr.c_str(); + std::srand(std::time(nullptr)); + const std::wstring classNameStr = std::wstring{ L"ProtoInputPointer" } + std::to_wstring(std::rand()); + const wchar_t* className = classNameStr.c_str(); - wc.lpszClassName = className; - wc.style = CS_OWNDC | CS_NOCLOSE; + wc.lpszClassName = className; + wc.style = CS_OWNDC | CS_NOCLOSE; - if (!RegisterClass(&wc)) - { - fprintf(stderr, "Failed to open fake cursor window\n"); - } - else - { - pointerWindow = CreateWindowExW(WS_EX_NOACTIVATE | WS_EX_NOINHERITLAYOUT | WS_EX_NOPARENTNOTIFY | - WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW | WS_EX_LAYERED, - wc.lpszClassName, classNameStr.c_str(), 0, - 0, 0, 200, 200, - nullptr, nullptr, hInstance, nullptr); + if (!RegisterClass(&wc)) + { + fprintf(stderr, "Failed to open fake cursor window\n"); + } + else + { + pointerWindow = CreateWindowExW(WS_EX_NOACTIVATE | WS_EX_NOINHERITLAYOUT | WS_EX_NOPARENTNOTIFY | + WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW | WS_EX_LAYERED, + wc.lpszClassName, classNameStr.c_str(), 0, + 0, 0, 200, 200, + nullptr, nullptr, hInstance, nullptr); - SetWindowLongW(pointerWindow, GWL_STYLE, WS_VISIBLE | WS_DISABLED); - SetLayeredWindowAttributes(pointerWindow, transparencyKey, 0, LWA_COLORKEY); + SetWindowLongW(pointerWindow, GWL_STYLE, WS_VISIBLE | WS_DISABLED); + SetLayeredWindowAttributes(pointerWindow, transparencyKey, 0, LWA_COLORKEY); - // Nucleus can put the game window above the pointer without this - SetWindowPos(pointerWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE); + // Nucleus can put the game window above the pointer without this + SetWindowPos(pointerWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE); - // ShowWindow(pointerWindow, SW_SHOWDEFAULT); - // UpdateWindow(pointerWindow); - EnableDisableFakeCursor(drawingEnabled); + // ShowWindow(pointerWindow, SW_SHOWDEFAULT); + // UpdateWindow(pointerWindow); + EnableDisableFakeCursor(drawingEnabled); - // Over every screen - EnumDisplayMonitors(nullptr, nullptr, &EnumWindowsProc, 0); - MoveWindow(pointerWindow, fakeCursorMinX, fakeCursorMinY, fakeCursorMaxX - fakeCursorMinX, fakeCursorMaxY - fakeCursorMinY, TRUE); + // Over every screen + EnumDisplayMonitors(nullptr, nullptr, &EnumWindowsProc, 0); + MoveWindow(pointerWindow, fakeCursorMinX, fakeCursorMinY, fakeCursorMaxX - fakeCursorMinX, fakeCursorMaxY - fakeCursorMinY, TRUE); - hdc = GetDC(pointerWindow); + hdc = GetDC(pointerWindow); - //TODO: configurable cursor - hCursor = LoadCursorW(NULL, IDC_ARROW); + //TODO: configurable cursor + hCursor = LoadCursorW(NULL, IDC_ARROW); - const auto threadHandle = CreateThread(nullptr, 0, - (LPTHREAD_START_ROUTINE)FakeCursorDrawLoopThread, GetModuleHandle(0), 0, 0); + const auto threadHandle = CreateThread(nullptr, 0, + (LPTHREAD_START_ROUTINE)FakeCursorDrawLoopThread, GetModuleHandle(0), 0, 0); - if (threadHandle != nullptr) - CloseHandle(threadHandle); + if (threadHandle != nullptr) + CloseHandle(threadHandle); - // Want to avoid doing anything in the message loop that might cause it to not respond, as the entire screen will say not responding... - MSG msg; - ZeroMemory(&msg, sizeof(msg)); - while (msg.message != WM_QUIT) - { - if (GetMessageW(&msg, pointerWindow, 0U, 0U))// Blocks - { - TranslateMessage(&msg); - DispatchMessage(&msg); - continue; + // Want to avoid doing anything in the message loop that might cause it to not respond, as the entire screen will say not responding... + MSG msg; + ZeroMemory(&msg, sizeof(msg)); + while (msg.message != WM_QUIT) + { + if (GetMessageW(&msg, pointerWindow, 0U, 0U))// Blocks + { + TranslateMessage(&msg); + DispatchMessage(&msg); + continue; + } } } } -} -DWORD WINAPI FakeCursorThreadStart(LPVOID lpParameter) -{ - printf("Fake Cursor thread start\n"); - FakeCursor::state.StartInternal(); - return 0; -} + DWORD WINAPI FakeCursorThreadStart(LPVOID lpParameter) + { + printf("Fake Cursor thread start\n"); + FakeCursor::state.StartInternal(); + return 0; + } -void FakeCursor::EnableDisableFakeCursor(bool enable) -{ - state.drawingEnabled = enable; - - ShowWindow(state.pointerWindow, enable ? SW_SHOWDEFAULT : SW_HIDE); - UpdateWindow(state.pointerWindow); -} + void FakeCursor::EnableDisableFakeCursor(bool enable) + { + state.drawingEnabled = enable; -void FakeCursor::Initialise() -{ - const auto threadHandle = CreateThread(nullptr, 0, - (LPTHREAD_START_ROUTINE)FakeCursorThreadStart, GetModuleHandle(0), 0, 0); + ShowWindow(state.pointerWindow, enable ? SW_SHOWDEFAULT : SW_HIDE); + UpdateWindow(state.pointerWindow); + } + + void FakeCursor::Initialise() + { + const auto threadHandle = CreateThread(nullptr, 0, + (LPTHREAD_START_ROUTINE)FakeCursorThreadStart, GetModuleHandle(0), 0, 0); - if (threadHandle != nullptr) - CloseHandle(threadHandle); -} + if (threadHandle != nullptr) + CloseHandle(threadHandle); + } -} +} \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.h b/src/ProtoInput/ProtoInputHooks/FakeCursor.h index 0574f66..fcd30e7 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.h +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.h @@ -26,7 +26,8 @@ class FakeCursor int offsetSET; //0:sizing 1:offset 2:done int cursorWidth = 40; int cursorHeight = 40; - + 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; diff --git a/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp b/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp index a7a4198..2054676 100644 --- a/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp @@ -57,6 +57,7 @@ UINT WINAPI Hook_GetRawInputData( void GetRawInputDataHook::InstallImpl() { + MessageBoxA(NULL, "Installing GetRawInputData Hook", "Info", MB_OK); hookInfo = std::get<1>(InstallNamedHook(L"user32", "GetRawInputData", Hook_GetRawInputData)); } diff --git a/src/ProtoInput/ProtoInputHooks/HookManager.cpp b/src/ProtoInput/ProtoInputHooks/HookManager.cpp index 7570030..98bbca1 100644 --- a/src/ProtoInput/ProtoInputHooks/HookManager.cpp +++ b/src/ProtoInput/ProtoInputHooks/HookManager.cpp @@ -21,6 +21,8 @@ #include "MoveWindowHook.h" #include "AdjustWindowRectHook.h" #include "RemoveBorderHook.h" +#include "RawInput.h" +#include "TranslateXtoMKB.h" namespace Proto { @@ -30,37 +32,59 @@ HookManager HookManager::hookManagerInstance{}; HookManager::HookManager() { // Do these in exactly the same order as in ProtoHookIDs - AddHook(ProtoHookIDs::RegisterRawInputHookID); - AddHook(ProtoHookIDs::GetRawInputDataHookID); - AddHook(ProtoHookIDs::MessageFilterHookID); - AddHook(ProtoHookIDs::GetCursorPosHookID); - AddHook(ProtoHookIDs::SetCursorPosHookID); - AddHook(ProtoHookIDs::GetKeyStateHookID); - AddHook(ProtoHookIDs::GetAsyncKeyStateHookID); - AddHook(ProtoHookIDs::GetKeyboardStateHookID); - AddHook(ProtoHookIDs::CursorVisibilityStateHookID); - AddHook(ProtoHookIDs::ClipCursorHookID); - AddHook(ProtoHookIDs::FocusHooksHookID); - AddHook(ProtoHookIDs::RenameHandlesHookID); - AddHook(ProtoHookIDs::XinputHookID); - AddHook(ProtoHookIDs::DinputOrderHookID); - AddHook(ProtoHookIDs::SetWindowPosHookID); - AddHook(ProtoHookIDs::BlockRawInputHookID); - AddHook(ProtoHookIDs::FindWindowHookID); - AddHook(ProtoHookIDs::CreateSingleHIDHookID); - AddHook(ProtoHookIDs::WindowStyleHookID); - AddHook(ProtoHookIDs::MoveWindowHookID); - AddHook(ProtoHookIDs::AdjustWindowRectHookID); - AddHook(ProtoHookIDs::RemoveBorderHookID); + AddHook(ProtoHookIDs::RegisterRawInputHookID); //0 + AddHook(ProtoHookIDs::GetRawInputDataHookID); //1 + AddHook(ProtoHookIDs::MessageFilterHookID);//2 + AddHook(ProtoHookIDs::GetCursorPosHookID);//3 + AddHook(ProtoHookIDs::SetCursorPosHookID);//4 + AddHook(ProtoHookIDs::GetKeyStateHookID);//5 + AddHook(ProtoHookIDs::GetAsyncKeyStateHookID);//6 + AddHook(ProtoHookIDs::GetKeyboardStateHookID);//7 + AddHook(ProtoHookIDs::CursorVisibilityStateHookID);//8 + AddHook(ProtoHookIDs::ClipCursorHookID);//9 + AddHook(ProtoHookIDs::FocusHooksHookID);//10 + AddHook(ProtoHookIDs::RenameHandlesHookID);//11 + AddHook(ProtoHookIDs::XinputHookID);//12 + AddHook(ProtoHookIDs::DinputOrderHookID);//13 + AddHook(ProtoHookIDs::SetWindowPosHookID);//14 + AddHook(ProtoHookIDs::BlockRawInputHookID);//15 + AddHook(ProtoHookIDs::FindWindowHookID);//16 + AddHook(ProtoHookIDs::CreateSingleHIDHookID);//17 + AddHook(ProtoHookIDs::WindowStyleHookID);//18 + AddHook(ProtoHookIDs::MoveWindowHookID);//19 + AddHook(ProtoHookIDs::AdjustWindowRectHookID);//20 + AddHook(ProtoHookIDs::RemoveBorderHookID);//21 } void HookManager::InstallHook(ProtoHookIDs hookID) { + if (hookID < 0 || hookID >= hookManagerInstance.hooks.size()) std::cerr << "Trying to install hook ID " << hookID << " which is out of range" << std::endl; else { - hookManagerInstance.hooks[hookID]->Install(); + if (!RawInput::TranslateXinputtoMKB) + hookManagerInstance.hooks[hookID]->Install(); + else // skipping original protoinput hooks on experimental Xinput to MKB translation mode + { + if (hookID == 0) ScreenshotInput::TranslateXtoMKB::registerrawinputhook = 1; + if (hookID == 1) ScreenshotInput::TranslateXtoMKB::rawinputhook = 1; + if (hookID == 2) ScreenshotInput::TranslateXtoMKB::rawinputhook = 1; //messagefilter + if (hookID == 3) ScreenshotInput::TranslateXtoMKB::getcursorposhook = 1; + if (hookID == 4) ScreenshotInput::TranslateXtoMKB::setcursorposhook = 1; + if (hookID == 5) ScreenshotInput::TranslateXtoMKB::getkeystatehook = 1; + if (hookID == 6) ScreenshotInput::TranslateXtoMKB::getasynckeystatehook = 1; + if (hookID == 7) ScreenshotInput::TranslateXtoMKB::GetKeyboardStateHook = 1; + if (hookID == 8) { + ScreenshotInput::TranslateXtoMKB::showcursorhook = 1; + ScreenshotInput::TranslateXtoMKB::setcursorhook = 1; + } + if (hookID == 9) ScreenshotInput::TranslateXtoMKB::clipcursorhook = 1; + if (hookID > 9 && hookID != 15) //15 is block rawinput dont want that. + hookManagerInstance.hooks[hookID]->Install(); + + } + } } @@ -70,6 +94,9 @@ void HookManager::UninstallHook(ProtoHookIDs hookID) std::cerr << "Trying to uninstall hook ID " << hookID << " which is out of range" << std::endl; else { + if (!RawInput::TranslateXinputtoMKB) + hookManagerInstance.hooks[hookID]->Uninstall(); + else if (hookID > 9) // skipping original protoinput hooks on experimental Xinput to MKB translation mode hookManagerInstance.hooks[hookID]->Uninstall(); } } @@ -83,7 +110,11 @@ bool HookManager::IsInstalled(ProtoHookIDs hookID) } else { - return hookManagerInstance.hooks[hookID]->IsInstalled(); + if (!RawInput::TranslateXinputtoMKB) + return hookManagerInstance.hooks[hookID]->IsInstalled(); + else if (hookID < 10) return true; + else return hookManagerInstance.hooks[hookID]->IsInstalled(); + } } diff --git a/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp b/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp index ab38d6a..a957af4 100644 --- a/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp +++ b/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp @@ -2,6 +2,7 @@ #include "HwndSelector.h" #include #include "FakeCursor.h" +#include "TranslateXtoMKB.h" namespace Proto @@ -24,7 +25,8 @@ BOOL IsMainWindow(HWND handle) IsWindowVisible(handle) && handle != (HWND)Proto::ConsoleHwnd && handle != Proto::ProtoGuiHwnd && - handle != FakeCursor::GetPointerWindow(); + handle != FakeCursor::GetPointerWindow() && + handle != ScreenshotInput::TranslateXtoMKB::pointerWindows; } BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index 4904b8f..04d0a5a 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -26,6 +26,7 @@ #include "MoveWindowHook.h" #include "AdjustWindowRectHook.h" #include "RemoveBorderHook.h" +#include "TranslateXtoMKB.h" namespace Proto { @@ -76,6 +77,7 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) } while (pipe == INVALID_HANDLE_VALUE); + bool gotkeyboardmouse = false; if (pipe != INVALID_HANDLE_VALUE) { printf("Successfully connected pipe \"%ws\"\n", pipeName.c_str()); @@ -124,17 +126,52 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) switch(msgHeader.messageType) { - case ProtoPipe::PipeMessageType::SetupHook: + + case ProtoPipe::PipeMessageType::AddSelectedMouseOrKeyboard: + { + const auto body = reinterpret_cast(messageBuffer); + + printf("Received message select mouse %d, keyboard %d\n", body->mouse, body->keyboard); + + if (body->mouse != -1) { - const auto body = reinterpret_cast(messageBuffer); - printf("Setup hook message: hook ID %d, install = %d\n", body->hookID, body->install); - if (body->install) - HookManager::InstallHook(body->hookID); - else - HookManager::UninstallHook(body->hookID); + gotkeyboardmouse = true; + RawInput::AddSelectedMouseHandle(body->mouse); + } + - break; + if (body->keyboard != -1) + { + gotkeyboardmouse = true; + RawInput::AddSelectedKeyboardHandle(body->keyboard); + } + + break; + } + case ProtoPipe::PipeMessageType::SetTranslateXinputtoMKB: + { + const auto body = reinterpret_cast(messageBuffer); + RawInput::TranslateXinputtoMKB = body->TranslateXinputtoMKB; + if (RawInput::TranslateXinputtoMKB == true) + { + if (gotkeyboardmouse) + { + RawInput::TranslateXinputtoMKB = false; + //MessageBoxA(NULL, "OOOhhhh, there is a mouse here. disabling", "tunell", MB_OK | MB_ICONWARNING); + } } + break; + } + case ProtoPipe::PipeMessageType::SetupHook: + { + const auto body = reinterpret_cast(messageBuffer); + printf("Setup hook message: hook ID %d, install = %d\n", body->hookID, body->install); + if (body->install) + HookManager::InstallHook(body->hookID); + else + HookManager::UninstallHook(body->hookID); + break; + } case ProtoPipe::PipeMessageType::SetupMessageFilter: { const auto body = reinterpret_cast(messageBuffer); @@ -287,6 +324,10 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) printf("Received message to %s fake cursor\n", body->enable ? "enable" : "disable"); FakeCursor::EnableDisableFakeCursor(body->enable); + if (body->enable) //1 game hdc //2 partial draw //3 full draw + ScreenshotInput::TranslateXtoMKB::drawfakecursor = 3; + else + ScreenshotInput::TranslateXtoMKB::drawfakecursor = 0; break; } @@ -295,7 +336,7 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) const auto body = reinterpret_cast(messageBuffer); printf("Received message to %s fake cursor fix\n", body->enable ? "enable" : "disable"); - + // Not sure about this... FakeCursor::state.DrawFakeCursorFix = body->enable; @@ -311,20 +352,7 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) break; } - case ProtoPipe::PipeMessageType::AddSelectedMouseOrKeyboard: - { - const auto body = reinterpret_cast(messageBuffer); - - printf("Received message select mouse %d, keyboard %d\n", body->mouse, body->keyboard); - if (body->mouse != -1) - RawInput::AddSelectedMouseHandle(body->mouse); - - if (body->keyboard != -1) - RawInput::AddSelectedKeyboardHandle(body->keyboard); - - break; - } case ProtoPipe::PipeMessageType::AddHandleToRename: { const auto body = reinterpret_cast(messageBuffer); @@ -348,7 +376,10 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) XinputHook::controllerIndex2 = body->controllerIndex2; XinputHook::controllerIndex3 = body->controllerIndex3; XinputHook::controllerIndex4 = body->controllerIndex4; - + if (RawInput::TranslateXinputtoMKB == true) + { + ScreenshotInput::TranslateXtoMKB::controllerID = XinputHook::controllerIndex; + } break; } case ProtoPipe::PipeMessageType::SetUseDinput: diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj index ee51cdc..cee13be 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj @@ -235,6 +235,7 @@ + @@ -286,6 +287,7 @@ + diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters index 624e681..043b5e9 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters @@ -28,6 +28,9 @@ {14e41680-f011-4d2c-b31b-3fd2d6ae9a52} + + {a0d1a945-2bce-40dd-88b8-54724cf1b678} + @@ -180,6 +183,9 @@ Source Files\Hooks + + Source Files\Hooks\TranslateXtoMKB + @@ -323,5 +329,8 @@ Source Files\Hooks + + Source Files\Hooks\TranslateXtoMKB + \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.cpp b/src/ProtoInput/ProtoInputHooks/RawInput.cpp index a05f0d1..d2ef14f 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.cpp +++ b/src/ProtoInput/ProtoInputHooks/RawInput.cpp @@ -15,6 +15,7 @@ #include "protoinpututil.h" #include "KeyboardButtonFilter.h" #include "MessageFilterHook.h" +#include "TranslateXtoMKB.h" namespace Proto { @@ -25,11 +26,9 @@ std::vector RawInput::forwardingWindows{}; bool RawInput::forwardRawInput = true; bool RawInput::lockInputToggleEnabled = false; bool RawInput::rawInputBypass = false; - - RAWINPUT RawInput::inputBuffer[RawInputBufferSize]{}; std::vector RawInput::rawinputs{}; - +bool RawInput::TranslateXinputtoMKB; const std::vector RawInput::usageTypesOfInterest { HID_USAGE_GENERIC_POINTER, @@ -114,14 +113,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); } } @@ -439,9 +444,9 @@ DWORD WINAPI RawInputWindowThread(LPVOID lpParameter) printf("Starting Raw Input window thread\n"); AddThreadToACL(GetCurrentThreadId()); - + const auto hinstance = GetModuleHandle(nullptr); - + WNDCLASS wc = { 0 }; wc.lpfnWndProc = RawInputWindowWndProc; wc.hInstance = hinstance; @@ -477,7 +482,7 @@ DWORD WINAPI RawInputWindowThread(LPVOID lpParameter) if (GetMessage(&msg, RawInput::rawInputHwnd, WM_INPUT, WM_INPUT)) { // if (msg.message == WM_INPUT) - { + { RawInput::ProcessRawInput((HRAWINPUT)msg.lParam, GET_RAWINPUT_CODE_WPARAM(msg.wParam) == RIM_INPUT, msg); } @@ -501,17 +506,17 @@ void RawInput::RefreshDevices() const auto oldKbCount = rawInputState.keyboardHandles.size(); const auto oldMouseCount = rawInputState.mouseHandles.size(); - + rawInputState.keyboardHandles.clear(); rawInputState.mouseHandles.clear(); - + std::cout << "Raw input devices:\n"; for (unsigned int i = 0; i < numDevices; ++i) { auto* device = &deviceArray[i]; std::cout << (device->dwType == RIM_TYPEHID ? "HID" : device->dwType == RIM_TYPEKEYBOARD ? "Keyboard" : "Mouse") << ": " << device->hDevice << std::endl; - + if (device->dwType == RIM_TYPEKEYBOARD) { rawInputState.keyboardHandles.push_back(device->hDevice); @@ -555,7 +560,7 @@ void RawInput::RefreshDevices() if (std::find(rawInputState.mouseHandles.begin(), rawInputState.mouseHandles.end(), rawInputState.deselectedMouseHandles[i]) == rawInputState.mouseHandles.end()) rawInputState.deselectedMouseHandles.erase(rawInputState.deselectedMouseHandles.begin() + i); } - + for (int i = rawInputState.selectedKeyboardHandles.size() - 1; i >= 0; --i) { if (std::find(rawInputState.keyboardHandles.begin(), rawInputState.keyboardHandles.end(), rawInputState.selectedKeyboardHandles[i]) == rawInputState.keyboardHandles.end()) @@ -614,11 +619,15 @@ std::bitset<9> RawInput::GetUsageBitField() void RawInput::InitialiseRawInput() { RefreshDevices(); + if (!RawInput::TranslateXinputtoMKB) + { - HANDLE hThread = CreateThread(nullptr, 0, - (LPTHREAD_START_ROUTINE)RawInputWindowThread, GetModuleHandle(nullptr), 0, 0); - if (hThread != nullptr) - CloseHandle(hThread); + HANDLE hThread = CreateThread(nullptr, 0, + (LPTHREAD_START_ROUTINE)RawInputWindowThread, GetModuleHandle(nullptr), 0, 0); + if (hThread != nullptr) + CloseHandle(hThread); + } + return; } void RawInput::UnregisterGameFromRawInput() diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.h b/src/ProtoInput/ProtoInputHooks/RawInput.h index dbdc7fd..7a9af34 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.h +++ b/src/ProtoInput/ProtoInputHooks/RawInput.h @@ -47,6 +47,7 @@ class RawInput static RawInputState rawInputState; static HWND rawInputHwnd; static bool forwardRawInput; + static bool TranslateXinputtoMKB; // Passes input from all devices to the game. Proto Input doesn't process anything static bool rawInputBypass; diff --git a/src/ProtoInput/ProtoInputHooks/RegisterRawInputHook.cpp b/src/ProtoInput/ProtoInputHooks/RegisterRawInputHook.cpp index 1d453e1..cf74591 100644 --- a/src/ProtoInput/ProtoInputHooks/RegisterRawInputHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/RegisterRawInputHook.cpp @@ -156,22 +156,22 @@ void RegisterRawInputHook::ShowGuiStatus() void RegisterRawInputHook::InstallImpl() { - if (!installedAtLeastOnce) - { - installedAtLeastOnce = true; - std::bitset<9> usages{}; - // usages[HID_USAGE_GENERIC_MOUSE] = true; - // usages[HID_USAGE_GENERIC_KEYBOARD] = true; - RawInput::SetUsageBitField(usages); - } - auto [status, _hookInfo] = InstallNamedHook(L"user32", "RegisterRawInputDevices", Hook_RegisterRawInputDevices); - this->hookInfo = _hookInfo; - - FindAlreadySubscribedWindows(); + if (!installedAtLeastOnce) + { + installedAtLeastOnce = true; + std::bitset<9> usages{}; + // usages[HID_USAGE_GENERIC_MOUSE] = true; + // usages[HID_USAGE_GENERIC_KEYBOARD] = true; + RawInput::SetUsageBitField(usages); + } - RawInput::UnregisterGameFromRawInput(); - RawInput::RegisterProtoForRawInput(); + auto [status, _hookInfo] = InstallNamedHook(L"user32", "RegisterRawInputDevices", Hook_RegisterRawInputDevices); + this->hookInfo = _hookInfo; + + FindAlreadySubscribedWindows(); + RawInput::UnregisterGameFromRawInput(); + RawInput::RegisterProtoForRawInput(); } void RegisterRawInputHook::UninstallImpl() diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp new file mode 100644 index 0000000..bb99821 --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -0,0 +1,4094 @@ +//#include "XinputHook.h" +//#include +#include +#include "Gui.h" +#include +//#include "OpenXinputWrapper.h" +#include "TranslateXtoMKB.h" +#include "RawInput.h" +#include +#include +#define NOMINMAX +#include +#include +#include "EasyHook.h" +#include +#include +#include +#include +#include // for swprintf +#include +#include // For strtoul +#include +#include +#include +#include "HwndSelector.h" +//#include "RawInput.h" +//#include +#pragma comment(lib, "dwmapi.lib") + +//#include "dllmain.h" +//#include "PostKeyFunction.cpp" + +#pragma comment(lib, "Xinput.lib") + +namespace ScreenshotInput +{ + + std::vector staticPointA; + std::vector staticPointB; + std::vector staticPointX; + std::vector staticPointY; + + int scanAtype = 0; + int scanBtype = 0; + int scanXtype = 0; + int scanYtype = 0; + bool showcursorcounter = true; + int AxisLeftsens; + int AxisRightsens; + int AxisUpsens; + int AxisDownsens; + int scrollspeed3; + + + int InitialMode; + int Modechange; + int sendfocus; + int responsetime; + int doubleclicks; + int scrollenddelay; + int quickMW; + bool inithere = false; + int ShoulderNextbmp; + + int scrolloutsidewindow; + int mode = InitialMode; + ///////////////// + bool movedmouse; + + HOOK_TRACE_INFO GETcursorpos = { NULL }; + HOOK_TRACE_INFO SETcursorpos = { NULL }; + HOOK_TRACE_INFO GETkeyboardstate = { NULL }; + HOOK_TRACE_INFO GETasynckeystate = { NULL }; + HOOK_TRACE_INFO GETkeystate = { NULL }; + HOOK_TRACE_INFO CLIPcursor = { NULL }; + HOOK_TRACE_INFO SETcursor = { NULL }; + HOOK_TRACE_INFO g_HookShowCursorHandle = { NULL }; + HOOK_TRACE_INFO GETcursorinfo = { NULL }; + + HOOK_TRACE_INFO SETrect = { NULL }; + HOOK_TRACE_INFO ADJUSTwindowrect = { NULL }; + + HOOK_TRACE_INFO GETrawinputdata = { NULL }; + HOOK_TRACE_INFO REGISTERrawinputdevices = { NULL }; + + HOOK_TRACE_INFO GETmessagea = { NULL }; + HOOK_TRACE_INFO GETmessagew = { NULL }; + HOOK_TRACE_INFO PEEKmessagea = { NULL }; + HOOK_TRACE_INFO PEEKmessagew = { NULL }; + HMODULE g_hModule = nullptr; + + bool rawmouseL = false; + bool rawmouseR = false;//0:scroll 1:left 2:right 3:up 4:down + std::vector keyState(256, 0); + CRITICAL_SECTION critical; //window thread + + POINT fakecursorW; + POINT startdrag; + POINT activatewindow; + POINT scroll; + bool loop = true; + HWND hwnd; + int showmessage = 0; //0 = no message, 1 = initializing, 2 = bmp mode, 3 = bmp and cursor mode, 4 = edit mode + int showmessageW = 0; //0 = no message, 1 = initializing, 2 = bmp mode, 3 = bmp and cursor mode, 4 = edit mode + int counter = 0; + bool scanrunning = false; + bool keys[256] = { false }; + + //syncronization control + HANDLE hMutex; + + int getmouseonkey = 0; + int message = 0; + auto hInstance = nullptr; + + POINT delta; + //hooks + bool hooksenabled = false; + bool hooksinited = false; + int keystatesend = 0; //key to send + int TranslateXtoMKB::clipcursorhook = 0; + int TranslateXtoMKB::getkeystatehook = 0; + int TranslateXtoMKB::getasynckeystatehook = 0; + int TranslateXtoMKB::getcursorposhook = 0; + int TranslateXtoMKB::setcursorposhook = 0; + int TranslateXtoMKB::setcursorhook = 0; + int TranslateXtoMKB::rawinputhook = 0; + int TranslateXtoMKB::GetKeyboardStateHook = 0; + bool TranslateXtoMKB::registerrawinputhook = 0; + int TranslateXtoMKB::showcursorhook = 0; + bool nodrawcursor = false; + + int ignorerect = 0; + POINT rectignore = { 0,0 }; //for getcursorposhook + int setrecthook = 0; + + int leftrect = 0; + int toprect = 0; + int rightrect = 0; + int bottomrect = 0; + + int resize = 1; + int numphotoA = -1; + int numphotoB = -1; + int numphotoX = -1; + int numphotoY = -1; + int numphotoC = -1; + int numphotoD = -1; + int numphotoE = -1; + int numphotoF = -1; + + int numphotoAbmps; + int numphotoBbmps; + int numphotoXbmps; + int numphotoYbmps; + + bool AuseStatic = 1; + bool BuseStatic = 1; + bool XuseStatic = 1; + bool YuseStatic = 1; + + //fake cursor + int TranslateXtoMKB::controllerID; + int Xf = 100; + int Yf = 100; + int OldX = 0; + int OldY = 0; + int ydrag; + int xdrag; + int Xoffset = 0; //offset for cursor + int Yoffset = 0; + bool scrollmap = false; + bool pausedraw = false; + bool gotcursoryet = false; + int TranslateXtoMKB::drawfakecursor; + int alwaysdrawcursor = 0; //always draw cursor even if setcursor set cursor NULL + HICON hCursor = 0; + DWORD lastClickTime; + HDC PointerWnd; + int WoldX, WoldY; + + //bmp search + bool foundit = false; + int hooksoninit = 0; + + int cursoroffsetx, cursoroffsety; + int offsetSET; //0:sizing 1:offset 2:done + int cursorWidth = 40; + int cursorHeight = 40; + HWND ScreenshotInput::TranslateXtoMKB::pointerWindows = nullptr; + bool DrawFakeCursorFix = false; + static int transparencyKey = RGB(0, 0, 1); + + //setwindowpos + int posX; + int posY; + int resX; + int resY; + HCURSOR oldhCursor = NULL; + HCURSOR hCursorW = NULL; + bool nochange = false; + + bool oldHadShowCursor = true; + + const extern WPARAM ScreenshotInput_MOUSE_SIGNATURE = 0x10000000; + const extern LPARAM ScreenshotInput_KEYBOARD_SIGNATURE = 0x10000000; + bool g_filterRawInput = false; + bool g_filterMouseMove = false; + bool g_filterMouseActivate = false; + bool g_filterWindowActivate = false; + bool g_filterWindowActivateApp = false; + bool g_filterMouseWheel = false; + bool g_filterMouseButton = true; + bool g_filterKeyboardButton = false; + + POINT oldposcheck; + POINT oldrescheck; + + //scroll type 3 + int tick = 0; + bool doscrollyes = false; + + bool onoroff = true; + + //remember old keystates + int oldscrollrightaxis = false; //reset + int oldscrollleftaxis = false; //reset + int oldscrollupaxis = false; //reset + int oldscrolldownaxis = false; //reset + bool Apressed = false; + bool Bpressed = false; + bool Xpressed = false; + bool Ypressed = false; + bool leftPressedold; + bool rightPressedold; + bool oldA = false; + bool oldB = false; + bool oldX = false; + bool oldY = false; + bool oldC = false; + bool oldD = false; + bool oldE = false; + bool oldF = false; + bool oldup = false; + bool olddown = false; + bool oldleft = false; + bool oldright = false; + + float radial_deadzone = 0.10f; // Circular/Radial Deadzone (0.0 to 0.3) + float axial_deadzone = 0.00f; // Square/Axial Deadzone (0.0 to 0.3) + const float max_threshold = 0.03f; // Max Input Threshold, an "outer deadzone" (0.0 to 0.15) + const float curve_slope = 0.16f; // The linear portion of the response curve (0.0 to 1.0) + const float curve_exponent = 5.00f; // The exponential portion of the curve (1.0 to 10.0) + float sensitivity = 12.00f; // Base sensitivity / max speed (1.0 to 30.0) + float accel_multiplier = 1.90f; // Look Acceleration Multiplier (1.0 to 3.0) + + bool musLB = false; + bool musRB = false; + bool rawmouseWu = false; + bool rawmouseWd = false; + + int startsearch = 0; + int startsearchA = 0; + int startsearchB = 0; + int startsearchX = 0; + int startsearchY = 0; + int startsearchC = 0; + int startsearchD = 0; + int startsearchE = 0; + int startsearchF = 0; + int skipintro = 0; + int righthanded = 0; + int scanoption = 0; + + int Atype = 0; + int Btype = 0; + int Xtype = 0; + int Ytype = 0; + int Ctype = 0; + int Dtype = 0; + int Etype = 0; + int Ftype = 0; + + POINT PointA; + POINT PointB; + POINT PointX; + POINT PointY; + + int scantick = 0; + int findwindowdelay = 0; + int bmpAtype = 0; + int bmpBtype = 0; + int bmpXtype = 0; + int bmpYtype = 0; + int bmpCtype = 0; + int bmpDtype = 0; + int bmpEtype = 0; + int bmpFtype = 0; + + int uptype = 0; + int downtype = 0; + int lefttype = 0; + int righttype = 0; + + + int x = 0; + + HBITMAP hbm; + + std::vector largePixels, smallPixels; + SIZE screenSize; + int strideLarge, strideSmall; + int smallW, smallH; + + //int sovetid = 16; + int knappsovetid = 100; + + int samekey = 0; + int samekeyA = 0; + INT WINAPI HookedShowCursor(BOOL bShow) + { //not called? + if (bShow) + { + showcursorcounter = true; + } + else + { + showcursorcounter = false; + } + return ShowCursor(bShow); + } + + HCURSOR WINAPI HookedSetCursor(HCURSOR hcursor) { + EnterCriticalSection(&critical); + hCursor = hcursor; // Store the cursor handle + + hcursor = SetCursor(hcursor); + LeaveCriticalSection(&critical); + return hcursor; + } + ////SetRect_t)(LPRECT lprc, int xLeft, int yTop, int xRight, int yBottom); + BOOL WINAPI HookedSetRect(LPRECT lprc, int xLeft, int yTop, int xRight, int yBottom) { + xLeft = leftrect; // Set the left coordinate to Xrect + yTop = toprect; // Set the top coordinate to Yrect + + xRight = rightrect; // Set the right coordinate to Xrect + 10 + yBottom = bottomrect; // Set the bottom coordinate to Yrect + 10 + + + bool result = SetRect(lprc, xLeft, yTop, xRight, yBottom); + return result; + } + + BOOL WINAPI HookedAdjustWindowRect(LPRECT lprc, DWORD dwStyle, BOOL bMenu) { + lprc->top = toprect; // Set the left coordinate to Xrect + lprc->bottom = bottomrect; // Set the left coordinate to Xrect + lprc->left = leftrect; // Set the left coordinate to Xrect + lprc->right = rightrect; // Set the left coordinate to Xrect + + bool result = AdjustWindowRect(lprc, dwStyle, bMenu); + return result; + } + + SHORT WINAPI HookedGetAsyncKeyState(int vKey) + { + if (keys[vKey] == true) { + return 0x8000; // key is down + } + else { + return 0x0000; // key is up + } + } + + HWND g_rawInputHwnd = nullptr; + + const int RAWINPUT_BUFFER_SIZE = 20; + RAWINPUT g_inputBuffer[RAWINPUT_BUFFER_SIZE]{}; + //std::vector g_forwardingWindows{}; + // Global/static counter + struct FakeKey { + USHORT vkey; + bool press; + }; + + static std::vector g_fakeKeys; + + // Add a fake key event to the array + void GenerateRawKey(USHORT vk, bool press) { + g_fakeKeys.push_back({ vk, press }); + if (vk < 256) { + if (press) { + keys[vk] = true; // mark as "down" + } + else { + keys[vk] = false; // clear "down" bit + } + } + } + + BOOL WINAPI HookedGetKeyboardState(PBYTE lpKeyState) { + if (!lpKeyState) { + return FALSE; + } + + // Call the original function to get real states //disabled cause of testing + // BOOL result = fpGetKeyboardState(lpKeyState); + memset(lpKeyState, 0, 256); + // Overlay fake states + for (int vk = 0; vk < 256; ++vk) { + if (keys[vk] == true) { + lpKeyState[vk] |= 0x80; // force down + } + else { //not needed if fpGetKeyboardState + lpKeyState[vk] &= ~0x80; // force up + } + } + + return TRUE; + } + + + UINT WINAPI HookedGetRawInputData( + HRAWINPUT hRawInput, + UINT uiCommand, + LPVOID pData, + PUINT pcbSize, + UINT cbSizeHeader + ) { + // Call the original function + UINT result = GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader); + + if (uiCommand == RID_INPUT && pData != nullptr) { + RAWINPUT* raw = (RAWINPUT*)pData; + // raw->header.wParam = RIM_INPUT; // Ensure wParam indicates input + if (raw->header.dwType == RIM_TYPEMOUSE && raw->header.wParam == RIM_INPUT) { + + // if (delta.x !=0) + raw->data.mouse.lLastX =delta.x; + // if (delta.y != 0) + raw->data.mouse.lLastY =delta.y; + + if (rawmouseR == true || rawmouseL == true || rawmouseWd == true || rawmouseWu == true) + raw->data.mouse.usButtonFlags = 0; + + if (rawmouseR == true) + raw->data.mouse.usButtonFlags |= RI_MOUSE_RIGHT_BUTTON_DOWN; + else + raw->data.mouse.usButtonFlags |= RI_MOUSE_RIGHT_BUTTON_UP; + + if (rawmouseL == true) + raw->data.mouse.usButtonFlags |= RI_MOUSE_LEFT_BUTTON_DOWN; + else + raw->data.mouse.usButtonFlags |= RI_MOUSE_LEFT_BUTTON_UP; + + + + if (rawmouseWd == true) + { + raw->data.mouse.usButtonFlags |= RI_MOUSE_WHEEL; + raw->data.mouse.usButtonData = -120; + } + else if (rawmouseWu == true) + { + raw->data.mouse.usButtonFlags |= RI_MOUSE_WHEEL; + raw->data.mouse.usButtonData = 120; + } + + } + if (raw->header.dwType == RIM_TYPEKEYBOARD && !g_fakeKeys.empty()) { + // Take the first fake key from the array + FakeKey fk = g_fakeKeys.front(); + g_fakeKeys.erase(g_fakeKeys.begin()); + + raw->data.keyboard.VKey = fk.vkey; + raw->data.keyboard.MakeCode = MapVirtualKey(fk.vkey, MAPVK_VK_TO_VSC); + raw->data.keyboard.Flags = fk.press ? RI_KEY_MAKE : RI_KEY_BREAK; + raw->data.keyboard.Message = fk.press ? WM_KEYDOWN : WM_KEYUP; + } + + } + + return result; + } + + void ForceRawInputPoll() //global all processes + { + INPUT input = { 0 }; + input.type = INPUT_MOUSE; + input.mi.dx = 0; + input.mi.dy = 0; + input.mi.dwFlags = MOUSEEVENTF_MOVE; // relative move + SendInput(1, &input, sizeof(INPUT)); + input.type = INPUT_KEYBOARD; + input.ki.wVk = VK_OEM_PERIOD; + input.ki.dwFlags = KEYEVENTF_KEYUP; + SendInput(1, &input, sizeof(INPUT)); + } + // Hooked GetKeyState + SHORT WINAPI HookedGetKeyState(int nVirtKey) { + if (keys[nVirtKey] == true) { + return 0x8000; // key is down + } + else { + return 0x0000; // key is up + } + } + + BOOL WINAPI MyGetCursorPos(PPOINT lpPoint) { + if (lpPoint) + { + POINT mpos; + mpos.y = Yf; + mpos.x = Xf; + + if (scrollmap == false) + { + + if (ignorerect == 1) { + mpos.x = Xf + rectignore.x; //hwnd coordinates 0-800 on a 800x600 window + mpos.y = Yf + rectignore.y;//hwnd coordinate s0-600 on a 800x600 window + lpPoint->x = mpos.x; + lpPoint->y = mpos.y; + } + else { + if (hwnd) + { + ClientToScreen(hwnd, &mpos); + } + lpPoint->x = mpos.x; + lpPoint->y = mpos.y; + } + } + + else + { + mpos.x = scroll.x; + mpos.y = scroll.y; + if (hwnd) + { + ClientToScreen(hwnd, &mpos); + } + + lpPoint->x = mpos.x; + lpPoint->y = mpos.y; + } + return TRUE; + } + return FALSE; + } + POINT mpos; + BOOL WINAPI MySetCursorPos(int X, int Y) { + if (hwnd) + { + POINT point; + point.x = X; + point.y = Y; + ScreenToClient(hwnd, &point); + Xf = point.x; + Yf = point.y; + } + return TRUE; //fpSetCursorPos(lpPoint); // Call the original SetCursorPos function + } + BOOL WINAPI HookedClipCursor(const RECT* lpRect) { + return true; //nonzero bool or int + //return originalClipCursor(nullptr); + + } + POINT windowpos(HWND window, int ignorerect, bool getpos) //return pos if true + { + if (ignorerect == 0) + { + POINT pos = { 0,0 }; + RECT recte; + GetClientRect(window, &recte); + if (getpos) { + pos.x = recte.left; + pos.y = recte.top; + ClientToScreen(window, &pos); + } + else { + pos.x = recte.right; //- recte.left; + pos.y = recte.bottom; //- recte.top; + } + return pos; + } + else + { + POINT pos = { 0,0 }; + RECT frameBounds; + HRESULT hr = DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frameBounds, sizeof(frameBounds)); + if (SUCCEEDED(hr)) + { + if (getpos) + { + pos.x = frameBounds.left; + pos.y = frameBounds.top; + } + else + { + pos.x = frameBounds.right - frameBounds.left; + pos.y = frameBounds.bottom - frameBounds.top; + } + } + return pos; + } + } + POINT GetStaticFactor(POINT pp, int doscale, bool isnotbmp) + { + // FLOAT ny; + POINT currentres = windowpos(hwnd, ignorerect, false); + FLOAT currentwidth = static_cast(currentres.x); + FLOAT currentheight = static_cast(currentres.y); + if (doscale == 1) + { + float scalex = currentwidth / 1024.0f; + float scaley = currentheight / 768.0f; + + pp.x = static_cast(std::lround(pp.x * scalex)); + pp.y = static_cast(std::lround(pp.y * scaley)); + } + if (doscale == 2) //4:3 blackbar only x + { + float difference = 0.0f; + float newwidth = currentwidth; + float curraspect = currentheight / currentwidth; + if (curraspect < 0.75f) + { + newwidth = currentheight / 0.75f; + if (isnotbmp) //cant pluss blackbars on bmps + difference = (currentwidth - newwidth) / 2; + } + float scalex = newwidth / 1024.0f; + float scaley = currentheight / 768.0f; + pp.x = static_cast(std::lround(pp.x * scalex) + difference); + pp.y = static_cast(std::lround(pp.y * scaley)); + } + if (doscale == 3) //only vertical stretch equal + { + float difference = 0.0f; + float newwidth = currentwidth; + float curraspect = currentheight / currentwidth; + if (curraspect < 0.5625f) + { + newwidth = currentheight / 0.5625f; + if (isnotbmp) //cant pluss blackbars on bmps + difference = (currentwidth - newwidth) / 2; + } + float scalex = newwidth / 1337.0f; + float scaley = currentheight / 768.0f; + pp.x = static_cast(std::lround(pp.x * scalex) + difference); + pp.y = static_cast(std::lround(pp.y * scaley)); + } + return pp; + } + bool Mutexlock(bool lock) { + // Create a named mutex + if (lock == true) + { + hMutex = CreateMutexA( + NULL, // Default security + FALSE, // Initially not owned + "Global\\PuttingInputByMessenils" // Name of mutex + ); + if (hMutex == NULL) { + std::cerr << "CreateMutex failed: " << GetLastError() << std::endl; + MessageBoxA(NULL, "Error!", "Failed to create mutex", MB_OK | MB_ICONINFORMATION); + return false; + } + // Check if mutex already exists + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + Sleep(5); + ReleaseMutex(hMutex); + CloseHandle(hMutex); + Mutexlock(true); //is this okay? + + } + } + if (lock == false) + { + ReleaseMutex(hMutex); + + CloseHandle(hMutex); + // hMutex = nullptr; // Optional: Prevent dangling pointer + + } + return true; + } + BOOL WINAPI HookedRegisterRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize) + { + // Modify all devices in the array + // MessageBoxA(NULL, "RegisterRawInputDevices Hooked!", "Info", MB_OK | MB_ICONINFORMATION); + for (UINT i = 0; i < uiNumDevices; ++i) { + pRawInputDevices[i].dwFlags |= RIDEV_INPUTSINK; + } + BOOL result = RegisterRawInputDevices(pRawInputDevices, uiNumDevices, cbSize); + // if (pRawInputDevices[0].hwndTarget != NULL) //if null follow keyboard focus + // hwnd = pRawInputDevices[0].hwndTarget; + // if (result == FALSE) + // { + // MessageBoxA(NULL, "RegisterRawInputDevices failed!", "Error", MB_OK | MB_ICONERROR); + //} + return result; + } + void EnableHooks() + { + if (TranslateXtoMKB::getcursorposhook == 1 || TranslateXtoMKB::getcursorposhook == 2) { + ULONG ACLEntries[1] = { 0 }; + LhSetExclusiveACL(ACLEntries, 1, &GETcursorpos); + } + if (TranslateXtoMKB::setcursorposhook == 1) { + ULONG ACLEntries[1] = { 0 }; + LhSetExclusiveACL(ACLEntries, 1, &SETcursorpos); + } + if (TranslateXtoMKB::getkeystatehook == 1) { + ULONG ACLEntries[1] = { 0 }; + LhSetExclusiveACL(ACLEntries, 1, &GETkeystate); + } + if (TranslateXtoMKB::getasynckeystatehook == 1) { + ULONG ACLEntries[1] = { 0 }; LhSetExclusiveACL(ACLEntries, 1, &GETasynckeystate); + } + if (TranslateXtoMKB::clipcursorhook == 1) { + ULONG ACLEntries[1] = { 0 }; LhSetExclusiveACL(ACLEntries, 1, &CLIPcursor); + } + if (setrecthook == 1) { + ULONG ACLEntries[1] = { 0 }; + LhSetExclusiveACL(ACLEntries, 1, &SETrect); + LhSetExclusiveACL(ACLEntries, 1, &ADJUSTwindowrect); + } + if (TranslateXtoMKB::setcursorhook == 1) + { + ULONG ACLEntries[1] = { 0 }; + LhSetExclusiveACL(ACLEntries, 1, &SETcursor); + } + if (TranslateXtoMKB::rawinputhook == 1 || TranslateXtoMKB::rawinputhook == 2) + { + ULONG ACLEntries[1] = { 0 }; + LhSetExclusiveACL(ACLEntries, 1, &GETrawinputdata); + } + if (TranslateXtoMKB::GetKeyboardStateHook == 1) + { + ULONG ACLEntries[1] = { 0 }; + LhSetExclusiveACL(ACLEntries, 1, &GETkeyboardstate); + } + // if (registerrawinputhook) + // { + // ULONG ACLEntries[1] = { 0 }; + // LhSetExclusiveACL(ACLEntries, 1, ®ISTERrawinputdevices); + // } + if (g_filterRawInput || g_filterMouseMove || g_filterMouseActivate || g_filterWindowActivate + || g_filterWindowActivateApp || g_filterMouseWheel || g_filterMouseButton || g_filterKeyboardButton) // If one of them is enabled + { + ULONG ACLEntries[1] = { 0 }; + LhSetExclusiveACL(ACLEntries, 1, &GETmessagea); + LhSetExclusiveACL(ACLEntries, 1, &GETmessagew); + LhSetExclusiveACL(ACLEntries, 1, &PEEKmessagea); + LhSetExclusiveACL(ACLEntries, 1, &PEEKmessagew); + } + if (TranslateXtoMKB::showcursorhook == 1) + { + ULONG ACLEntries[1] = { 0 }; + LhSetExclusiveACL(ACLEntries, 1, &g_HookShowCursorHandle); + } + hooksenabled = true; + } + void DisableHooks() + { + ULONG ACLEntries[1] = { 0 }; + LhSetGlobalExclusiveACL(ACLEntries, 0); + hooksenabled = false; + return; + } + + void SetupHook() + { + + // Log() << "Loading " << path; + HMODULE hUser32 = GetModuleHandleA("user32"); + if (!hUser32) { + MessageBoxA(NULL, "FATAL: Could not get a handle to user32.dll! Hooks will not be installed.", "error", MB_OK); + return; + } + NTSTATUS result; + + if (TranslateXtoMKB::getcursorposhook == 1 || TranslateXtoMKB::getcursorposhook == 2) { + result = LhInstallHook(GetProcAddress(hUser32, "GetCursorPos"), MyGetCursorPos, NULL, &GETcursorpos); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetCursorPos hook", "Error", MB_OK | MB_ICONERROR); + } + if (TranslateXtoMKB::setcursorposhook == 1) { + result = LhInstallHook(GetProcAddress(hUser32, "SetCursorPos"), MySetCursorPos, NULL, &SETcursorpos); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install SetCursorPos hook", "Error", MB_OK | MB_ICONERROR); + } + if (TranslateXtoMKB::getkeystatehook == 1) { + result = LhInstallHook(GetProcAddress(hUser32, "GetKeyState"), HookedGetKeyState, NULL, &GETkeystate); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetKeyState hook", "Error", MB_OK | MB_ICONERROR); + } + if (TranslateXtoMKB::getasynckeystatehook == 1) { + result = LhInstallHook(GetProcAddress(hUser32, "GetAsyncKeyState"), HookedGetAsyncKeyState, NULL, &GETasynckeystate); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetAsyncKeyState hook", "Error", MB_OK | MB_ICONERROR); + } + if (TranslateXtoMKB::clipcursorhook == 1) { + result = LhInstallHook(GetProcAddress(hUser32, "ClipCursor"), HookedClipCursor, NULL, &CLIPcursor); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install ClipCursor hook", "Error", MB_OK | MB_ICONERROR); + } + if (setrecthook == 1) { + result = LhInstallHook(GetProcAddress(hUser32, "SetRect"), HookedSetRect, NULL, &SETrect); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install SetRect hook", "Error", MB_OK | MB_ICONERROR); + result = LhInstallHook(GetProcAddress(hUser32, "AdjustWindowRect"), HookedAdjustWindowRect, NULL, &ADJUSTwindowrect); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install AdjustWindowRect hook", "Error", MB_OK | MB_ICONERROR); + } + if (TranslateXtoMKB::setcursorhook == 1) + { + result = LhInstallHook(GetProcAddress(hUser32, "SetCursor"), HookedSetCursor, NULL, &SETcursor); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install SetCursor hook", "Error", MB_OK | MB_ICONERROR); + } + if (TranslateXtoMKB::rawinputhook == 1 || TranslateXtoMKB::rawinputhook == 2) + { + result = LhInstallHook(GetProcAddress(hUser32, "GetRawInputData"), HookedGetRawInputData, NULL, &GETrawinputdata); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetRawInputData hook", "Error", MB_OK | MB_ICONERROR); + } + if (TranslateXtoMKB::GetKeyboardStateHook == 1) + { + result = LhInstallHook(GetProcAddress(hUser32, "GetKeyboardState"), HookedGetKeyboardState, NULL, &GETkeyboardstate); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetKeyboardState hook", "Error", MB_OK | MB_ICONERROR); + } + + // if (registerrawinputhook) + // { + // result = LhInstallHook(GetProcAddress(hUser32, "RegisterRawInputDevices"), HookedRegisterRawInputDevices, NULL, ®ISTERrawinputdevices); + // if (FAILED(result)) MessageBoxA(NULL, "Failed to install RegisterRawInputDevices hook", "Error", MB_OK | MB_ICONERROR); + // } + if (g_filterRawInput || g_filterMouseMove || g_filterMouseActivate || g_filterWindowActivate + || g_filterWindowActivateApp || g_filterMouseWheel || g_filterMouseButton || g_filterKeyboardButton) // If one of them is enabled + { + // result = LhInstallHook(GetProcAddress(hUser32, "GetMessageA"), ScreenshotInput::MessageFilterHook::Hook_GetMessageA, NULL, &GETmessagea); + // if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetMessageA hook", "Error", MB_OK | MB_ICONERROR); + // result = LhInstallHook(GetProcAddress(hUser32, "GetMessageW"), ScreenshotInput::MessageFilterHook::Hook_GetMessageW, NULL, &GETmessagew); + // if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetMessageW hook", "Error", MB_OK | MB_ICONERROR); + // result = LhInstallHook(GetProcAddress(hUser32, "PeekMessageA"), ScreenshotInput::MessageFilterHook::Hook_PeekMessageA, NULL, &PEEKmessagea); + // if (FAILED(result)) MessageBoxA(NULL, "Failed to install PeekMessageA hook", "Error", MB_OK | MB_ICONERROR); + // result = LhInstallHook(GetProcAddress(hUser32, "PeekMessageW"), ScreenshotInput::MessageFilterHook::Hook_PeekMessageW, NULL, &PEEKmessagew); + // if (FAILED(result)) MessageBoxA(NULL, "Failed to install PeekMessageW hook", "Error", MB_OK | MB_ICONERROR); + } + if (TranslateXtoMKB::showcursorhook == 1) + { + result = LhInstallHook(GetProcAddress(hUser32, "ShowCursor"), HookedShowCursor, NULL, &g_HookShowCursorHandle); + if (FAILED(result)) MessageBoxA(NULL, "Failed to install ShowCursor hook", "Error", MB_OK | MB_ICONERROR); + } + hooksinited = true; + + //MH_EnableHook(MH_ALL_HOOKS); + return; + } + + + void vibrateController(int controllerId, WORD strength) + { + XINPUT_VIBRATION vibration = {}; + vibration.wLeftMotorSpeed = strength; // range: 0 - 65535 + vibration.wRightMotorSpeed = strength; + + // Activate vibration + OpenXInputSetState(controllerId, &vibration); + + // Keep vibration on for 1 second + Sleep(50); // milliseconds + + // Stop vibration + vibration.wLeftMotorSpeed = 0; + vibration.wRightMotorSpeed = 0; + OpenXInputSetState(controllerId, &vibration); + } + + bool SendMouseClick(int x, int y, int z, int many) { + // Create a named mutex + + POINT heer; + + unsigned int sig = ScreenshotInput_MOUSE_SIGNATURE; + + heer.x = x; + heer.y = y; + if (TranslateXtoMKB::getcursorposhook == 2) + ClientToScreen(hwnd, &heer); + + LPARAM clickPos = MAKELPARAM(heer.x, heer.y); + if (z == 1) { + + unsigned int wParamDown = VK_LBUTTON | sig; // Add signature + unsigned int wParamUp = 0 | sig; // Add signature + + PostMessage(hwnd, WM_LBUTTONDOWN, wParamDown, clickPos); + PostMessage(hwnd, WM_LBUTTONUP, wParamUp, clickPos); + keystatesend = VK_LEFT; + } + if (z == 2) { + + unsigned int wParamDown = VK_RBUTTON | sig; + unsigned int wParamUp = 0 | sig; + + PostMessage(hwnd, WM_RBUTTONDOWN, wParamDown, clickPos); + PostMessage(hwnd, WM_RBUTTONUP, wParamUp, clickPos); + } + if (z == 3) { + unsigned int wParamDown = VK_LBUTTON | sig; + + unsigned int mouseMkFlags = VK_LBUTTON | sig; + PostMessage(hwnd, WM_LBUTTONDOWN, mouseMkFlags, clickPos); + keystatesend = VK_LEFT; + musLB = true; + } + if (z == 4) + { + unsigned int wParamUp = 0 | sig; + PostMessage(hwnd, WM_LBUTTONUP, wParamUp, clickPos); + musLB = false; + + } + if (z == 5) { + unsigned int wParamDown = VK_RBUTTON | sig; + + PostMessage(hwnd, WM_RBUTTONDOWN, wParamDown, clickPos); + keystatesend = VK_RIGHT; + musRB = true; + } + if (z == 6) + { + unsigned int wParamUp = 0 | sig; + PostMessage(hwnd, WM_RBUTTONUP, wParamUp, clickPos); + musRB = false; + + } + if (z == 20 || z == 21) //WM_mousewheel need desktop coordinates + { + + ClientToScreen(hwnd, &heer); + LPARAM clickPos = MAKELPARAM(heer.x, heer.y); + WPARAM wParam = 0; + if (z == 20) { + wParam = MAKEWPARAM(0, -120); + rawmouseWd = true; + } + if (z == 21) { + wParam = MAKEWPARAM(0, 120); + rawmouseWu = true; + } + wParam |= sig; // + PostMessage(hwnd, WM_MOUSEWHEEL, wParam, clickPos); + } + if (z == 30) //WM_LBUTTONDBLCLK + { + unsigned int wParam = 0 | sig; + PostMessage(hwnd, WM_LBUTTONDBLCLK, wParam, clickPos); + } + else if (z == 8 || z == 10 || z == 11) //only mousemove + { + unsigned int wParam = 0 | sig; + PostMessage(hwnd, WM_MOUSEMOVE, wParam, clickPos); + //PostMessage(hwnd, WM_SETCURSOR, (WPARAM)hwnd, MAKELPARAM(HTCLIENT, WM_MOUSEMOVE)); + + } + return true; + } + + std::string UGetExecutableFolder() { + char path[MAX_PATH]; + GetModuleFileNameA(NULL, path, MAX_PATH); + + std::string exePath(path); + + size_t lastSlash = exePath.find_last_of("\\/"); + return exePath.substr(0, lastSlash); + } + + + std::wstring WGetExecutableFolder() { + wchar_t path[MAX_PATH]; + GetModuleFileNameW(NULL, path, MAX_PATH); + std::wstring exePath(path); + size_t lastSlash = exePath.find_last_of(L"\\/"); + + if (lastSlash == std::wstring::npos) + return L""; + return exePath.substr(0, lastSlash); + } + + bool FindSubImage24( + const BYTE* largeData, int largeW, int largeH, int strideLarge, + const BYTE* smallData, int smallW, int smallH, int strideSmall, + POINT& foundAt, int Xstart, int Ystart + ) { + for (int y = Ystart; y <= largeH - smallH; ++y) { + for (int x = Xstart; x <= largeW - smallW; ++x) { + bool match = true; + for (int j = 0; j < smallH && match; ++j) { + const BYTE* pLarge = largeData + (y + j) * strideLarge + x * 3; + const BYTE* pSmall = smallData + j * strideSmall; + if (memcmp(pLarge, pSmall, smallW * 3) != 0) { + match = false; + } + } + if (match) { + foundAt.x = x; + foundAt.y = y; + return true; + } + } + } + return false; + } + + int CalculateStride(int width) { + return ((width * 3 + 3) & ~3); + } + + + bool Save24BitBMP(std::wstring filename, const BYTE* pixels, int width, int height) { //for testing purposes + int stride = ((width * 3 + 3) & ~3); + int imageSize = stride * height; + + BITMAPFILEHEADER bfh = {}; + bfh.bfType = 0x4D42; // "BM" + bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + bfh.bfSize = bfh.bfOffBits + imageSize; + + BITMAPINFOHEADER bih = {}; + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = width; + bih.biHeight = -height; // bottom-up BMP (positive height) + bih.biPlanes = 1; + bih.biBitCount = 24; + bih.biCompression = BI_RGB; + bih.biSizeImage = imageSize; + + HANDLE hFile = CreateFileW(filename.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) return false; + + DWORD written; + WriteFile(hFile, &bfh, sizeof(bfh), &written, NULL); + WriteFile(hFile, &bih, sizeof(bih), &written, NULL); + WriteFile(hFile, pixels, imageSize, &written, NULL); + CloseHandle(hFile); + + return true; + } + + bool IsTriggerPressed(BYTE triggerValue) { + BYTE threshold = 175; + return triggerValue > threshold; + } + bool LoadBMP24Bit(std::wstring filename, std::vector& pixels, int& width, int& height, int& stride) { + HBITMAP hbm = (HBITMAP)LoadImageW(NULL, filename.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION); + if (!hbm) return false; + + //BITMAP scaledbmp; + BITMAP bmp; + GetObject(hbm, sizeof(BITMAP), &bmp); + width = bmp.bmWidth - 1; + height = bmp.bmHeight - 1; + stride = CalculateStride(width); + + pixels.resize(stride * height); + + BITMAPINFO bmi = {}; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + + BYTE* pBits = nullptr; + HDC hdc = GetDC(NULL); + GetDIBits(hdc, hbm, 0, height, pixels.data(), &bmi, DIB_RGB_COLORS); + + if (hdc) DeleteDC(hdc); + if (hbm) DeleteObject(hbm); + return true; + } + + bool SaveWindow10x10BMP(HWND hwnd, std::wstring filename, int x, int y) { + HDC hdcWindow = GetDC(hwnd); + HDC hdcMem = CreateCompatibleDC(hdcWindow); + + // Size: 10x10 + int width = 10; + int height = 10; + int stride = ((width * 3 + 3) & ~3); + std::vector pixels(stride * height); + + // Create a 24bpp bitmap + BITMAPINFO bmi = {}; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; // top-down DIB + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + + + //stretchblt + + BYTE* pBits = nullptr; + + HBITMAP hbm24 = CreateDIBSection(hdcWindow, &bmi, DIB_RGB_COLORS, (void**)&pBits, 0, 0); + if (!hbm24) { + DeleteDC(hdcMem); + ReleaseDC(hwnd, hdcWindow); + return false; + } + + HGDIOBJ oldbmp = SelectObject(hdcMem, hbm24); + + BitBlt(hdcMem, 0, 0, width, height, hdcWindow, x, y, SRCCOPY); + + // Prepare to retrieve bits + BITMAPINFOHEADER bih = {}; + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = width; + bih.biHeight = -height; // top-down for easier use + bih.biPlanes = 1; + bih.biBitCount = 24; + bih.biCompression = BI_RGB; + + GetDIBits(hdcMem, hbm24, 0, height, pixels.data(), (BITMAPINFO*)&bih, DIB_RGB_COLORS); + + // Save + bool ok = Save24BitBMP(filename.c_str(), pixels.data(), width, height); + + // Cleanup + SelectObject(hdcMem, oldbmp); + if (hbm24) DeleteObject(hbm24); + if (hdcMem)DeleteDC(hdcMem); + if (hdcWindow) ReleaseDC(hwnd, hdcWindow); + + return ok; + } + HBRUSH transparencyBrush; + + void DrawRedX(HDC hdc, int x, int y) //blue + { + HPEN hPen = CreatePen(PS_SOLID, 3, RGB(0, 0, 255)); + HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); + + MoveToEx(hdc, x - 15, y - 15, NULL); + LineTo(hdc, x + 15, y + 15); + + MoveToEx(hdc, x + 15, y - 15, NULL); + LineTo(hdc, x - 15, y + 15); + + SelectObject(hdc, hOldPen); + DeleteObject(hPen); + return; + } + void DrawBlueCircle(HDC hdc, int x, int y) //red + { + // Create a NULL brush (hollow fill) + HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH); + HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); + + HPEN hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0)); + HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); + + Ellipse(hdc, x - 15, y - 15, x + 15, y + 15); + + SelectObject(hdc, hOldBrush); + SelectObject(hdc, hOldPen); + DeleteObject(hPen); + } + void DrawGreenTriangle(HDC hdc, int x, int y) + { + // Use a NULL brush for hollow + HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH); + HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); + + HPEN hPen = CreatePen(PS_SOLID, 3, RGB(0, 255, 0)); + HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); + + POINT pts[3]; + pts[0].x = x; pts[0].y = y - 10; // top center + pts[1].x = x - 10; pts[1].y = y + 10; // bottom left + pts[2].x = x + 10; pts[2].y = y + 10; // bottom right + + Polygon(hdc, pts, 3); + + SelectObject(hdc, hOldBrush); + SelectObject(hdc, hOldPen); + DeleteObject(hPen); + } + + void DrawPinkSquare(HDC hdc, int x, int y) + { + // Create a NULL brush (hollow fill) + HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH); + HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); + + HPEN hPen = CreatePen(PS_SOLID, 3, RGB(255, 192, 203)); + HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); + + // Draw hollow rectangle (square) 20x20 + Rectangle(hdc, x - 15, y - 15, x + 15, y + 15); + + SelectObject(hdc, hOldBrush); + SelectObject(hdc, hOldPen); + DeleteObject(hPen); + } + + int moveH = 0; + int moveV = 0; //intro mainly to visualize cursor window size + bool otherway = false; + void DrawToHDC(HDC hdcWindow, int X, int Y, int showmessage) + { + + + //RECT fill{ WoldX, WoldY, WoldX + cursorWidth, WoldY + cursorHeight }; + if (TranslateXtoMKB::drawfakecursor == 2 || TranslateXtoMKB::drawfakecursor == 3) { + if (scanoption || TranslateXtoMKB::drawfakecursor == 3) + { + //erase + RECT rect; + GetClientRect(TranslateXtoMKB::pointerWindows, &rect); // client coordinates + FillRect(hdcWindow, &rect, transparencyBrush); + + } + else { + RECT rect = { WoldX, WoldY, WoldX + 32, WoldY + 32 }; //need bmp width height + WoldX = X - Xoffset; + WoldY = Y - Yoffset; + FillRect(hdcWindow, &rect, transparencyBrush); + } + } + + + if (scanoption == 1) + { + EnterCriticalSection(&critical); + POINT pos = { fakecursorW.x, fakecursorW.y }; + POINT Apos = { PointA.x, PointA.y }; + POINT Bpos = { PointB.x, PointB.y }; + POINT Xpos = { PointX.x, PointX.y }; + POINT Ypos = { PointY.x, PointY.y }; + //hCursorW = hCursor; + LeaveCriticalSection(&critical); + + //draw spots + if (Apos.x != 0 && Apos.y != 0) + DrawRedX(hdcWindow, Apos.x, Apos.y); + + if (Bpos.x != 0 && Bpos.y != 0) + DrawBlueCircle(hdcWindow, Bpos.x, Bpos.y); + + if (Xpos.x != 0 && Xpos.y != 0) + DrawGreenTriangle(hdcWindow, Xpos.x, Xpos.y); + + if (Ypos.x != 0 && Ypos.y != 0) + DrawPinkSquare(hdcWindow, Ypos.x, Ypos.y); + + } + if (showmessage == 99) //intro + { + RECT rect; + GetClientRect(TranslateXtoMKB::pointerWindows, &rect); // client coordinates + FillRect(hdcWindow, &rect, transparencyBrush); + + TextOut(hdcWindow, rect.right / 2, rect.bottom / 2, TEXT("LOADING..."), 10); + + DrawPinkSquare(hdcWindow, 20 + moveV, 20 + moveV); + DrawGreenTriangle(hdcWindow, rect.right - moveV - 20, rect.bottom - moveV - 20); + DrawBlueCircle(hdcWindow, rect.right - moveV - 20, 20 + moveV); + DrawRedX(hdcWindow, 20 + moveV, rect.bottom - moveV - 20); + + HCURSOR cursor = LoadCursor(NULL, IDC_ARROW); + DrawIcon(hdcWindow, X - Xoffset, Y - Yoffset, cursor); + + if (moveV < rect.bottom - 20 && moveV < rect.right - 20 && moveV >= 0) + { + if (!otherway) + moveV += 10; + else moveV -= 10; + } + + else if (!otherway) + { + moveV -= 10; + otherway = true; + } + else if (otherway) + { + moveV += 10; + otherway = false; + } + //showmessage will auto expire and go to 0 in mainthread + } + if (showmessage == 1) + { + TextOut(hdcWindow, X, Y, TEXT("BMP MODE"), 8); + TextOut(hdcWindow, X, Y + 17, TEXT("only mapping searches"), 21); + } + else if (showmessage == 2) + { + TextOut(hdcWindow, X, Y, TEXT("CURSOR MODE"), 11); + TextOut(hdcWindow, X, Y + 17, TEXT("mapping searches + cursor"), 25); + } + else if (showmessage == 3) + { + TextOut(hdcWindow, X, Y, TEXT("EDIT MODE"), 9); + TextOut(hdcWindow, X, Y + 15, TEXT("tap a button to bind it to coordinate"), 37); + TextOut(hdcWindow, X, Y + 30, TEXT("A,B,X,Y,R2,R3,L2,L3 can be mapped"), 32); + } + else if (showmessage == 4) + { + TextOut(hdcWindow, 20, 5, TEXT("Z0 no scale, Z1 stretch, Z2 4:3 stretch, Z3 16:9"), 49); + + TCHAR buf[32]; + wsprintf(buf, TEXT("Z0: X: %d Y: %d"), X, Y); + TextOut(hdcWindow, 20, 20, buf, lstrlen(buf)); + + + POINT staticpoint = GetStaticFactor({ X, Y }, 1, true); + TextOut(hdcWindow, staticpoint.x, staticpoint.y, TEXT("1"), 1); + + staticpoint = GetStaticFactor({ X, Y }, 2, true); + TextOut(hdcWindow, staticpoint.x, staticpoint.y, TEXT("2"), 1); + + staticpoint = GetStaticFactor({ X, Y }, 3, true); + TextOut(hdcWindow, staticpoint.x, staticpoint.y, TEXT("3"), 1); + + HCURSOR cursor = LoadCursor(NULL, IDC_ARROW); + DrawIcon(hdcWindow, X - Xoffset, Y - Yoffset, cursor); + } + else if (showmessage == 10) + { + TextOut(hdcWindow, X, Y, TEXT("BUTTON MAPPED"), 13); + } + else if (showmessage == 11) + { + TextOut(hdcWindow, X, Y, TEXT("WAIT FOR MESSAGE EXPIRE!"), 24); + } + else if (showmessage == 12) + { + TextOut(hdcWindow, 20, 20, TEXT("DISCONNECTED!"), 14); //14 + } + else if (showmessage == 69) + { + TextOut(hdcWindow, X, Y, TEXT("SHUTTING DOWN"), 13); + } + else if (showmessage == 70) + { + TextOut(hdcWindow, X, Y, TEXT("STARTING!"), 10); + } + else if (showmessage == 71) + { + TextOut(hdcWindow, X, Y, TEXT("WINDOW?"), 7); + } + if (nodrawcursor == false && showcursorcounter == true) // is 1 + { + if (hCursor != 0 && onoroff == true) + { + gotcursoryet = true; + if (X - Xoffset < 0 || Y - Yoffset < 0) + DrawIconEx(hdcWindow, X, Y, hCursor, 32, 32, 0, NULL, DI_NORMAL);//need bmp width height + else + DrawIconEx(hdcWindow, X - Xoffset, Y - Yoffset, hCursor, 32, 32, 0, NULL, DI_NORMAL);//need bmp width height + + } + else if (onoroff == true && (alwaysdrawcursor == 1 || gotcursoryet == false)) + { + HCURSOR cursor = LoadCursor(NULL, IDC_ARROW); + DrawIcon(hdcWindow, X - Xoffset, Y - Yoffset, cursor); + } + } + return; + } + + + + + void DblBufferAndCallDraw(HDC cursorhdc, int X, int Y, int showmessage) { + + POINT res = windowpos(hwnd, ignorerect, false); + int width = res.x; + int height = res.y; + + HDC hdcMem = CreateCompatibleDC(cursorhdc); + HBITMAP hbmMem = CreateCompatibleBitmap(cursorhdc, width, height); + HGDIOBJ oldBmp = SelectObject(hdcMem, hbmMem); + + //BitBlt(hdcMem, 0, 0, width, height, cursorhdc, 0, 0, SRCCOPY); + // SetBkMode(hdcMem, TRANSPARENT); + + DrawToHDC(hdcMem, X, Y, showmessage); + + BitBlt(cursorhdc, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY); + + // cleanup + SelectObject(hdcMem, oldBmp); + DeleteObject(hbmMem); + DeleteDC(hdcMem); + } + void GetGameHDCAndCallDraw(HWND hwnd) { + if (scanoption) + EnterCriticalSection(&critical); + HDC hdc = GetDC(hwnd); + if (hdc) + { + DrawToHDC(hdc, Xf, Yf, showmessage); + ReleaseDC(hwnd, hdc); + } + + if (scanoption) + LeaveCriticalSection(&critical); + return; + } + + bool CaptureWindow24Bit(HWND hwnd, SIZE& capturedwindow, std::vector& pixels, int& strideOut, bool draw, bool stretchblt) + { + if (scanoption && TranslateXtoMKB::drawfakecursor == 1) + EnterCriticalSection(&critical); + HDC hdcWindow = GetDC(hwnd); + HDC hdcMem = CreateCompatibleDC(hdcWindow); + + + RECT rcClient; + GetClientRect(hwnd, &rcClient); + int width = rcClient.right - rcClient.left; + int height = rcClient.bottom - rcClient.top; + capturedwindow.cx = width; + capturedwindow.cy = height; + + int stride = ((width * 3 + 3) & ~3); + strideOut = stride; + pixels.resize(stride * height); + + BITMAPINFO bmi = {}; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; // top-down + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + + BYTE* pBits = nullptr; + HBITMAP hbm24 = CreateDIBSection(hdcWindow, &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0); + if (hbm24) + { + HGDIOBJ oldBmp = SelectObject(hdcMem, hbm24); + BitBlt(hdcMem, 0, 0, width, height, hdcWindow, 0, 0, SRCCOPY); + GetDIBits(hdcMem, hbm24, 0, height, pixels.data(), &bmi, DIB_RGB_COLORS); + SelectObject(hdcMem, oldBmp); + DeleteObject(hbm24); + // hbm24 = nullptr; + + } //hbm24 not null + + if (hdcMem) DeleteDC(hdcMem); + if (hdcWindow) ReleaseDC(hwnd, hdcWindow); + + if (scanoption && TranslateXtoMKB::drawfakecursor == 1) + LeaveCriticalSection(&critical); + return true; + } //function end + // Helper: Get stick magnitude + float GetStickMagnitude(SHORT x, SHORT y) { + return sqrtf(static_cast(x) * x + static_cast(y) * y); + } + + // Helper: Clamp value to range [-1, 1] + float Clamp(float v) { + if (v < -1.0f) return -1.0f; + if (v > 1.0f) return 1.0f; + return v; + } + // #define DEADZONE 8000 + // #define MAX_SPEED 30.0f // Maximum pixels per poll + // #define ACCELERATION 2.0f // Controls non-linear ramp (higher = more acceleration) + + + POINT CalculateUltimateCursorMove( + SHORT stickX, SHORT stickY, + float c_deadzone, + float s_deadzone, + float max_threshold, + float curve_slope, + float curve_exponent, + float sensitivity, + float accel_multiplier + ) { + static double mouseDeltaAccumulatorX = 0.0; + static double mouseDeltaAccumulatorY = 0.0; + + double normX = static_cast(stickX) / 32767.0; + double normY = static_cast(stickY) / 32767.0; + + double magnitude = std::sqrt(normX * normX + normY * normY); + if (magnitude < c_deadzone) { + return { 0, 0 }; // Inside circular deadzone + } + if (std::abs(normX) < s_deadzone) { + normX = 0.0; // Inside axial deadzone for X + } + if (std::abs(normY) < s_deadzone) { + normY = 0.0; // Inside axial deadzone for Y + } + magnitude = std::sqrt(normX * normX + normY * normY); + if (magnitude < 1e-6) { + return { 0, 0 }; + } + + double effectiveRange = 1.0 - max_threshold - c_deadzone; + if (effectiveRange < 1e-6) effectiveRange = 1.0; + + double remappedMagnitude = (magnitude - c_deadzone) / effectiveRange; + remappedMagnitude = (std::max)(0.0, (std::min)(1.0, remappedMagnitude)); + + double curvedMagnitude = curve_slope * remappedMagnitude + (1.0 - curve_slope) * std::pow(remappedMagnitude, curve_exponent); + + double finalSpeed = sensitivity * accel_multiplier; + + double dirX = normX / magnitude; + double dirY = normY / magnitude; + double finalMouseDeltaX = dirX * curvedMagnitude * finalSpeed; + double finalMouseDeltaY = dirY * curvedMagnitude * finalSpeed; + + mouseDeltaAccumulatorX += finalMouseDeltaX; + mouseDeltaAccumulatorY += finalMouseDeltaY; + LONG integerDeltaX = static_cast(mouseDeltaAccumulatorX); + LONG integerDeltaY = static_cast(mouseDeltaAccumulatorY); + + mouseDeltaAccumulatorX -= integerDeltaX; + mouseDeltaAccumulatorY -= integerDeltaY; + + return { integerDeltaX, -integerDeltaY }; + } + + void PostKeyFunction(HWND hwnd, int keytype, bool press) { + DWORD mykey = 0; + DWORD presskey = WM_KEYDOWN; + + + + if (!press) { + presskey = WM_KEYUP; // Key up event + } + + //standard keys for dpad + if (keytype == -1) + mykey = VK_UP; + if (keytype == -2) + mykey = VK_DOWN; + if (keytype == -3) + mykey = VK_LEFT; + if (keytype == -4) + mykey = VK_RIGHT; + + if (keytype == 3) + mykey = VK_ESCAPE; + if (keytype == 4) + mykey = VK_RETURN; + if (keytype == 5) + mykey = VK_TAB; + if (keytype == 6) + mykey = VK_SHIFT; + if (keytype == 7) + mykey = VK_CONTROL; + if (keytype == 8) + mykey = VK_SPACE; + + if (keytype == 9) + mykey = 0x4D; //M + + if (keytype == 10) + mykey = 0x57; //W + + if (keytype == 11) + mykey = 0x53; //S + + if (keytype == 12) + mykey = 0x41; //A + + if (keytype == 13) + mykey = 0x44; //D + + if (keytype == 14) + mykey = 0x45; //E + + if (keytype == 15) + mykey = 0x46; //F + + if (keytype == 16) + mykey = 0x47; //G + + if (keytype == 17) + mykey = 0x48; //H + + if (keytype == 18) + mykey = 0x49; //I + + if (keytype == 19) + mykey = 0x51; //Q + + if (keytype == 20) + mykey = VK_OEM_PERIOD; + + if (keytype == 21) + mykey = 0x52; //R + + if (keytype == 22) + mykey = 0x54; //T + + if (keytype == 23) + mykey = 0x42; //B + + if (keytype == 24) + mykey = 0x43; //C + + if (keytype == 25) + mykey = 0x4B; //K + + if (keytype == 26) + mykey = 0x55; //U + + if (keytype == 27) + mykey = 0x56; //V + + if (keytype == 28) + mykey = 0x57; //W + + if (keytype == 30) + mykey = 0x30; //0 + + if (keytype == 31) + mykey = 0x31; //1 + + if (keytype == 32) + mykey = 0x32; //2 + + if (keytype == 33) + mykey = 0x33; //3 + + if (keytype == 34) + mykey = 0x34; //4 + + if (keytype == 35) + mykey = 0x35; //5 + + if (keytype == 36) + mykey = 0x36; //6 + + if (keytype == 37) + mykey = 0x37; //7 + + if (keytype == 38) + mykey = 0x38; //8 + + if (keytype == 39) + mykey = 0x39; //9 + + if (keytype == 40) + mykey = VK_UP; + + if (keytype == 41) + mykey = VK_DOWN; + + if (keytype == 42) + mykey = VK_LEFT; + + if (keytype == 43) + mykey = VK_RIGHT; + + if (keytype == 44) + mykey = 0x58; //X + + if (keytype == 45) + mykey = 0x5A; //Z + + if (keytype == 46) + mykey = 0x4C; //L + + + + if (keytype == 51) + mykey = VK_F1; + + if (keytype == 52) + mykey = VK_F2; + + if (keytype == 53) + mykey = VK_F3; + + if (keytype == 54) + mykey = VK_F4; + + if (keytype == 55) + mykey = VK_F5; + + if (keytype == 56) + mykey = VK_F6; + + if (keytype == 57) + mykey = VK_F7; + + if (keytype == 58) + mykey = VK_F8; + if (keytype == 59) + mykey = VK_F9; + + if (keytype == 60) + mykey = VK_F10; + + if (keytype == 61) + mykey = VK_F11; + + if (keytype == 62) + mykey = VK_F12; + + if (keytype == 63) { //control+C + mykey = VK_CONTROL; + } + + + if (keytype == 70) + mykey = VK_NUMPAD0; + + if (keytype == 71) + mykey = VK_NUMPAD1; + + if (keytype == 72) + mykey = VK_NUMPAD2; + + if (keytype == 73) + mykey = VK_NUMPAD3; + + if (keytype == 74) + mykey = VK_NUMPAD4; + + if (keytype == 75) + mykey = VK_NUMPAD5; + + if (keytype == 76) + mykey = VK_NUMPAD6; + + if (keytype == 77) + mykey = VK_NUMPAD7; + + if (keytype == 78) + mykey = VK_NUMPAD8; + + if (keytype == 79) + mykey = VK_NUMPAD9; + + if (keytype == 80) + mykey = VK_SUBTRACT; + + if (keytype == 81) + mykey = VK_ADD; + + UINT scanCode = MapVirtualKey(mykey, MAPVK_VK_TO_VSC); + unsigned int lParam; + + BOOL isExtended = (mykey == VK_LEFT || mykey == VK_RIGHT || + mykey == VK_UP || mykey == VK_DOWN || + mykey == VK_INSERT || mykey == VK_DELETE || + mykey == VK_HOME || mykey == VK_END || + mykey == VK_PRIOR || mykey == VK_NEXT || + mykey == VK_RCONTROL || mykey == VK_RMENU); + if (isExtended) + lParam |= (1 << 24); + if (press) + { + + lParam = 1; // repeat count 1 or 0? + lParam |= (scanCode << 16); // scan code + lParam |= (0 << 30); // previous state + lParam |= (0 << 31); // transition state (0 = key down) + keys[mykey] = true; + } + else + { + + + unsigned int lparam = 0; + lparam |= 1; // Repeat count (always 1 for key up) + lParam |= (scanCode << 16); + lparam |= (1 << 30); // Previous key state (always 1 for key up) + lparam |= (1 << 31); // Transition state (always 1 for key up) + keys[mykey] = false; + keystatesend = 0; + } + + + if (g_filterKeyboardButton == 1) { + LPARAM ScreenshotInput_KEYBOARD_SIGNATUR = 0x10000000; + PostMessage(hwnd, presskey, ScreenshotInput_KEYBOARD_SIGNATUR |= mykey, lParam); + } + else PostMessage(hwnd, presskey, mykey, lParam); + + // for (HWND ahwnd : g_windows) + // { //multiwindow support + // if (IsWindow(ahwnd) && hwnd != hwnd) + // { + // PostMessage(ahwnd, presskey, mykey, lParam); + // } + // } + // PostMessage(hwnd, WM_INPUT, VK_RIGHT, lParam); + if (TranslateXtoMKB::rawinputhook == 1 || TranslateXtoMKB::rawinputhook == 2) + GenerateRawKey(mykey, press); + if (keytype == 63) { + // PostMessage(hwnd, presskey, ScreenshotInput_KEYBOARD_SIGNATUR |= 0x43, lParam); //game specific key combo. Warlords Battlecry 3 convert button + } + return; + + } + + void BmpInputAction(int X, int Y, int type) //moveclickorboth + { + + if (type == 0) //click and move + { + Xf = X; + Yf = Y; + SendMouseClick(X, Y, 8, 1); + Sleep(5); + SendMouseClick(X, Y, 3, 2); + Sleep(5); + SendMouseClick(X, Y, 4, 2); + movedmouse = true; + } + else if (type == 1) //only move + { + Xf = X; + Yf = Y; + + SendMouseClick(X, Y, 8, 1); + movedmouse = true; + } + else if (type == 2) //only click + { + SendMouseClick(X, Y, 8, 1); + Sleep(2); + SendMouseClick(X, Y, 3, 2); + Sleep(2); + SendMouseClick(X, Y, 4, 2); + Sleep(2); + SendMouseClick(Xf, Yf, 8, 1); + } + } + void Bmpfound(const char key[3], int X, int Y, int i, bool onlysearch, bool found, int store) + { + int input = 0; + if (strcmp(key, "\\A") == 0) + { + if (found) + { + // EnterCriticalSection(&critical); + + // LeaveCriticalSection(&critical); + if (onlysearch) + { + EnterCriticalSection(&critical); + startsearchA = i; + input = scanAtype; + staticPointA[i].x = X; + staticPointA[i].y = Y; + PointA.x = X; + PointA.y = Y; + LeaveCriticalSection(&critical); + } + else + { + input = scanAtype; + if (store) { + staticPointA[i].x = X; + staticPointA[i].y = Y; + + } + if (startsearchA < numphotoA - 1) + startsearchA = i + 1; + else startsearchA = 0; + } + } + else + { + if (onlysearch) + { + EnterCriticalSection(&critical); + startsearchA = 0; + PointA.x = 0; + PointA.y = 0; + LeaveCriticalSection(&critical); + } + } + } + if (strcmp(key, "\\B") == 0) + { + if (found) + { + //EnterCriticalSection(&critical); + + //LeaveCriticalSection(&critical); + if (onlysearch) + { + EnterCriticalSection(&critical); + startsearchB = i; + PointB.x = X; + staticPointB[i].x = X; + staticPointB[i].y = Y; + PointB.y = Y; + LeaveCriticalSection(&critical); + } + else + { + input = scanBtype; + if (store) { + staticPointB[i].x = X; + staticPointB[i].y = Y; + } + if (startsearchB < numphotoB - 1) + startsearchB = i + 1; + else startsearchB = 0; + } + } + else + { + if (onlysearch) + { + EnterCriticalSection(&critical); + startsearchB = 0; + PointB.x = 0; + PointB.y = 0; + LeaveCriticalSection(&critical); + } + } + } + if (strcmp(key, "\\X") == 0) + { + if (found) + { + // EnterCriticalSection(&critical); + + //LeaveCriticalSection(&critical); + if (onlysearch) + { + EnterCriticalSection(&critical); + startsearchX = i; + PointX.x = X; + PointX.y = Y; + staticPointX[i].x = X; + staticPointX[i].y = Y; + LeaveCriticalSection(&critical); + } + else + { + input = scanXtype; + startsearchX = i + 1; + if (store) { + staticPointX[i].x = X; + staticPointX[i].y = Y; + } + if (startsearchX < numphotoX - 1) + startsearchX = i + 1; + else startsearchX = 0; + } + } + else + { + if (onlysearch) + { + EnterCriticalSection(&critical); + startsearchX = 0; + PointX.x = 0; + PointX.y = 0; + LeaveCriticalSection(&critical); + } + } + } + if (strcmp(key, "\\Y") == 0) + { + //EnterCriticalSection(&critical); + + //LeaveCriticalSection(&critical); + if (found) + { + if (onlysearch) + { + EnterCriticalSection(&critical); + startsearchX = i; + staticPointY[i].x = X; + staticPointY[i].y = Y; + PointY.x = X; + PointY.y = Y; + LeaveCriticalSection(&critical); + } + else + { + input = scanYtype; + startsearchY = i + 1; + if (store) { + staticPointY[i].x = X; + staticPointY[i].y = Y; + } + if (startsearchY < numphotoY - 1) + startsearchY = i + 1; + else startsearchY = 0; + } + } + else + { + if (onlysearch) + { + EnterCriticalSection(&critical); + startsearchY = 0; + //input = scanYtype; + PointY.x = 0; + PointY.y = 0; + LeaveCriticalSection(&critical); + } + } + } + if (strcmp(key, "\\C") == 0) + { + if (found && !onlysearch) + { + startsearchC = i + 1; + input = Ctype; + } + } + if (strcmp(key, "\\D") == 0) + { + if (found && !onlysearch) + { + startsearchD = i + 1; + input = Dtype; + } + } + if (strcmp(key, "\\E") == 0) + { + if (found && !onlysearch) + { + startsearchE = i + 1; + input = Etype; + } + } + if (strcmp(key, "\\F") == 0) + { + if (found && !onlysearch) + { + startsearchF = i + 1; + input = Ftype; + } + } + if (!onlysearch) + { + if (found) + { //input sent in this function + BmpInputAction(X, Y, input); + } + } + return; + } + + POINT CheckStatics(const char abc[3], int numtocheck) + { + POINT newpoint{ 0,0 }; + if (strcmp(abc, "\\A") == 0) + { + if (staticPointA[numtocheck].x != 0) + { + // + newpoint.x = staticPointA[numtocheck].x; + newpoint.y = staticPointA[numtocheck].y; + } + } + if (strcmp(abc, "\\B") == 0) + { + if (staticPointB[numtocheck].x != 0) + { + newpoint.x = staticPointB[numtocheck].x; + newpoint.y = staticPointB[numtocheck].y; + } + } + if (strcmp(abc, "\\X") == 0) + { + if (staticPointX[numtocheck].x != 0) + { + newpoint.x = staticPointX[numtocheck].x; + newpoint.y = staticPointX[numtocheck].y; + } + } + if (strcmp(abc, "\\Y") == 0) + { + if (staticPointY[numtocheck].x != 0) + { + newpoint.x = staticPointY[numtocheck].x; + newpoint.y = staticPointY[numtocheck].y; + } + } + return newpoint; + } + bool ButtonScanAction(const char key[3], int mode, int serchnum, int startsearch, bool onlysearch, POINT currentpoint, int checkarray) + { + //HBITMAP hbbmdsktop; + //criticals + //EnterCriticalSection(&critical); + bool found = false; + //LeaveCriticalSection(&critical); + //mode // onlysearch + POINT pt = { 0,0 }; + POINT noeder = { 0,0 }; + //MessageBox(NULL, "some kind of error", "startsearch searchnum error", MB_OK | MB_ICONINFORMATION); + int numbmp = 0; + if (mode != 2) + { + int numphoto = 0; + //if (checkarray == 1) + //{ //always check static first? + noeder = CheckStatics(key, startsearch); + if (noeder.x != 0) + { + Bmpfound(key, noeder.x, noeder.y, startsearch, onlysearch, true, checkarray); //or not found + found = true; + return true; + } + //} + if (!found) + { + for (int i = startsearch; i < serchnum; i++) //memory problem here somewhere + { + if (checkarray == 1) + { + noeder = CheckStatics(key, i); + if (noeder.x != 0) + { + Bmpfound(key, noeder.x, noeder.y, i, onlysearch, true, checkarray); //or not found + found = true; + return true; + } + } + // if (checkarray) + + // MessageBox(NULL, "some kind of error", "startsearch searchnum error", MB_OK | MB_ICONINFORMATION); + std::string path = UGetExecutableFolder() + key + std::to_string(i) + ".bmp"; + std::wstring wpath(path.begin(), path.end()); + // HDC soke; + if (LoadBMP24Bit(wpath.c_str(), smallPixels, smallW, smallH, strideSmall) && !found) + { + // MessageBox(NULL, "some kind of error", "loaded bmp", MB_OK | MB_ICONINFORMATION); + // Capture screen + // HBITMAP hbbmdsktop; + if (CaptureWindow24Bit(hwnd, screenSize, largePixels, strideLarge, false, resize)) + { + if (onlysearch) + { + if (FindSubImage24(largePixels.data(), screenSize.cx, screenSize.cy, strideLarge, smallPixels.data(), smallW, smallH, strideSmall, pt, currentpoint.x, currentpoint.y)) + { + numphoto = i; + found = true; + break; + } + } + if (found == false) + { + if (FindSubImage24(largePixels.data(), screenSize.cx, screenSize.cy, strideLarge, smallPixels.data(), smallW, smallH, strideSmall, pt, 0, 0)) + { + // MessageBox(NULL, "some kind of error", "found spot", MB_OK | MB_ICONINFORMATION); + found = true; + numphoto = i; + break; + } + }//found + } //hbmdessktop + }//loadbmp + } + } + if (!found) + { + for (int i = 0; i < serchnum; i++) //memory problem here somewhere + { + if (checkarray == 1) + { + noeder = CheckStatics(key, i); + if (noeder.x != 0) + { + //MessageBox(NULL, "some kind of error", "startsearch searchnum error", MB_OK | MB_ICONINFORMATION); + Bmpfound(key, noeder.x, noeder.y, i, onlysearch, true, checkarray); //or not found + found = true; + return true; + } + } + + std::string path = UGetExecutableFolder() + key + std::to_string(i) + ".bmp"; + std::wstring wpath(path.begin(), path.end()); + if (LoadBMP24Bit(wpath.c_str(), smallPixels, smallW, smallH, strideSmall) && !found) + { + //ShowMemoryUsageMessageBox(); + if (CaptureWindow24Bit(hwnd, screenSize, largePixels, strideLarge, false, resize)) + + {// MessageBox(NULL, "some kind of error", "captured desktop", MB_OK | MB_ICONINFORMATION); + //ShowMemoryUsageMessageBox(); + if (FindSubImage24(largePixels.data(), screenSize.cx, screenSize.cy, strideLarge, smallPixels.data(), smallW, smallH, strideSmall, pt, 0, 0)) + { + // MessageBox(NULL, "some kind of error", "found spot", MB_OK | MB_ICONINFORMATION); + found = true; + numphoto = i; + break; + } + + } //hbmdessktop + }//loadbmp + } + + } + EnterCriticalSection(&critical); + bool foundit = found; + LeaveCriticalSection(&critical); + Bmpfound(key, pt.x, pt.y, numphoto, onlysearch, found, checkarray); //or not found + if (found == true) + return true; + else return false; + } + + if (mode == 2 && showmessage == 0 && onlysearch == false) //mode 2 button mapping //showmessage var to make sure no double map or map while message + { + //RepaintWindow(hwnd, NULL, FALSE); + Sleep(100); //to make sure red flicker expired + std::string path = UGetExecutableFolder() + key + std::to_string(serchnum) + ".bmp"; + std::wstring wpath(path.begin(), path.end()); + SaveWindow10x10BMP(hwnd, wpath.c_str(), Xf, Yf); + // MessageBox(NULL, "Mapped spot!", key, MB_OK | MB_ICONINFORMATION); + showmessage = 10; + return true; + } + else if (mode == 2 && onlysearch == false) + showmessage = 11;//wait for mesage expire + return true; + } + //int akkumulator = 0; + +#define WM_MOVE_pointerWindows (WM_APP + 2) + + void GetWindowDimensions(HWND pointerWindow) + { + HWND tHwnd = hwnd; + if (pointerWindow == tHwnd) + return; + + if (IsWindow(tHwnd)) + { + POINT pos = windowpos(hwnd, ignorerect, true); + POINT res = windowpos(hwnd, ignorerect, false); + + SetWindowPos(pointerWindow, HWND_TOPMOST, + pos.x, + pos.y, + res.x, + res.y, + SWP_NOACTIVATE); + ShowWindow(pointerWindow, SW_SHOW); + } + } + // Window procedure + bool neederase = false; + LRESULT CALLBACK FakeCursorWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch (msg) + { + case WM_MOVE_pointerWindows: + { + GetWindowDimensions(hWnd); + break; + } + case WM_PAINT: + { + return 1; + break; + } + case WM_ERASEBKGND: + { + return 1; + break; + } + case WM_DESTROY: + { + PostQuitMessage(0); + return 0; + } + default: + break; + } + + return DefWindowProc(hWnd, msg, wParam, lParam); + } + bool scanloop = false; + DWORD WINAPI ScanThread(LPVOID, int Aisstatic, int Bisstatic, int Xisstatic, int Yisstatic) + { + int scantick = 0; + Sleep(3000); + int Astatic = Aisstatic; + int Bstatic = Bisstatic; + int Xstatic = Xisstatic; + int Ystatic = Yisstatic; + //scanrunning = true; + scanloop = true; + while (scanloop) + { + EnterCriticalSection(&critical); + POINT Apos = { PointA.x, PointA.y }; + POINT Bpos = { PointB.x, PointB.y }; + POINT Xpos = { PointX.x, PointX.y }; + POINT Ypos = { PointY.x, PointY.y }; + int startsearchAW = startsearchA; + int startsearchBW = startsearchB; + int startsearchXW = startsearchX; + int startsearchYW = startsearchY; + POINT PointAW = PointA; + POINT PointBW = PointB; + POINT PointXW = PointX; + POINT PointYW = PointY; + LeaveCriticalSection(&critical); + + + + if (scantick < 3) + scantick++; + else scantick = 0; + if (scanoption == 1) + { + if (scantick == 0 && numphotoA > 0) + { + if (Astatic == 1) + { + if (staticPointA[startsearchAW].x == 0 && staticPointA[startsearchAW].y == 0) + ButtonScanAction("\\A", 1, numphotoA, startsearchAW, true, PointAW, Astatic); + else + Bmpfound("\\A", staticPointA[startsearchAW].x, staticPointA[startsearchAW].y, startsearchAW, true, true, Astatic); + } + else ButtonScanAction("\\A", 1, numphotoA, startsearchAW, true, PointAW, Astatic); + } + + if (scantick == 1 && numphotoB > 0) + { + if (Bstatic == 1) + { + if (staticPointB[startsearchBW].x == 0 && staticPointB[startsearchBW].y == 0) + //MessageBoxA(NULL, "heisann", "A", MB_OK); + ButtonScanAction("\\B", 1, numphotoB, startsearchBW, true, PointAW, Bstatic); + else + Bmpfound("\\B", staticPointB[startsearchBW].x, staticPointB[startsearchBW].y, startsearchBW, true, true, Bstatic); + } + else ButtonScanAction("\\B", 1, numphotoB, startsearchBW, true, PointBW, Bstatic); + + } + if (scantick == 2 && numphotoX > 0) + { + if (Xstatic == 1) + { + if (staticPointX[startsearchXW].x == 0 && staticPointX[startsearchXW].y == 0) + ButtonScanAction("\\X", 1, numphotoX, startsearchXW, true, PointXW, Xstatic); + else Bmpfound("\\X", staticPointX[startsearchXW].x, staticPointX[startsearchXW].y, startsearchXW, true, true, Xstatic); + } + else ButtonScanAction("\\X", 1, numphotoX, startsearchXW, true, PointXW, Xstatic); + + } + if (scantick == 3 && numphotoY > 0) + { + if (Ystatic == 1) + { + if (staticPointY[startsearchYW].x == 0 && staticPointY[startsearchYW].y == 0) + //MessageBoxA(NULL, "heisann", "A", MB_OK); + ButtonScanAction("\\Y", 1, numphotoY, startsearchYW, true, PointYW, Ystatic); + else + Bmpfound("\\Y", staticPointY[startsearchYW].x, staticPointY[startsearchYW].y, startsearchYW, true, true, Ystatic); + } + ButtonScanAction("\\Y", 1, numphotoY, startsearchYW, true, PointYW, Ystatic); + } + Sleep(10); + } + //else Sleep(1000); + } + return 0; + } + //TODO: width/height probably needs to change + + + // DrawFakeCursorFix. cursor offset scan and cursor size fix + + + // Thread to create and run the window + DWORD WINAPI WindowThreadProc(LPVOID) { + // Sleep(5000); + //EnterCriticalSection(&critical); + transparencyBrush = (HBRUSH)CreateSolidBrush(transparencyKey); + WNDCLASSW wc = { }; + wc.lpfnWndProc = FakeCursorWndProc; + wc.hInstance = GetModuleHandleW(0); + wc.hbrBackground = transparencyBrush; + + std::srand(static_cast(std::time(nullptr))); + const std::wstring classNameStr = std::wstring{ L"GtoMnK_Pointer_Window" } + std::to_wstring(std::rand()); + + wc.lpszClassName = classNameStr.c_str(); + wc.style = CS_OWNDC | CS_NOCLOSE; + + RegisterClassW(&wc); + + TranslateXtoMKB::pointerWindows = CreateWindowExW(WS_EX_NOACTIVATE | WS_EX_NOINHERITLAYOUT | WS_EX_NOPARENTNOTIFY | + WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW | WS_EX_LAYERED, + wc.lpszClassName, L"classNameStr.c_str()", + WS_POPUP | WS_VISIBLE, + 0, 0, 800, 600, + nullptr, nullptr, GetModuleHandle(NULL), nullptr); + + + + + if (!TranslateXtoMKB::pointerWindows) { + MessageBoxA(NULL, "Failed to create pointer window", "Error", MB_OK | MB_ICONERROR); + + } + SetLayeredWindowAttributes(TranslateXtoMKB::pointerWindows, transparencyKey, 0, LWA_COLORKEY); + + MSG msg; + ZeroMemory(&msg, sizeof(msg)); + //LeaveCriticalSection(&critical); + while (GetMessage(&msg, nullptr, 0, 0)) + { + if (msg.message != WM_QUIT) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + } + return 0; + } + + + + void pollbuttons(WORD buttons, RECT rect) + { + if (oldA == true) + { + if (buttons & XINPUT_GAMEPAD_A && onoroff == true) + { + // keep posting? + } + else { + oldA = false; + PostKeyFunction(hwnd, Atype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_A && onoroff == true) + { + oldA = true; + + if (!scanoption) { + startsearch = startsearchA; + ButtonScanAction("\\A", mode, numphotoA, startsearch, false, { 0,0 }, AuseStatic);//buttonacton will be occupied by scanthread + } + else + { + EnterCriticalSection(&critical); + POINT Cpoint; + Cpoint.x = PointA.x; + Cpoint.y = PointA.y; + + //LeaveCriticalSection(&critical); + if (Cpoint.x != 0 && Cpoint.y != 0) + { + if (ShoulderNextbmp == 0) + { + if (startsearchA < numphotoA - 1) + startsearchA++; //dont want it to update before input done + else startsearchA = 0; + PointA.x = 0; + PointA.y = 0; + } + BmpInputAction(Cpoint.x, Cpoint.y, scanAtype); + foundit = true; + + } + LeaveCriticalSection(&critical); + } + + EnterCriticalSection(&critical); + if (foundit == false && Atype != 0) + { + PostKeyFunction(hwnd, Atype, true); + } + LeaveCriticalSection(&critical); + if (mode == 2 && showmessage != 11) + { + numphotoA++; + Sleep(500); + } + } + + + + if (oldB == true) + { + if (buttons & XINPUT_GAMEPAD_B && onoroff == true) + { + // keep posting? + } + else { + oldB = false; + PostKeyFunction(hwnd, Btype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_B && onoroff == true) + { + + + oldB = true; + if (!scanoption) { + startsearch = startsearchB; + ButtonScanAction("\\B", mode, numphotoB, startsearch, false, { 0,0 }, BuseStatic); + } + else + { + EnterCriticalSection(&critical); + POINT Cpoint; + Cpoint.x = PointB.x; + Cpoint.y = PointB.y; + + if (Cpoint.x != 0 && Cpoint.y != 0) + { + if (ShoulderNextbmp == 0) + { + if (startsearchB < numphotoB - 1) + startsearchB++; //dont want it to update before input done + else startsearchB = 0; + PointB.x = 0; + PointB.y = 0; + } + BmpInputAction(Cpoint.x, Cpoint.y, scanBtype); + } + LeaveCriticalSection(&critical); + } + EnterCriticalSection(&critical); + if (foundit == false) + { + PostKeyFunction(hwnd, Btype, true); + } + LeaveCriticalSection(&critical); + if (mode == 2 && showmessage != 11) + { + numphotoB++; + Sleep(500); + } + + } + + + + if (oldX == true) + { + if (buttons & XINPUT_GAMEPAD_X && onoroff == true) + { + // keep posting? + } + else { + oldX = false; + PostKeyFunction(hwnd, Xtype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_X && onoroff == true) + { + oldX = true; + + + if (!scanoption) + { + startsearch = startsearchX; + ButtonScanAction("\\X", mode, numphotoX, startsearch, false, { 0,0 }, XuseStatic); + } + else + { + EnterCriticalSection(&critical); + POINT Cpoint; + Cpoint.x = PointX.x; + Cpoint.y = PointX.y; + + movedmouse = true; + if (Cpoint.x != 0 && Cpoint.y != 0) + { + if (ShoulderNextbmp == 0) + { + if (startsearchX < numphotoX - 1) + startsearchX++; //dont want it to update before input done + else startsearchX = 0; + PointX.x = 0; + PointX.y = 0; + } + BmpInputAction(Cpoint.x, Cpoint.y, scanXtype); + + } + LeaveCriticalSection(&critical); + } + EnterCriticalSection(&critical); + if (foundit == false) + { + PostKeyFunction(hwnd, Xtype, true); + } + LeaveCriticalSection(&critical); + if (mode == 2 && showmessage != 11) + { + numphotoX++; + Sleep(500); + } + } + + + + if (oldY == true) + { + if (buttons & XINPUT_GAMEPAD_Y && onoroff == true) + { + // keep posting? + } + else { + oldY = false; + PostKeyFunction(hwnd, Ytype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_Y && onoroff == true) + { + oldY = true; + + + if (!scanoption) { + startsearch = startsearchY; + ButtonScanAction("\\Y", mode, numphotoY, startsearch, false, { 0,0 }, false); + } + else + { + EnterCriticalSection(&critical); + POINT Cpoint; + Cpoint.x = PointY.x; + Cpoint.y = PointY.y; + + if (Cpoint.x != 0 && Cpoint.y != 0) + { + if (ShoulderNextbmp == 0) + { + if (startsearchY < numphotoY - 1) + startsearchY++; //dont want it to update before input done + else startsearchY = 0; + PointY.x = 0; + PointY.y = 0; + } + BmpInputAction(Cpoint.x, Cpoint.y, scanYtype); + + } + LeaveCriticalSection(&critical); + } + if (mode == 2 && showmessage != 11) + { //mapping mode + numphotoY++; + Sleep(500); + } + EnterCriticalSection(&critical); + if (foundit == false) + { + PostKeyFunction(hwnd, Ytype, true); + } + LeaveCriticalSection(&critical); + } + + + + if (oldC == true) + { + if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER && onoroff == true) + { + // keep posting? + } + else { + oldC = false; + PostKeyFunction(hwnd, Ctype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER && onoroff == true) + { + oldC = true; + + if (ShoulderNextbmp == 1) + { + EnterCriticalSection(&critical); + if (startsearchA < numphotoA - 1) + startsearchA++; //dont want it to update before input done + else startsearchA = 0; + if (startsearchB < numphotoB - 1) + startsearchB++; //dont want it to update before input done + else startsearchB = 0; + if (startsearchX < numphotoX - 1) + startsearchX++; //dont want it to update before input done + else startsearchX = 0; + LeaveCriticalSection(&critical); + } + startsearch = startsearchC; + if (!scanoption) + ButtonScanAction("\\C", mode, numphotoC, startsearch, false, { 0,0 }, false); + EnterCriticalSection(&critical); + if (foundit == false) + { + PostKeyFunction(hwnd, Ctype, true); + } + LeaveCriticalSection(&critical); + if (mode == 2 && showmessage == 0) + { + numphotoC++; + Sleep(500); + } + } + + + + if (oldD == true) + { + if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER && onoroff == true) + { + // keep posting? + } + else { + oldD = false; + PostKeyFunction(hwnd, Dtype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER && onoroff == true) + { + oldD = true; + + startsearch = startsearchD; + if (!scanoption) + ButtonScanAction("\\D", mode, numphotoD, startsearch, false, { 0,0 }, false); + EnterCriticalSection(&critical); + if (ShoulderNextbmp) + { + + if (startsearchA > 0) + startsearchA--; + else startsearchA = numphotoA - 1; + if (startsearchB > 0) + startsearchB--; + else startsearchB = numphotoB - 1; + if (startsearchX > 0) + startsearchX--; + else startsearchX = numphotoX - 1; + if (startsearchY > 0) + startsearchY--; + else startsearchY = numphotoY - 1; + + } + if (foundit == false) + { + PostKeyFunction(hwnd, Dtype, true); + } + LeaveCriticalSection(&critical); + if (mode == 2 && showmessage != 11) + { + numphotoD++; + Sleep(500); + } + } + + + + if (oldE == true) + { + if (buttons & XINPUT_GAMEPAD_RIGHT_THUMB && onoroff == true) + { + // keep posting? + } + else { + oldE = false; + PostKeyFunction(hwnd, Etype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_RIGHT_THUMB && onoroff == true) + { + oldE = true; + + startsearch = startsearchE; + if (!scanoption) + ButtonScanAction("\\E", mode, numphotoE, startsearch, false, { 0,0 }, false); + EnterCriticalSection(&critical); + if (foundit == false) + { + PostKeyFunction(hwnd, Etype, true); + } + LeaveCriticalSection(&critical); + if (mode == 2 && showmessage != 11) + { + numphotoE++; + Sleep(500); + } + } + + + + if (oldF == true) + { + if (buttons & XINPUT_GAMEPAD_LEFT_THUMB && onoroff == true) + { + // keep posting? + } + else { + oldF = false; + PostKeyFunction(hwnd, Ftype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_LEFT_THUMB && onoroff == true) + { + oldF = true; + + startsearch = startsearchF; + if (!scanoption) + ButtonScanAction("\\F", mode, numphotoF, startsearch, false, { 0,0 }, false); + EnterCriticalSection(&critical); + if (foundit == false) + { + PostKeyFunction(hwnd, Ftype, true); + } + LeaveCriticalSection(&critical); + if (mode == 2 && showmessage != 11) + { + numphotoF++; + Sleep(500); + } + } + + + + + if (oldup) + { + if (buttons & XINPUT_GAMEPAD_DPAD_UP && onoroff == true) + { + //post keep? + if (scrolloutsidewindow >= 3 && quickMW == 1) { + + SendMouseClick(Xf, Yf, 20, 1); + + } + } + else { + oldup = false; + PostKeyFunction(hwnd, uptype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_UP && onoroff == true) + { + + scroll.x = rect.left + (rect.right - rect.left) / 2; + if (scrolloutsidewindow == 0) + scroll.y = rect.top + 1; + if (scrolloutsidewindow == 1) + scroll.y = rect.top - 1; + scrollmap = true; + if (scrolloutsidewindow == 2) { + oldup = true; + PostKeyFunction(hwnd, uptype, true); + } + if (scrolloutsidewindow >= 3) { + oldup = true; + scrollmap = false; + + SendMouseClick(Xf, Yf, 20, 1); + + + } + } + + + + + else if (olddown) + { + if (buttons & XINPUT_GAMEPAD_DPAD_DOWN && onoroff == true) + { + //post keep? + if (scrolloutsidewindow >= 3 && quickMW == 1) { + + SendMouseClick(Xf, Yf, 21, 1); + + } + } + else { + olddown = false; + PostKeyFunction(hwnd, downtype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_DOWN && onoroff == true) + { + + scroll.x = rect.left + (rect.right - rect.left) / 2; + if (scrolloutsidewindow == 0) + scroll.y = rect.bottom - 1; + if (scrolloutsidewindow == 1) + scroll.y = rect.bottom + 1; + scrollmap = true; + if (scrolloutsidewindow == 2) { + olddown = true; + PostKeyFunction(hwnd, downtype, true); + } + if (scrolloutsidewindow >= 3) { + olddown = true; + scrollmap = false; + + SendMouseClick(Xf, Yf, 21, 1); + + + } + } + + + + + + else if (oldleft) + { + if (buttons & XINPUT_GAMEPAD_DPAD_LEFT && onoroff == true) + { + //post keep? + } + else { + oldleft = false; + PostKeyFunction(hwnd, lefttype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_LEFT && onoroff == true) + { + if (scrolloutsidewindow == 0) + scroll.x = rect.left + 1; + if (scrolloutsidewindow == 1) + scroll.x = rect.left - 1; + scroll.y = rect.top + (rect.bottom - rect.top) / 2; + + scrollmap = true; + if (scrolloutsidewindow == 2 || scrolloutsidewindow == 4) { + oldleft = true; + PostKeyFunction(hwnd, lefttype, true); + } + + } + + + + + + else if (oldright) + { + if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT && onoroff == true) + { + //post keep? + } + else { + oldright = false; + PostKeyFunction(hwnd, righttype, false); + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT && onoroff == true) + { + if (scrolloutsidewindow == 0) + scroll.x = rect.right - 1; + if (scrolloutsidewindow == 1) + scroll.x = rect.right + 1; + scroll.y = rect.top + (rect.bottom - rect.top) / 2; + scrollmap = true; + if (scrolloutsidewindow == 2 || scrolloutsidewindow == 4) { + oldright = true; + PostKeyFunction(hwnd, righttype, true); + } + } + else + { + scrollmap = false; + } + + + + + if (buttons & XINPUT_GAMEPAD_START && (showmessage == 0 || showmessage == 4)) + { + Sleep(100); + if (onoroff == true && buttons & XINPUT_GAMEPAD_LEFT_SHOULDER && buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) + { + //MessageBox(NULL, "Bmp mode", "shutdown", MB_OK | MB_ICONINFORMATION); + showmessage = 69; + } + else if (onoroff == false && buttons & XINPUT_GAMEPAD_LEFT_SHOULDER && buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) + { + //MessageBox(NULL, "Bmp mode", "starting", MB_OK | MB_ICONINFORMATION); + showmessage = 70; + } + else if (mode == 0 && Modechange == 1 && onoroff == true) + { + mode = 1; + + // MessageBox(NULL, "Bmp + Emulated cursor mode", "Move the flickering red dot and use right trigger for left click. left trigger for right click", MB_OK | MB_ICONINFORMATION); + showmessage = 2; + } + else if (mode == 1 && Modechange == 1 && onoroff == true) + { + mode = 2; + //MessageBox(NULL, "Edit Mode", "Button mapping. will map buttons you click with the flickering red dot as an input coordinate", MB_OK | MB_ICONINFORMATION); + showmessage = 3; + + + } + else if (mode == 2 && Modechange == 1 && onoroff == true) + { + mode = 3; + // MessageBox(NULL, "Bmp mode", "only send input on bmp match", MB_OK | MB_ICONINFORMATION); + showmessage = 4; + Sleep(1000); + } + else if (mode == 3 && Modechange == 1 && onoroff == true) + { + // mode = 0; + // MessageBox(NULL, "Bmp mode", "only send input on bmp match", MB_OK | MB_ICONINFORMATION); + showmessage = 1; + } + + else if (onoroff == true) { //assume modechange not allowed. send escape key instead + keystatesend = VK_ESCAPE; + } + // Sleep(1000); //have time to release button. this is no hurry anyway + + } + } + int HowManyBmps(std::wstring path, bool andstatics) + { + int start = -1; + + int x = 0; + std::wstring filename; + while (x < 50 && start == -1) + { + filename = path + std::to_wstring(x) + L".bmp"; + if (HBITMAP hbm = (HBITMAP)LoadImageW(NULL, filename.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION)) + { + x++; + DeleteObject(hbm); + + } + else { + start = x; + } + } + + //searching statics + x = 0; + int inistart = -1; + while (x < 50 && inistart == -1) + { + std::string iniPath = UGetExecutableFolder() + "\\Xinput.ini"; + std::string iniSettings = "Statics"; + + std::string name(path.end() - 1, path.end()); + std::string string = name.c_str() + std::to_string(x) + "X"; + + + int sjekkX = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); //simple test if settings read but write it wont work. + if (sjekkX != 0) + { + string = name.c_str() + std::to_string(x) + "X"; + x++; + } + else inistart = x; + } + if (!andstatics || inistart == 0) + return start; + else return start + inistart; + } + + + + bool initovector() + { + std::string iniPath = UGetExecutableFolder() + "\\Xinput.ini"; + std::string iniSettings = "Statics"; + std::string name = "A"; + int y = -1; + int sjekkx = 0; + bool test = false; + int x = -1; + int scalemethod = 0; + POINT inipoint; + while (x < 50 && y == -1) + { + x++; + std::string string = name + std::to_string(x) + "X"; + sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (sjekkx != 0) + { + test = true; + inipoint.x = sjekkx; + + string = name + std::to_string(x) + "Y"; + inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + + string = name + std::to_string(x) + "Z"; + scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (scalemethod != 0) + inipoint = GetStaticFactor(inipoint, scalemethod, true); + staticPointA[x + numphotoYbmps].y = inipoint.y; + staticPointA[x + numphotoYbmps].x = inipoint.x; + } + else y = 10; + } + y = -1; + name = "B"; + sjekkx = 0; + x = -1; + while (x < 50 && y == -1) + { + x++; + std::string string = name + std::to_string(x) + "X"; + sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (sjekkx != 0) + { + test = true; + inipoint.x = sjekkx; + + string = name + std::to_string(x) + "Y"; + inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + + string = name + std::to_string(x) + "Z"; + scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (scalemethod != 0) + inipoint = GetStaticFactor(inipoint, scalemethod, true); + staticPointB[x + numphotoYbmps].y = inipoint.y; + staticPointB[x + numphotoYbmps].x = inipoint.x; + } + + else y = 10; + } + y = -1; + name = "X"; + sjekkx = 0; + x = -1; + while (x < 50 && y == -1) + { + x++; + std::string string = name.c_str() + std::to_string(x) + "X"; + //MessageBoxA(NULL, "no bmps", "aaahaAAAHAA", MB_OK); + sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (sjekkx != 0) + { + test = true; + inipoint.x = sjekkx; + + string = name + std::to_string(x) + "Y"; + inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + + string = name + std::to_string(x) + "Z"; + scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (scalemethod != 0) + inipoint = GetStaticFactor(inipoint, scalemethod, true); + staticPointX[x + numphotoYbmps].y = inipoint.y; + staticPointX[x + numphotoYbmps].x = inipoint.x; + + } + + else y = 10; + } + y = -1; + name = "Y"; + sjekkx = 0; + x = -1; + while (x < 50 && y == -1) + { + x++; + std::string string = name.c_str() + std::to_string(x) + "X"; + sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (sjekkx != 0) + { + test = true; + inipoint.x = sjekkx; + + string = name + std::to_string(x) + "Y"; + inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + + string = name + std::to_string(x) + "Z"; + scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (scalemethod != 0) + inipoint = GetStaticFactor(inipoint, scalemethod, true); + staticPointY[x + numphotoYbmps].y = inipoint.y; + staticPointY[x + numphotoYbmps].x = inipoint.x; + } + else y = 10; + } + if (test == true) + return true; + else return false; //no points + } + + + bool enumeratebmps() + { + + + std::wstring path = WGetExecutableFolder() + L"\\A"; + numphotoA = HowManyBmps(path, true); + numphotoAbmps = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\B"; + numphotoB = HowManyBmps(path, true); + numphotoBbmps = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\X"; + numphotoX = HowManyBmps(path, true); + numphotoXbmps = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\Y"; + numphotoY = HowManyBmps(path, true); + numphotoYbmps = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\C"; + numphotoC = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\D"; + numphotoD = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\E"; + numphotoE = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\F"; + numphotoF = HowManyBmps(path, false); + + if (numphotoA < 0 && numphotoB < 0 && numphotoX < 0 && numphotoY < 00) + { + + return false; + } + + return true; + } + std::wstring ToWString(const std::string& s) + { + return std::wstring(s.begin(), s.end()); + } + bool readsettings() { + char buffer[16]; //or only 4 maybe + + // settings reporting + std::string iniPath = UGetExecutableFolder() + "\\Xinput.ini"; + std::string iniSettings = "Settings"; + + //controller settings + //controllerID = GetPrivateProfileIntA(iniSettings.c_str(), "Controllerid", -9000, iniPath.c_str()); //simple test if settings read + AxisLeftsens = GetPrivateProfileIntA(iniSettings.c_str(), "AxisLeftsens", -9000, iniPath.c_str()); + AxisRightsens = GetPrivateProfileIntA(iniSettings.c_str(), "AxisRightsens", 9000, iniPath.c_str()); + AxisUpsens = GetPrivateProfileIntA(iniSettings.c_str(), "AxisUpsens", 9000, iniPath.c_str()); + AxisDownsens = GetPrivateProfileIntA(iniSettings.c_str(), "AxisDownsens", -9000, iniPath.c_str()); + scrollspeed3 = GetPrivateProfileIntA(iniSettings.c_str(), "Scrollspeed", 150, iniPath.c_str()); + righthanded = GetPrivateProfileIntA(iniSettings.c_str(), "Righthanded", 1, iniPath.c_str()); + scanoption = GetPrivateProfileIntA(iniSettings.c_str(), "Scan", 0, iniPath.c_str()); + GetPrivateProfileStringA(iniSettings.c_str(), "Radial_Deadzone", "0.0", buffer, sizeof(buffer), iniPath.c_str()); + radial_deadzone = std::stof(buffer); //sensitivity + + //window set pos + posX = GetPrivateProfileIntA(iniSettings.c_str(), "posX", 0, iniPath.c_str()); + posY = GetPrivateProfileIntA(iniSettings.c_str(), "posY", 0, iniPath.c_str()); + resX = GetPrivateProfileIntA(iniSettings.c_str(), "resX", 0, iniPath.c_str()); + resY = GetPrivateProfileIntA(iniSettings.c_str(), "resY", 0, iniPath.c_str()); + + GetPrivateProfileStringA(iniSettings.c_str(), "Axial_Deadzone", "0.0", buffer, sizeof(buffer), iniPath.c_str()); + axial_deadzone = std::stof(buffer); //sensitivity + + GetPrivateProfileStringA(iniSettings.c_str(), "Sensitivity", "12.0", buffer, sizeof(buffer), iniPath.c_str()); + sensitivity = std::stof(buffer); //sensitivity //accel_multiplier + + GetPrivateProfileStringA(iniSettings.c_str(), "Accel_Multiplier", "2.0", buffer, sizeof(buffer), iniPath.c_str()); + accel_multiplier = std::stof(buffer); + + Xoffset = GetPrivateProfileIntA(iniSettings.c_str(), "Xoffset", 0, iniPath.c_str()); + Yoffset = GetPrivateProfileIntA(iniSettings.c_str(), "Yoffset", 0, iniPath.c_str()); + + //mode + InitialMode = GetPrivateProfileIntA(iniSettings.c_str(), "Initial Mode", 1, iniPath.c_str()); + Modechange = GetPrivateProfileIntA(iniSettings.c_str(), "Allow modechange", 0, iniPath.c_str()); + + sendfocus = GetPrivateProfileIntA(iniSettings.c_str(), "Sendfocus", 0, iniPath.c_str()); + responsetime = GetPrivateProfileIntA(iniSettings.c_str(), "Responsetime", 1, iniPath.c_str()); + doubleclicks = GetPrivateProfileIntA(iniSettings.c_str(), "Doubleclicks", 0, iniPath.c_str()); + scrollenddelay = GetPrivateProfileIntA(iniSettings.c_str(), "DelayEndScroll", 50, iniPath.c_str()); + quickMW = GetPrivateProfileIntA(iniSettings.c_str(), "MouseWheelContinous", 0, iniPath.c_str()); + + //clicknotmove 2000 + keyboard key code + //movenotclick 1000 + keyboard key code + Atype = GetPrivateProfileIntA(iniSettings.c_str(), "A", 0, iniPath.c_str()); + Btype = GetPrivateProfileIntA(iniSettings.c_str(), "B", 0, iniPath.c_str()); + Xtype = GetPrivateProfileIntA(iniSettings.c_str(), "X", 1, iniPath.c_str()); + Ytype = GetPrivateProfileIntA(iniSettings.c_str(), "Y", 0, iniPath.c_str()); + Ctype = GetPrivateProfileIntA(iniSettings.c_str(), "RightShoulder", 2, iniPath.c_str()); + Dtype = GetPrivateProfileIntA(iniSettings.c_str(), "LeftShoulder", 0, iniPath.c_str()); + Etype = GetPrivateProfileIntA(iniSettings.c_str(), "RightThumb", 0, iniPath.c_str()); + Ftype = GetPrivateProfileIntA(iniSettings.c_str(), "LeftThumb", 0, iniPath.c_str()); + AuseStatic = GetPrivateProfileIntA(iniSettings.c_str(), "ScanAstatic", 0, iniPath.c_str()); + BuseStatic = GetPrivateProfileIntA(iniSettings.c_str(), "ScanBstatic", 0, iniPath.c_str()); + XuseStatic = GetPrivateProfileIntA(iniSettings.c_str(), "ScanXstatic", 0, iniPath.c_str()); + YuseStatic = GetPrivateProfileIntA(iniSettings.c_str(), "ScanYstatic", 0, iniPath.c_str()); + skipintro = GetPrivateProfileIntA(iniSettings.c_str(), "SkipIntro", 0, iniPath.c_str()); + + wchar_t buffers[256] = { 0 }; + + //setting bmp search type like flag values + if (Atype > 1999) + { + bmpAtype = 2; + scanAtype = 2; + Atype = Atype - 2000; + + } + else if (Atype > 999) + { + bmpAtype = 1; + scanAtype = 1; + Atype = Atype - 1000; + } + else + { + bmpAtype = 0; + scanAtype = 0; + } + + if (Btype > 1999) + { + bmpBtype = 2; + scanBtype = 2; + Btype = Btype - 2000; + } + else if (Btype > 999) + { + bmpBtype = 1; + scanBtype = 1; + Btype = Btype - 1000; + } + else + { + bmpBtype = 0; + scanBtype = 0; + } + + if (Xtype > 1999) + { + scanXtype = 2; + bmpXtype = 2; + Xtype = Xtype - 2000; + } + else if (Xtype > 999) + { + bmpXtype = 1; + scanXtype = 1; + Xtype = Xtype - 1000; + } + else + { + bmpXtype = 0; + scanXtype = 0; + } + + if (Ytype > 1999) + { + bmpYtype = 2; + scanYtype = 2; + Ytype = Ytype - 2000; + } + else if (Ytype > 999) + { + bmpYtype = 1; + scanYtype = 1; + Ytype = Ytype - 1000; + } + else + { + bmpYtype = 0; + scanYtype = 0; + } + + if (Ctype > 1999) + { + bmpCtype = 2; + Ctype = Ctype - 2000; + } + else if (Ctype > 999) + { + bmpCtype = 1; + Ctype = Ctype - 1000; + } + else + { + bmpCtype = 0; + } + + if (Dtype > 1999) + { + bmpDtype = 2; + Dtype = Dtype - 2000; + } + else if (Dtype > 999) + { + bmpDtype = 1; + Dtype = Dtype - 1000; + } + else + { + bmpDtype = 0; + } + + if (Etype > 1999) + { + bmpEtype = 2; + Etype = Etype - 2000; + } + else if (Etype > 999) + { + bmpEtype = 1; + Etype = Etype - 1000; + } + else + { + bmpEtype = 0; + } + + if (Ftype > 1999) + { + Ftype = Ftype - 2000; + } + else if (Ftype > 999) + { + bmpFtype = 1; + Ftype = Ftype - 1000; + } + else + { + bmpFtype = 0; + } + + uptype = GetPrivateProfileIntA(iniSettings.c_str(), "Upkey", -1, iniPath.c_str()); + downtype = GetPrivateProfileIntA(iniSettings.c_str(), "Downkey", -2, iniPath.c_str()); + lefttype = GetPrivateProfileIntA(iniSettings.c_str(), "Leftkey", -3, iniPath.c_str()); + righttype = GetPrivateProfileIntA(iniSettings.c_str(), "Rightkey", -4, iniPath.c_str()); + ShoulderNextbmp = GetPrivateProfileIntA(iniSettings.c_str(), "ShouldersNextBMP", 0, iniPath.c_str()); + + //TranslateXtoMKB::drawfakecursor = GetPrivateProfileIntA(iniSettings.c_str(), "DrawFakeCursor", 3, iniPath.c_str()); + alwaysdrawcursor = GetPrivateProfileIntA(iniSettings.c_str(), "DrawFakeCursorAlways", 0, iniPath.c_str()); + ignorerect = GetPrivateProfileIntA(iniSettings.c_str(), "IgnoreRect", 0, iniPath.c_str()); + + scrolloutsidewindow = GetPrivateProfileIntA(iniSettings.c_str(), "Scrollmapfix", 1, iniPath.c_str()); //scrolloutsidewindow + mode = InitialMode; + + return true; + } + void ThreadFunction(HMODULE hModule) + { + Proto::AddThreadToACL(GetCurrentThreadId()); + + if (hooksoninit == 1) //if 2 then just after window found + { + SetupHook(); + EnableHooks(); + } + Sleep(2000); + if (readsettings() == false) + { + //messagebox? settings not read + } + if (findwindowdelay > 0) + Sleep(findwindowdelay * 1000); //delaying windowsearch + RECT rect; + bool Aprev = false; + if (scanoption == 1) + { //starting bmp conttinous scanner + std::thread tree(ScanThread, g_hModule, AuseStatic, BuseStatic, XuseStatic, YuseStatic); + tree.detach(); + } + if (TranslateXtoMKB::drawfakecursor == 0) + { + TranslateXtoMKB::drawfakecursor = 1; + nodrawcursor = true; + } + bool window = false; + bool gotwindow = false; + if (skipintro == 0) + showmessage = 99; + int retrynum = 0; + while (loop == true) + { + rawmouseWu = false; //reset + rawmouseWd = false; //reset + movedmouse = false; //reset + keystatesend = 0; //reset keystate + foundit = false; //reset foundit the bmp search found or not + if (!hwnd) + hwnd = (HWND)Proto::HwndSelector::GetSelectedHwnd(); + else + { + if (hooksoninit == 2 && hooksinited == false) + { + SetupHook(); + if (!hooksenabled) + EnableHooks(); + } + + if (!inithere) + { + if (!enumeratebmps()) //always this before initovector + { + if (scanoption) + { + MessageBoxA(NULL, "Error. scanoption without bmps", "No BMPS found", MB_OK); + scanloop = false; //force stop scan thread + scanoption = 0; + } + + } + + //resize window if set in ini + if (resX != 0) + { + SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE); + SetWindowPos(hwnd, NULL, posX, posY, resX, resY, SWP_NOZORDER | SWP_NOACTIVATE); + } + + staticPointA.assign(numphotoA + 1, POINT{ 0, 0 }); + staticPointB.assign(numphotoB + 1, POINT{ 0, 0 }); + staticPointX.assign(numphotoX + 1, POINT{ 0, 0 }); + staticPointY.assign(numphotoY + 1, POINT{ 0, 0 }); + initovector(); + inithere = true; + } + // + POINT poscheck = windowpos(hwnd, ignorerect, true); + POINT rescheck = windowpos(hwnd, ignorerect, false); + if (TranslateXtoMKB::drawfakecursor == 2 || TranslateXtoMKB::drawfakecursor == 3) + {//fake cursor window creation + + if (!window) + { + std::thread two(WindowThreadProc, g_hModule); + two.detach(); + Sleep(100); //give time to create window + EnterCriticalSection(&critical); + while (!TranslateXtoMKB::pointerWindows) { + MessageBoxA(NULL, "No pointerwindow", "ohno,try drawfakecursor 1 instead", MB_OK); + Sleep(1000); + } + if (TranslateXtoMKB::pointerWindows) { + //Sleep(500); + PointerWnd = GetDC(TranslateXtoMKB::pointerWindows); + SendMessage(TranslateXtoMKB::pointerWindows, WM_MOVE_pointerWindows, 0, 0); //focus to avoid alt tab issues + LeaveCriticalSection(&critical); + } + window = true; + } + else if (poscheck.x != oldposcheck.x || oldposcheck.y != oldposcheck.y || oldrescheck.y != oldrescheck.y || oldrescheck.x != oldrescheck.x) + { + EnterCriticalSection(&critical); + if (TranslateXtoMKB::pointerWindows) + SendMessage(TranslateXtoMKB::pointerWindows, WM_MOVE_pointerWindows, 0, 0); + //clearing points and reinit on window move or resize + staticPointA.clear(); + staticPointB.clear(); + staticPointX.clear(); + staticPointY.clear(); + initovector(); //this also call for scaling if needed + LeaveCriticalSection(&critical); + Sleep(1000); //pause renderiing + } + + oldposcheck.x = poscheck.x; + oldposcheck.y = poscheck.y; + + oldrescheck.x = rescheck.x; + oldrescheck.y = rescheck.y; + + } + + if (ignorerect == 1) + { + // These are the actual visible edges of the window in client coordinates + POINT upper = windowpos(hwnd, ignorerect, true); + POINT lower = windowpos(hwnd, ignorerect, false); + + //used in getcursrorpos + rectignore.x = upper.x; + rectignore.y = upper.y; //+titlebar if any? + + rect.right = lower.x + upper.x; //+ upper? + rect.bottom = lower.y + upper.y;//+ upper? + rect.left = 0; //upper? + rect.top = 0; + + } + else + { + GetClientRect(hwnd, &rect); + } + XINPUT_STATE state; + ZeroMemory(&state, sizeof(XINPUT_STATE)); + // Check controller 0 + DWORD dwResult = OpenXInputGetState(TranslateXtoMKB::controllerID, &state); + bool leftPressed = IsTriggerPressed(state.Gamepad.bLeftTrigger); + bool rightPressed = IsTriggerPressed(state.Gamepad.bRightTrigger); + + + if (dwResult == ERROR_SUCCESS) + { + + //criticals for windowthread // now only scanthread. + // //window rendering handled by current thread + EnterCriticalSection(&critical); + fakecursorW.x = Xf; + fakecursorW.y = Yf; + showmessageW = showmessage; + LeaveCriticalSection(&critical); + + // Controller is connected + WORD buttons = state.Gamepad.wButtons; + pollbuttons(buttons, rect); //all buttons exept triggers and axises + if (showmessage == 12) //was disconnected last scan? + { + showmessage = 0; + } + + if (mode > 0 && onoroff == true) + { + //fake cursor poll + int Xaxis = 0; + int Yaxis = 0; + int scrollXaxis = 0; + int scrollYaxis = 0; + POINT resw = windowpos(hwnd, ignorerect, false); + int width = resw.x; + int height = resw.y; + int Yscroll = 0; + int Xscroll = 0; + bool didscroll = false; + + + if (righthanded == 1) { + Xaxis = state.Gamepad.sThumbRX; + Yaxis = state.Gamepad.sThumbRY; + scrollXaxis = state.Gamepad.sThumbLX; + scrollYaxis = state.Gamepad.sThumbLY; + } + else + { + Xaxis = state.Gamepad.sThumbLX; + Yaxis = state.Gamepad.sThumbLY; + scrollXaxis = state.Gamepad.sThumbRX; + scrollYaxis = state.Gamepad.sThumbRY; + } + + if (scrolloutsidewindow == 2 || scrolloutsidewindow == 3 || scrolloutsidewindow == 4) + { + + if (oldscrollleftaxis) + { + if (scrollXaxis < AxisLeftsens) //left + { + if (scrolloutsidewindow == 3) + { //keep + scrollXaxis = scrollXaxis - AxisLeftsens; //zero input + doscrollyes = true; + Xscroll = +scrollXaxis / scrollspeed3; + didscroll = true; + } + // PostKeyFunction(hwnd, 42, true); + } + else + { //stop + oldscrollleftaxis = false; + if (scrolloutsidewindow == 2) + PostKeyFunction(hwnd, 42, false); + if (scrolloutsidewindow == 4) + PostKeyFunction(hwnd, 12, false); + } + } + else if (scrollXaxis < AxisLeftsens) //left + { + if (scrolloutsidewindow == 2) + PostKeyFunction(hwnd, 42, true); + if (scrolloutsidewindow == 4) + PostKeyFunction(hwnd, 12, true); + if (scrolloutsidewindow == 3 && doscrollyes == false) + {//start + tick = 0; + SendMouseClick(Xf, Yf, 8, 1); + SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 + } + oldscrollleftaxis = true; + //keystatesend = VK_LEFT; + } + + + if (oldscrollrightaxis) + { + if (scrollXaxis > AxisRightsens) //right + { + if (scrolloutsidewindow == 3) + { //keep + doscrollyes = true; + scrollXaxis = scrollXaxis - AxisRightsens; //zero input + Xscroll = scrollXaxis / scrollspeed3; + didscroll = true; + } + } + else { + oldscrollrightaxis = false; + if (scrolloutsidewindow == 2) + PostKeyFunction(hwnd, 43, false); + if (scrolloutsidewindow == 4) + PostKeyFunction(hwnd, 13, false); + } + } + else if (scrollXaxis > AxisRightsens) //right + { + if (scrolloutsidewindow == 2) + PostKeyFunction(hwnd, 43, true); + if (scrolloutsidewindow == 4) + PostKeyFunction(hwnd, 13, true); + if (scrolloutsidewindow == 3 && doscrollyes == false) + {//start + tick = 0; + SendMouseClick(Xf, Yf, 8, 1); + SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 + } + oldscrollrightaxis = true; + //keystatesend = VK_RIGHT; + + } + + + + if (oldscrolldownaxis) + { + if (scrollYaxis < AxisDownsens) + { + // PostKeyFunction(hwnd, 41, true); + if (scrolloutsidewindow == 3) + { //keep + scrollYaxis = scrollYaxis - AxisDownsens; //zero input + doscrollyes = true; + Yscroll = scrollYaxis / scrollspeed3; + didscroll = true; + } + } + else { + oldscrolldownaxis = false; + if (scrolloutsidewindow == 2) + PostKeyFunction(hwnd, 41, false); + if (scrolloutsidewindow == 4) + PostKeyFunction(hwnd, 11, false); + } + } + else if (scrollYaxis < AxisDownsens) //down + { //start + if (scrolloutsidewindow == 2) + PostKeyFunction(hwnd, 41, true); + if (scrolloutsidewindow == 4) + PostKeyFunction(hwnd, 11, true); + if (scrolloutsidewindow == 3 && doscrollyes == false) + {//start + tick = 0; + SendMouseClick(Xf, Yf, 8, 1); + SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 + } + oldscrolldownaxis = true; + } + + + + + + if (oldscrollupaxis) + { + if (scrollYaxis > AxisUpsens) + { + // PostKeyFunction(hwnd, 40, true); + if (scrolloutsidewindow == 3) + { //keep + scrollYaxis = scrollYaxis - AxisUpsens; //zero input + doscrollyes = true; + + Yscroll = scrollYaxis / scrollspeed3; //150 + didscroll = true; + } + } + else { + oldscrollupaxis = false; + if (scrolloutsidewindow == 2) + PostKeyFunction(hwnd, 40, false); + if (scrolloutsidewindow == 4) + PostKeyFunction(hwnd, 10, false); + } + } + else if (scrollYaxis > AxisUpsens) //up + { + if (scrolloutsidewindow == 2) + PostKeyFunction(hwnd, 40, true); + if (scrolloutsidewindow == 4) + PostKeyFunction(hwnd, 10, true); + if (scrolloutsidewindow == 3 && doscrollyes == false) + {//start + tick = 0; + SendMouseClick(Xf, Yf, 8, 1); + SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 + } + oldscrollupaxis = true; + } + } + + + //mouse left click and drag scrollfunction //scrolltype 3 + + if (doscrollyes) { + SendMouseClick(Xf + Xscroll, Yf - Yscroll, 8, 1); //4 skal vere 3 + if (!didscroll && tick == scrollenddelay) + { + //MessageBox(NULL, "Scroll stopped", "Info", MB_OK | MB_ICONINFORMATION); + doscrollyes = false; + SendMouseClick(Xf, Yf, 6, 2); //4 skal vere 3 + } + } + + + + if (scrolloutsidewindow < 2 && scrollmap == false) //was 2 + { + if (scrollXaxis < AxisLeftsens - 10000) //left + { + if (scrolloutsidewindow == 0) + scroll.x = rect.left + 1; + if (scrolloutsidewindow == 1) + scroll.x = rect.left - 1; + if (scrolloutsidewindow == 3) + scroll.x = (rect.left + (rect.right - rect.left) / 2) - 100; + scroll.y = rect.top + (rect.bottom - rect.top) / 2; + + scrollmap = true; + + } + else if (scrollXaxis > AxisRightsens + 10000) //right + { + if (scrolloutsidewindow == 0) + scroll.x = rect.right - 1; + if (scrolloutsidewindow == 1) + scroll.x = rect.right + 1; + if (scrolloutsidewindow == 3) + scroll.x = (rect.left + (rect.right - rect.left) / 2) + 100; + scroll.y = rect.top + (rect.bottom - rect.top) / 2; + + scrollmap = true; + + } + else if (scrollYaxis < AxisDownsens - 10000) //down + { + scroll.x = rect.left + (rect.right - rect.left) / 2; + if (scrolloutsidewindow == 0) + scroll.y = rect.bottom - 1; + if (scrolloutsidewindow == 1) + scroll.y = rect.bottom + 1; + if (scrolloutsidewindow == 3) + scroll.y = (rect.top + (rect.bottom - rect.top) / 2) + 100; + scrollmap = true; + + + } + + else if (scrollYaxis > AxisUpsens + 10000) //up + { + scroll.x = rect.left + (rect.right - rect.left) / 2; + if (scrolloutsidewindow == 0) + scroll.y = rect.top + 1; + if (scrolloutsidewindow == 1) + scroll.y = rect.top - 1; + if (scrolloutsidewindow == 3) + scroll.y = (rect.top + (rect.bottom - rect.top) / 2) - 100; + scrollmap = true; + } + + else { + scrollmap = false; + } + } + + delta = CalculateUltimateCursorMove( + Xaxis, Yaxis, + radial_deadzone, axial_deadzone, max_threshold, + curve_slope, curve_exponent, + sensitivity, accel_multiplier + ); + if (delta.x != 0 || delta.y != 0) { + Xf += delta.x; + Yf += delta.y; + movedmouse = true; + } + + //may freeze cursor here. dont know why yet + if (Xf > width - 1) Xf = width - 1; + if (Yf > height - 1) Yf = height - 1; + if (Yf < 1) Yf = 1; + if (Xf < 1) Xf = 1; + + if (movedmouse == true) //fake cursor move message + { + SendMouseClick(Xf, Yf, 8, 1); + } + + if (leftPressed) + { + + if (leftPressedold == false) + { + //save coordinates + startdrag.x = Xf; + startdrag.y = Yf; + leftPressedold = true; + rawmouseR = true; + if (scrolloutsidewindow == 3) + { + SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 + SendMouseClick(Xf, Yf, 6, 2); //double click + } + else + SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 + } + + } + else if (leftPressedold) + { + if (!leftPressed) + { + + SendMouseClick(Xf, Yf, 6, 2); //double click + + leftPressedold = false; + rawmouseR = false; + } + } + if (rightPressed) + { + if (rightPressedold == false) + { + //save coordinates + //start + if (hooksinited == false) + { + SetupHook(); + if (!hooksenabled) + EnableHooks(); + } + startdrag.x = Xf; + startdrag.y = Yf; + rightPressedold = true; + rawmouseL = true; + + DWORD currentTime = GetTickCount64(); + if (currentTime - lastClickTime < GetDoubleClickTime() && doubleclicks == 1) //movedmouse? + { + SendMouseClick(Xf, Yf, 30, 2); //4 skal vere 3 + } + else + { + SendMouseClick(Xf, Yf, 3, 2); //4 skal vere 3 + } + lastClickTime = currentTime; + + + } + } + else if (rightPressedold) + { + if (!rightPressed) + { + SendMouseClick(Xf, Yf, 4, 2); + rightPressedold = false; + rawmouseL = false; + } + } //if rightpress + + } //if mode above 0 + } //if controller + else { + showmessage = 12; + //MessageBoxA(NULL, "Controller not connected", "Error", MB_OK | MB_ICONERROR); + } + + + //rendering. 3 methods. 1 direct draw. 2 partial on own window. 3 full redraw double buffer on own window + if (TranslateXtoMKB::drawfakecursor == 1) + GetGameHDCAndCallDraw(hwnd); //calls DrawToHdc in here + else if (TranslateXtoMKB::drawfakecursor == 2) + { + if (scanoption) + DblBufferAndCallDraw(PointerWnd, Xf, Yf, showmessage); //full redraw + else if (movedmouse) DrawToHDC(PointerWnd, Xf, Yf, showmessage); //partial, much faster. may not erase correctly on staticpoints and messages yet + } + else if (TranslateXtoMKB::drawfakecursor == 3) + DblBufferAndCallDraw(PointerWnd, Xf, Yf, showmessage); //full redraw + + + } // if hwnd + if (showmessage != 0 && showmessage != 12) + { + counter++; + if (counter > 400) + { + if (showmessage == 1) { + mode = 0; + showmessage = 0; + } + if (showmessage == 69) { //disabling dll + onoroff = false; + if (hooksenabled) + DisableHooks(); + } + if (showmessage == 70) { //enabling dll + onoroff = true; + if (!hooksenabled) + EnableHooks(); + } + if (mode != 3) + showmessage = 0; + counter = 0; + } + } + // if (pointerWindow) { + // ReleaseDC(pointerWindow, PointerWnd); + // } + if (TranslateXtoMKB::rawinputhook == 1) //to make game poll rawinput + { + //need only 1 + ForceRawInputPoll(); //global all processes + } + // showcursorcounter = IsCursorVisible(); + if (tick < scrollenddelay) + tick++; + + if (mode == 0) + Sleep(10); + if (mode > 0) { + Sleep(1 + responsetime); + } + if (showmessage == 99) + Sleep(15); + } //loop end but endless + return; + } + + void TranslateXtoMKB::Initialize(HMODULE hModule) + { + + g_hModule = hModule; + + std::string iniPath = UGetExecutableFolder() + "\\Xinput.ini"; + std::string iniSettings = "Hooks"; + // controllerID = + //hook settings + //TranslateXtoMKB::clipcursorhook = GetPrivateProfileIntA(iniSettings.c_str(), "ClipCursorHook", 1, iniPath.c_str()); + /// TranslateXtoMKB::getkeystatehook = GetPrivateProfileIntA(iniSettings.c_str(), "GetKeystateHook", 1, iniPath.c_str()); + // TranslateXtoMKB::getasynckeystatehook = GetPrivateProfileIntA(iniSettings.c_str(), "GetAsynckeystateHook", 1, iniPath.c_str()); + // TranslateXtoMKB::getcursorposhook = GetPrivateProfileIntA(iniSettings.c_str(), "GetCursorposHook", 1, iniPath.c_str()); + // TranslateXtoMKB::setcursorposhook = GetPrivateProfileIntA(iniSettings.c_str(), "SetCursorposHook", 1, iniPath.c_str()); + // TranslateXtoMKB::setcursorhook = GetPrivateProfileIntA(iniSettings.c_str(), "SetCursorHook", 1, iniPath.c_str()); + // TranslateXtoMKB::rawinputhook = GetPrivateProfileIntA(iniSettings.c_str(), "RawInputHook", 1, iniPath.c_str()); + // TranslateXtoMKB::GetKeyboardStateHook = GetPrivateProfileIntA(iniSettings.c_str(), "GetKeyboardStateHook", 1, iniPath.c_str()); + setrecthook = GetPrivateProfileIntA(iniSettings.c_str(), "SetRectHook", 0, iniPath.c_str()); + leftrect = GetPrivateProfileIntA(iniSettings.c_str(), "SetRectLeft", 0, iniPath.c_str()); + toprect = GetPrivateProfileIntA(iniSettings.c_str(), "SetRectTop", 0, iniPath.c_str()); + rightrect = GetPrivateProfileIntA(iniSettings.c_str(), "SetRectRight", 800, iniPath.c_str()); + bottomrect = GetPrivateProfileIntA(iniSettings.c_str(), "SetRectBottom", 600, iniPath.c_str()); + // TranslateXtoMKB::registerrawinputhook = GetPrivateProfileIntA(iniSettings.c_str(), "RegisterRawInputHook", 1, iniPath.c_str()); + TranslateXtoMKB::showcursorhook = GetPrivateProfileIntA(iniSettings.c_str(), "ShowCursorHook", 1, iniPath.c_str()); + + // [MessageFilter] + g_filterRawInput = GetPrivateProfileIntA(iniSettings.c_str(), "RawInputFilter", 0, iniPath.c_str()); + g_filterMouseMove = GetPrivateProfileIntA(iniSettings.c_str(), "MouseMoveFilter", 0, iniPath.c_str()); + g_filterMouseActivate = GetPrivateProfileIntA(iniSettings.c_str(), "MouseActivateFilter", 0, iniPath.c_str()); + g_filterWindowActivate = GetPrivateProfileIntA(iniSettings.c_str(), "WindowActivateFilter", 0, iniPath.c_str()); + g_filterWindowActivateApp = GetPrivateProfileIntA(iniSettings.c_str(), "WindowActivateAppFilter", 0, iniPath.c_str()); + g_filterMouseWheel = GetPrivateProfileIntA(iniSettings.c_str(), "MouseWheelFilter", 0, iniPath.c_str()); + g_filterMouseButton = GetPrivateProfileIntA(iniSettings.c_str(), "MouseButtonFilter", 0, iniPath.c_str()); + g_filterKeyboardButton = GetPrivateProfileIntA(iniSettings.c_str(), "KeyboardButtonFilter", 0, iniPath.c_str()); + hwnd = (HWND)Proto::HwndSelector::GetSelectedHwnd(); + + //hook at once or wait for input + hooksoninit = GetPrivateProfileIntA(iniSettings.c_str(), "hooksoninit", 1, iniPath.c_str()); + + InitializeCriticalSection(&critical); + std::thread one(ThreadFunction, g_hModule); + one.detach(); + //CloseHandle(one); + return; + } +} \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h new file mode 100644 index 0000000..8a00493 --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h @@ -0,0 +1,41 @@ +#pragma once +#include "Hook.h" +#include "InstallHooks.h" + +namespace ScreenshotInput +{ + + class TranslateXtoMKB + { + private: + // static bool usetraqnslation; + + public: + //static bool TranslateXinputtoMKB; + //static POINT delta; + //static bool LMB; + //static bool RMB; + static HWND pointerWindows; + static int clipcursorhook; + static void Initialize(HMODULE g_hModule); + static int controllerID; + static int drawfakecursor; + static int getkeystatehook; + static int getasynckeystatehook; + static int getcursorposhook; + static int setcursorposhook; + static int setcursorhook; + static int rawinputhook; + static int GetKeyboardStateHook; + static bool registerrawinputhook; + static int showcursorhook; + + //void PollLoop(); + //void Sendinput(); + // bool HasGuiStatus() const override { return true; } + // void ShowGuiStatus() override; + // void InstallImpl() override; + // void UninstallImpl() override; + }; + +} \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/XinputHook.h b/src/ProtoInput/ProtoInputHooks/XinputHook.h index 861a870..0ff62c5 100644 --- a/src/ProtoInput/ProtoInputHooks/XinputHook.h +++ b/src/ProtoInput/ProtoInputHooks/XinputHook.h @@ -5,34 +5,34 @@ namespace Proto { -class XinputHook final : public Hook -{ -private: - std::vector hookInfos{}; - - static bool useDinput; - -public: - static unsigned int controllerIndex; - static unsigned int controllerIndex2; - static unsigned int controllerIndex3; - static unsigned int controllerIndex4; - - static bool useOpenXinput; - - const char* GetHookName() const override { return "Xinput"; } - const char* GetHookDescription() const override { - return - "Hooks Xinput functions to redirect input to the selected controller. " - "DirectInput (Dinput) redirecting is required to use more than 4 controllers (Xinput has a maximum of 4). "; - } - bool HasGuiStatus() const override { return true; } - void ShowGuiStatus() override; - void InstallImpl() override; - void UninstallImpl() override; - - static void SetUseDinput(bool useDinput); - static bool GetUseDinput() { return useDinput; } -}; - -} + class XinputHook final : public Hook + { + private: + std::vector hookInfos{}; + + static bool useDinput; + + public: + static unsigned int controllerIndex; + static unsigned int controllerIndex2; + static unsigned int controllerIndex3; + static unsigned int controllerIndex4; + + static bool useOpenXinput; + + const char* GetHookName() const override { return "Xinput"; } + const char* GetHookDescription() const override { + return + "Hooks Xinput functions to redirect input to the selected controller. " + "DirectInput (Dinput) redirecting is required to use more than 4 controllers (Xinput has a maximum of 4). "; + } + bool HasGuiStatus() const override { return true; } + void ShowGuiStatus() override; + void InstallImpl() override; + void UninstallImpl() override; + + static void SetUseDinput(bool useDinput); + static bool GetUseDinput() { return useDinput; } + }; + +} \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/dllmain.cpp b/src/ProtoInput/ProtoInputHooks/dllmain.cpp index c8350b7..2ec94ca 100644 --- a/src/ProtoInput/ProtoInputHooks/dllmain.cpp +++ b/src/ProtoInput/ProtoInputHooks/dllmain.cpp @@ -16,6 +16,7 @@ #include "FocusMessageLoop.h" #include "Gui.h" #include "FakeCursor.h" +#include "TranslateXtoMKB.h" HMODULE dll_hModule; @@ -42,6 +43,11 @@ DWORD WINAPI StartThread(LPVOID lpParameter) std::cout << "Hooks DLL loaded\n"; + Proto::StartPipeCommunication(); + + Sleep(50); //let pipe finish + + Proto::RawInput::InitialiseRawInput(); // Useful to add a pause if we need to attach a debugger // MessageBoxW(NULL, L"Press OK to start", L"", MB_OK); @@ -49,27 +55,31 @@ DWORD WINAPI StartThread(LPVOID lpParameter) Proto::FocusMessageLoop::SetupThread(); - Proto::FakeCursor::Initialise(); - Proto::AddThreadToACL(GetCurrentThreadId()); - - HANDLE hGuiThread = CreateThread(nullptr, 0, - (LPTHREAD_START_ROUTINE)GuiThread, dll_hModule, CREATE_SUSPENDED, &Proto::GuiThreadID); - - Proto::RawInput::InitialiseRawInput(); - - Proto::StartPipeCommunication(); - ResumeThread(hGuiThread); + if (!Proto::RawInput::TranslateXinputtoMKB) + { - if (hGuiThread != nullptr) - CloseHandle(hGuiThread); - - std::cout << "Reached end of startup thread\n"; - + + + Proto::FakeCursor::Initialise(); + + + + HANDLE hGuiThread = CreateThread(nullptr, 0, + (LPTHREAD_START_ROUTINE)GuiThread, dll_hModule, CREATE_SUSPENDED, &Proto::GuiThreadID); + + ResumeThread(hGuiThread); + + if (hGuiThread != nullptr) + CloseHandle(hGuiThread); + + std::cout << "Reached end of startup thread\n"; + } + else ScreenshotInput::TranslateXtoMKB::Initialize(dll_hModule); return 0; } - + // EasyHook entry point extern "C" __declspec(dllexport) void __stdcall NativeInjectionEntryPoint(REMOTE_ENTRY_INFO * inRemoteInfo) { diff --git a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h index 3410825..6ca78a4 100644 --- a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h +++ b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h @@ -7,6 +7,8 @@ namespace ProtoPipe enum class PipeMessageType { + AddSelectedMouseOrKeyboard, + SetTranslateXinputtoMKB, SetupHook, WakeUpProcess, SetupMessageFilter, @@ -18,7 +20,6 @@ enum class PipeMessageType SetDrawFakeCursor, SetDrawFakeCursorFix, SetExternalFreezeFakeInput, - AddSelectedMouseOrKeyboard, AddHandleToRename, SetControllerIndex, SetUseDinput, @@ -50,6 +51,16 @@ struct PipeMessageHeader PipeMessageType messageType; unsigned int messageSize; }; +struct PipeMessageAddSelectedMouseOrKeyboard +{ + unsigned int mouse = -1; + unsigned int keyboard = -1; +}; + +struct PipeMessageSetTranslateXinputtoMKB +{ + bool TranslateXinputtoMKB; +}; struct PipeMessageSetupHook { @@ -115,11 +126,7 @@ struct PipeMessageSetExternalFreezeFakeInput bool freezeEnabled; }; -struct PipeMesasgeAddSelectedMouseOrKeyboard -{ - unsigned int mouse = -1; - unsigned int keyboard = -1; -}; + struct PipeMessageAddHandleToRename { diff --git a/src/ProtoInput/ProtoInputHost/Gui.cpp b/src/ProtoInput/ProtoInputHost/Gui.cpp index e69f1a0..5e727e5 100644 --- a/src/ProtoInput/ProtoInputHost/Gui.cpp +++ b/src/ProtoInput/ProtoInputHost/Gui.cpp @@ -134,6 +134,12 @@ bool Launch() return false; }; + if (instance.mouseHandle != -1) + AddSelectedMouseHandle(instanceHandle, instance.mouseHandle); + + if (instance.keyboardHandle != -1) + AddSelectedKeyboardHandle(instanceHandle, instance.keyboardHandle); + SetTranslateXinputtoMKB(instanceHandle, currentProfile.TranslateXinputtoMKB); if (hookEnabled(RegisterRawInputHookID)) InstallHook(instanceHandle, RegisterRawInputHookID); if (hookEnabled(GetRawInputDataHookID)) InstallHook(instanceHandle, GetRawInputDataHookID); if (hookEnabled(MessageFilterHookID)) InstallHook(instanceHandle, MessageFilterHookID); @@ -157,6 +163,7 @@ bool Launch() if (hookEnabled(BlockRawInputHookID)) InstallHook(instanceHandle, BlockRawInputHookID); SetUseOpenXinput(instanceHandle, currentProfile.useOpenXinput); + SetUseDinputRedirection(instanceHandle, currentProfile.dinputToXinputRedirection); if (hookEnabled(XinputHookID)) InstallHook(instanceHandle, XinputHookID); @@ -207,11 +214,6 @@ bool Launch() for (const auto& renameNamedPipeHandle : currentProfile.renameNamedPipeHandles) AddNamedPipeToRename(instanceHandle, utf8_decode(renameNamedPipeHandle).c_str()); - if (instance.mouseHandle != -1) - AddSelectedMouseHandle(instanceHandle, instance.mouseHandle); - - if (instance.keyboardHandle != -1) - AddSelectedKeyboardHandle(instanceHandle, instance.keyboardHandle); SetControllerIndex(instanceHandle, instance.controllerIndex); @@ -671,8 +673,16 @@ void SelectedInstanceWindow() ImGui::PushID(128794); ImGui::Spacing(); - ImGui::TextWrapped("Controller index"); + ImGui::Separator(); ImGui::SliderInt("", (int*)&instance.controllerIndex, 0, 16, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::Separator(); + ImGui::TextWrapped("Controller index"); + ImGui::Separator(); + ImGui::Checkbox("Translate X to MKB", ¤tProfile.TranslateXinputtoMKB); // + ImGui::Separator(); + ImGui::Checkbox("Use OpenXinput", ¤tProfile.useOpenXinput); // + + ImGui::PopID(); } @@ -867,8 +877,6 @@ void OptionsMenu() ImGui::Checkbox("Dinput to Xinput redirection", ¤tProfile.dinputToXinputRedirection); - ImGui::Checkbox("Use OpenXinput", ¤tProfile.useOpenXinput); - ImGui::Checkbox("Use fake clip cursor", ¤tProfile.useFakeClipCursor); ImGui::Checkbox("Show fake cursor when image updated", ¤tProfile.showCursorWhenImageUpdated); diff --git a/src/ProtoInput/ProtoInputHost/Profiles.h b/src/ProtoInput/ProtoInputHost/Profiles.h index 3fe6cd5..a3a4f26 100644 --- a/src/ProtoInput/ProtoInputHost/Profiles.h +++ b/src/ProtoInput/ProtoInputHost/Profiles.h @@ -55,7 +55,7 @@ struct Profile { "Rename Handles", true, "Rename Handles", ProtoHookIDs::RenameHandlesHookID }, { "Block Raw Input", false, "Block Raw Input", ProtoHookIDs::BlockRawInputHookID }, { "Dinput Order", false, "Dinput Order", ProtoHookIDs::DinputOrderHookID }, - { "Xinput", false, "Xinput", ProtoHookIDs::XinputHookID } + { "Xinput", false, "Xinput", ProtoHookIDs::XinputHookID } }; std::vector messageFilters @@ -72,6 +72,7 @@ struct Profile bool dinputToXinputRedirection = false; bool useOpenXinput = false; + bool TranslateXinputtoMKB = false; bool useFakeClipCursor = true; @@ -114,6 +115,7 @@ struct Profile cereal::make_nvp("dinputToXinputRedirection", dinputToXinputRedirection), cereal::make_nvp("useOpenXinput", useOpenXinput), + cereal::make_nvp("TranslateXinputtoMKB", TranslateXinputtoMKB), cereal::make_nvp("useFakeClipCursor", useFakeClipCursor), cereal::make_nvp("showCursorWhenImageUpdated", showCursorWhenImageUpdated), diff --git a/src/ProtoInput/ProtoInputLoader/Inject.cpp b/src/ProtoInput/ProtoInputLoader/Inject.cpp index 58bcf33..89bd676 100644 --- a/src/ProtoInput/ProtoInputLoader/Inject.cpp +++ b/src/ProtoInput/ProtoInputLoader/Inject.cpp @@ -46,6 +46,49 @@ bool Isx64(unsigned long pid) return !is32; } +void AddSelectedInputHandleImpl(ProtoInstanceHandle instanceHandle, unsigned int handle, bool mouse) +{ + if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) + { + auto& instance = find->second; + + WaitClientConnect(instance); + + ProtoPipe::PipeMessageAddSelectedMouseOrKeyboard message //spelling okay? + { + mouse ? handle : -1, + mouse ? -1 : handle + }; + + ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::AddSelectedMouseOrKeyboard, &message); + } +} +extern "C" __declspec(dllexport) void AddSelectedMouseHandle(ProtoInstanceHandle instanceHandle, unsigned int mouseHandle) +{ + AddSelectedInputHandleImpl(instanceHandle, mouseHandle, true); +} + +extern "C" __declspec(dllexport) void AddSelectedKeyboardHandle(ProtoInstanceHandle instanceHandle, unsigned int keyboardHandle) +{ + AddSelectedInputHandleImpl(instanceHandle, keyboardHandle, false); +} +void SetTranslateXinputtoMKB(ProtoInstanceHandle instanceHandle, bool TranslateXinputtoMKB) +{ + if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) + { + auto& instance = find->second; + + WaitClientConnect(instance); + + ProtoPipe::PipeMessageSetTranslateXinputtoMKB message + { + TranslateXinputtoMKB + }; + + ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetTranslateXinputtoMKB, &message); + } +} + extern "C" __declspec(dllexport) void StartFocusMessageLoop(ProtoInstanceHandle instanceHandle, int milliseconds, bool wm_activate, bool wm_activateapp, bool wm_ncactivate, bool wm_setfocus, bool wm_mouseactivate) @@ -138,33 +181,7 @@ extern "C" __declspec(dllexport) void SetExternalFreezeFakeInput(ProtoInstanceHa } } -void AddSelectedInputHandleImpl(ProtoInstanceHandle instanceHandle, unsigned int handle, bool mouse) -{ - if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) - { - auto& instance = find->second; - - WaitClientConnect(instance); - ProtoPipe::PipeMesasgeAddSelectedMouseOrKeyboard message //spelling okay? - { - mouse ? handle : -1, - mouse ? -1 : handle - }; - - ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::AddSelectedMouseOrKeyboard, &message); - } -} - -extern "C" __declspec(dllexport) void AddSelectedMouseHandle(ProtoInstanceHandle instanceHandle, unsigned int mouseHandle) -{ - AddSelectedInputHandleImpl(instanceHandle, mouseHandle, true); -} - -extern "C" __declspec(dllexport) void AddSelectedKeyboardHandle(ProtoInstanceHandle instanceHandle, unsigned int keyboardHandle) -{ - AddSelectedInputHandleImpl(instanceHandle, keyboardHandle, false); -} extern "C" __declspec(dllexport) void SetControllerIndex(ProtoInstanceHandle instanceHandle, unsigned int controllerIndex, unsigned int controllerIndex2, unsigned int controllerIndex3, unsigned int controllerIndex4) { diff --git a/src/ProtoInput/ProtoInputLoader/include/protoloader.h b/src/ProtoInput/ProtoInputLoader/include/protoloader.h index 853489a..cf5daa2 100644 --- a/src/ProtoInput/ProtoInputLoader/include/protoloader.h +++ b/src/ProtoInput/ProtoInputLoader/include/protoloader.h @@ -55,6 +55,10 @@ extern "C" __declspec(dllexport) ProtoInstanceHandle EasyHookInjectStartup( unsigned long* outPid, void* environment = nullptr); + +extern "C" __declspec(dllexport) void AddSelectedMouseHandle(ProtoInstanceHandle instanceHandle, unsigned int mouseHandle); +extern "C" __declspec(dllexport) void AddSelectedKeyboardHandle(ProtoInstanceHandle instanceHandle, unsigned int keyboardHandle); +extern "C" __declspec(dllexport) void SetTranslateXinputtoMKB(ProtoInstanceHandle instanceHandle, bool TranslateXinputtoMKB); extern "C" __declspec(dllexport) void InstallHook(ProtoInstanceHandle instanceHandle, ProtoHookIDs hookID); extern "C" __declspec(dllexport) void UninstallHook(ProtoInstanceHandle instanceHandle, ProtoHookIDs hookID); @@ -84,8 +88,6 @@ extern "C" __declspec(dllexport) void SetDrawFakeCursorFix(ProtoInstanceHandle i extern "C" __declspec(dllexport) void SetExternalFreezeFakeInput(ProtoInstanceHandle instanceHandle, bool enableFreeze); -extern "C" __declspec(dllexport) void AddSelectedMouseHandle(ProtoInstanceHandle instanceHandle, unsigned int mouseHandle); -extern "C" __declspec(dllexport) void AddSelectedKeyboardHandle(ProtoInstanceHandle instanceHandle, unsigned int keyboardHandle); extern "C" __declspec(dllexport) void SetControllerIndex(ProtoInstanceHandle instanceHandle, unsigned int controllerIndex, unsigned int controllerIndex2 = 0, unsigned int controllerIndex3 = 0, unsigned int controllerIndex4 = 0); diff --git a/src/ProtoInput/ProtoInputUtil/InputLocker.cpp b/src/ProtoInput/ProtoInputUtil/InputLocker.cpp index f6356bb..006a393 100644 --- a/src/ProtoInput/ProtoInputUtil/InputLocker.cpp +++ b/src/ProtoInput/ProtoInputUtil/InputLocker.cpp @@ -13,7 +13,7 @@ LRESULT CALLBACK LowLevelMouseProc( ) { //TODO: change wparam/lparam instead of blocking - return isLocked ? 1 : CallNextHookEx(nullptr, nCode, wParam, lParam); + return CallNextHookEx(nullptr, nCode, wParam, lParam);// isLocked ? 1 : } LRESULT CALLBACK LowLevelKeyboardProc( @@ -75,7 +75,7 @@ extern "C" __declspec(dllexport) unsigned int LockInput(bool lock) if (lock && !installedHooks) { installedHooks = true; - SetWindowsHookExW(WH_MOUSE_LL, LowLevelMouseProc, GetModuleHandle(0), 0); + //SetWindowsHookExW(WH_MOUSE_LL, LowLevelMouseProc, GetModuleHandle(0), 0); SetWindowsHookExW(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(0), 0); } From 7072f584653a82544331c8874913de31e25ca3a6 Mon Sep 17 00:00:00 2001 From: messenils Date: Tue, 27 Jan 2026 19:40:21 +0100 Subject: [PATCH 03/20] Removed debug message. Fixed correct Xinput ID for TranslateXinput option --- src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp | 2 +- src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp b/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp index 2054676..4d4f57a 100644 --- a/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp @@ -57,7 +57,7 @@ UINT WINAPI Hook_GetRawInputData( void GetRawInputDataHook::InstallImpl() { - MessageBoxA(NULL, "Installing GetRawInputData Hook", "Info", MB_OK); + //MessageBoxA(NULL, "Installing GetRawInputData Hook", "Info", MB_OK); hookInfo = std::get<1>(InstallNamedHook(L"user32", "GetRawInputData", Hook_GetRawInputData)); } diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index 04d0a5a..ef50e5c 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -378,7 +378,7 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) XinputHook::controllerIndex4 = body->controllerIndex4; if (RawInput::TranslateXinputtoMKB == true) { - ScreenshotInput::TranslateXtoMKB::controllerID = XinputHook::controllerIndex; + ScreenshotInput::TranslateXtoMKB::controllerID = XinputHook::controllerIndex - 1; } break; } From d88d2533874c25d99b49ec2f419cba2073fe4b03 Mon Sep 17 00:00:00 2001 From: messenils Date: Fri, 6 Feb 2026 18:00:30 +0100 Subject: [PATCH 04/20] Erased TranslateXtoMKB and started over again. now all of protoinputs hooks and functions are reused. exept for a custom rawinputhook only used in XinputTranslation. missing button remappings. still a work in progress --- .../ProtoInputHooks/GtoMnK_RawInput.cpp | 302 ++ .../ProtoInputHooks/GtoMnK_RawInput.h | 25 + .../ProtoInputHooks/GtoMnK_RawInputHooks.cpp | 62 + .../ProtoInputHooks/GtoMnK_RawInputHooks.h | 11 + .../ProtoInputHooks/HookManager.cpp | 52 +- .../ProtoInputHooks/HwndSelector.cpp | 5 +- .../ProtoInputHooks/PipeCommunication.cpp | 4 - .../ProtoInputHooks/ProtoInputHooks.vcxproj | 4 + .../ProtoInputHooks.vcxproj.filters | 12 + src/ProtoInput/ProtoInputHooks/RawInput.cpp | 174 +- src/ProtoInput/ProtoInputHooks/RawInput.h | 2 + .../ProtoInputHooks/TranslateXtoMKB.cpp | 4345 ++--------------- .../ProtoInputHooks/TranslateXtoMKB.h | 23 +- src/ProtoInput/ProtoInputHooks/dllmain.cpp | 29 +- 14 files changed, 1000 insertions(+), 4050 deletions(-) create mode 100644 src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.cpp create mode 100644 src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.h create mode 100644 src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.cpp create mode 100644 src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.h diff --git a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.cpp b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.cpp new file mode 100644 index 0000000..c2ed913 --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.cpp @@ -0,0 +1,302 @@ +#include "GtoMnK_RawInput.h" +#include "GtoMnK_RawInputHooks.h" +#include "HwndSelector.h" + +namespace ScreenshotInput { + + //public + RAWINPUT RawInput::g_inputBuffer[20]{}; + std::vector RawInput::g_forwardingWindows{}; + HWND RawInput::g_rawInputHwnd = nullptr; + bool RawInput::createdWindowIsOwned; + LRESULT WINAPI RawInputWindowWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + DWORD WINAPI RawInputWindowThread(LPVOID lpParameter); + //void RecoverMissedRegistration(); + + // A fix for RawInput registrations that get lost. e.g when we use `StartUpDelay` or add a dinput.dll + void RecoverMissedRegistration() { + UINT nDevices = 0; + GetRegisteredRawInputDevices(NULL, &nDevices, sizeof(RAWINPUTDEVICE)); + + if (nDevices == 0) return; + + std::vector devices(nDevices); + if (GetRegisteredRawInputDevices(devices.data(), &nDevices, sizeof(RAWINPUTDEVICE)) == (UINT)-1) { + return; + } + + //LOG("Recovery: checking %u registered RawInput devices...", nDevices); + + for (const auto& device : devices) { + if (device.usUsagePage == 1 && device.usUsage == 2) { + + HWND target = device.hwndTarget; + + // If target is NULL, it means "Focus Window", so we rely on our Foreground check. + // But if it is NOT NULL, it is the specific window (likely hidden) the game wants. + if (target != NULL) { + + bool known = false; + for (auto w : RawInput::g_forwardingWindows) { + if (w == target) { known = true; break; } + } + + if (!known) { + //LOG("Recovery: Found registered RawInput Target (0x%p). Adding to list.", target); + RawInput::g_forwardingWindows.push_back(target); + } + } + } + } + } + void RawInput::Initialize() { + // LOG("RawInput System: Initializing..."); + + RecoverMissedRegistration(); + + HANDLE hWindowReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (hWindowReadyEvent == NULL) { + //LOG("FATAL: Could not create window ready event!"); + return; + } + + HANDLE hThread = CreateThread(nullptr, 0, RawInputWindowThread, hWindowReadyEvent, 0, 0); + if (hThread) { + WaitForSingleObject(hWindowReadyEvent, 2000); + CloseHandle(hThread); + } + RawInputHooks::InstallHooks(); + CloseHandle(hWindowReadyEvent); + } + + void RawInput::Shutdown() { + //LOG("RawInput System: Shutting down..."); + + if (RawInput::g_rawInputHwnd) { + PostMessage(RawInput::g_rawInputHwnd, WM_QUIT, 0, 0); + } + } + + + + LRESULT WINAPI RawInputWindowWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + case WM_DESTROY: { + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + + DWORD WINAPI RawInputWindowThread(LPVOID lpParameter) { + HANDLE hWindowReadyEvent = (HANDLE)lpParameter; + + /*if (createdWindowIsOwned) + { + hwnd = GetMainWindowHandle(GetCurrentProcessId(), iniWindowName, iniClassName, 60000); + + if (!hwnd || !IsWindow(hwnd)) { + LOG("Timeout: Game Window never appeared. RawInput aborting."); + return 1; + } + LOG("RawInput window is owned by the game window."); + }*/ + + //LOG("RawInput hidden window thread started."); + WNDCLASSW wc = { 0 }; + wc.lpfnWndProc = RawInputWindowWndProc; + wc.hInstance = GetModuleHandle(NULL); + wc.lpszClassName = L"GtoMnK_RawInput_Window"; + + HWND parentWindow; + if (RawInput::createdWindowIsOwned) + parentWindow = (HWND)Proto::HwndSelector::GetSelectedHwnd(); + else + parentWindow = nullptr; + + if (RegisterClassW(&wc)) { + RawInput::g_rawInputHwnd = CreateWindowW(wc.lpszClassName, L"GtoMnK RI Sink", 0, 0, 0, 0, 0, parentWindow, NULL, wc.hInstance, NULL); + } + + if (!RawInput::g_rawInputHwnd) { + //LOG("FATAL: Failed to create RawInput hidden window!"); + SetEvent(hWindowReadyEvent); + return 1; + } + + SetEvent(hWindowReadyEvent); + //LOG("RawInput hidden window created and ready."); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0) > 0) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + //LOG("RawInput hidden window thread finished."); + return 0; + } + + void RawInput::InjectFakeRawInput(const RAWINPUT& fakeInput) { + static size_t bufferCounter = 0; + bufferCounter = (bufferCounter + 1) % RawInput::RAWINPUT_BUFFER_SIZE; + RawInput::g_inputBuffer[bufferCounter] = fakeInput; + + const LPARAM magicLParam = (bufferCounter) | 0xAB000000; + + for (const auto& hwnd : RawInput::g_forwardingWindows) { + PostMessageW(hwnd, WM_INPUT, RIM_INPUT, magicLParam); + + } + } + void RawInput::GenerateRawKey(int vkCode, bool press, bool isExtended) { + if (vkCode == 0) return; + + RAWINPUT ri = {}; + ri.header.dwType = RIM_TYPEKEYBOARD; + ri.header.hDevice = NULL; + + UINT scanCode = MapVirtualKey(vkCode, MAPVK_VK_TO_VSC); + ri.data.keyboard.MakeCode = scanCode; + ri.data.keyboard.Message = press ? WM_KEYDOWN : WM_KEYUP; + ri.data.keyboard.VKey = vkCode; + ri.data.keyboard.Flags = press ? RI_KEY_MAKE : RI_KEY_BREAK; + + if (isExtended) { + ri.data.keyboard.Flags |= RI_KEY_E0; + } + + RawInput::InjectFakeRawInput(ri); + } + + void RawInput::GenerateRawMouseButton(int actionCode, bool press) { + RAWINPUT ri = {}; + ri.header.dwType = RIM_TYPEMOUSE; + ri.header.hDevice = NULL; + if (actionCode == -8) { // Left Double + GenerateRawMouseButton(-1, true); GenerateRawMouseButton(-1, false); + GenerateRawMouseButton(-1, press); return; + } + if (actionCode == -9) { // Right Double + GenerateRawMouseButton(-2, true); GenerateRawMouseButton(-2, false); + GenerateRawMouseButton(-2, press); return; + } + if (actionCode == -10) { // Middle Double + GenerateRawMouseButton(-3, true); GenerateRawMouseButton(-3, false); + GenerateRawMouseButton(-3, press); return; + } + if (actionCode == -11) { // X1 Double + GenerateRawMouseButton(-4, true); GenerateRawMouseButton(-4, false); + GenerateRawMouseButton(-4, press); return; + } + if (actionCode == -12) { // X2 Double + GenerateRawMouseButton(-5, true); GenerateRawMouseButton(-5, false); + GenerateRawMouseButton(-5, press); return; + } + switch (actionCode) { + case -1: ri.data.mouse.usButtonFlags = press ? RI_MOUSE_LEFT_BUTTON_DOWN : RI_MOUSE_LEFT_BUTTON_UP; break; + case -2: ri.data.mouse.usButtonFlags = press ? RI_MOUSE_RIGHT_BUTTON_DOWN : RI_MOUSE_RIGHT_BUTTON_UP; break; + case -3: ri.data.mouse.usButtonFlags = press ? RI_MOUSE_MIDDLE_BUTTON_DOWN : RI_MOUSE_MIDDLE_BUTTON_UP; break; + case -4: ri.data.mouse.usButtonFlags = press ? RI_MOUSE_BUTTON_4_DOWN : RI_MOUSE_BUTTON_4_UP; break; + case -5: ri.data.mouse.usButtonFlags = press ? RI_MOUSE_BUTTON_5_DOWN : RI_MOUSE_BUTTON_5_UP; break; + case -6: if (press) ri.data.mouse.usButtonFlags = RI_MOUSE_WHEEL; ri.data.mouse.usButtonData = WHEEL_DELTA; break; + case -7: if (press) ri.data.mouse.usButtonFlags = RI_MOUSE_WHEEL; ri.data.mouse.usButtonData = -WHEEL_DELTA; break; + } + RawInput::InjectFakeRawInput(ri); + } + + // For keyboard actions for both methods + void RawInput::TranslateKeyboardAction(int actionCode, int& outVkCode, bool& outIsExtended) { + outVkCode = 0; + outIsExtended = false; + + // Special & Modifier Keys + if (actionCode == 1) outVkCode = VK_ESCAPE; + if (actionCode == 2) outVkCode = VK_RETURN; // Main Enter Key + if (actionCode == 3) outVkCode = VK_TAB; + if (actionCode == 4) outVkCode = VK_SHIFT; // Generic Shift + if (actionCode == 5) outVkCode = VK_LSHIFT; // Left Shift + if (actionCode == 6) outVkCode = VK_RSHIFT; // Right Shift + if (actionCode == 7) outVkCode = VK_CONTROL; // Generic Control + if (actionCode == 8) outVkCode = VK_LCONTROL; // Left Control + if (actionCode == 9) outVkCode = VK_RCONTROL; // Right Control + if (actionCode == 10) outVkCode = VK_MENU; // Generic Alt + if (actionCode == 11) outVkCode = VK_LMENU; // Left Alt + if (actionCode == 12) outVkCode = VK_RMENU; // Right Alt + if (actionCode == 13) outVkCode = VK_SPACE; + if (actionCode == 14) outVkCode = VK_UP; // Arrow Up + if (actionCode == 15) outVkCode = VK_DOWN; // Arrow Down + if (actionCode == 16) outVkCode = VK_LEFT; // Arrow Left + if (actionCode == 17) outVkCode = VK_RIGHT; // Arrow Right + if (actionCode == 18) outVkCode = VK_BACK; // Backspace + if (actionCode == 19) outVkCode = VK_DELETE; + if (actionCode == 20) outVkCode = VK_INSERT; + if (actionCode == 21) outVkCode = VK_END; + if (actionCode == 22) outVkCode = VK_HOME; + if (actionCode == 23) outVkCode = VK_PRIOR; // Page Up + if (actionCode == 24) outVkCode = VK_NEXT; // Page Down + // Alphabet + if (actionCode >= 25 && actionCode <= 50) outVkCode = 'A' + (actionCode - 25); + // Top Row Numbers + if (actionCode >= 51 && actionCode <= 60) outVkCode = '0' + (actionCode - 51); + // F-Keys + if (actionCode >= 61 && actionCode <= 72) outVkCode = VK_F1 + (actionCode - 61); + // Numpad Numbers & Operators + if (actionCode >= 73 && actionCode <= 82) outVkCode = VK_NUMPAD0 + (actionCode - 73); + if (actionCode == 83) outVkCode = VK_ADD; + if (actionCode == 84) outVkCode = VK_SUBTRACT; + if (actionCode == 85) outVkCode = VK_MULTIPLY; + if (actionCode == 86) outVkCode = VK_DIVIDE; + if (actionCode == 87) outVkCode = VK_DECIMAL; + if (actionCode == 88) outVkCode = VK_RETURN; // Numpad Enter + // Numpad Navigation (when NumLock is OFF) + if (actionCode == 91) outVkCode = VK_INSERT; // Numpad 0 + if (actionCode == 92) outVkCode = VK_END; // Numpad 1 + if (actionCode == 93) outVkCode = VK_DOWN; // Numpad 2 + if (actionCode == 94) outVkCode = VK_NEXT; // Numpad 3 + if (actionCode == 95) outVkCode = VK_LEFT; // Numpad 4 + if (actionCode == 96) outVkCode = VK_RIGHT; // Numpad 6 + if (actionCode == 97) outVkCode = VK_HOME; // Numpad 7 + if (actionCode == 98) outVkCode = VK_UP; // Numpad 8 + if (actionCode == 99) outVkCode = VK_PRIOR; // Numpad 9 + if (actionCode == 100) outVkCode = VK_DELETE; // Numpad . + // Lock Keys + if (actionCode == 101) outVkCode = VK_CAPITAL; // Caps Lock + if (actionCode == 102) outVkCode = VK_NUMLOCK; // Num Lock + if (actionCode == 103) outVkCode = VK_SCROLL; // Scroll Lock + // Symbols + if (actionCode == 104) outVkCode = VK_OEM_1; // ; (Semicolon) + if (actionCode == 105) outVkCode = VK_OEM_PLUS; // = (Plus/Equal) + if (actionCode == 106) outVkCode = VK_OEM_COMMA; // , (Comma) + if (actionCode == 107) outVkCode = VK_OEM_MINUS; // - (Minus) + if (actionCode == 108) outVkCode = VK_OEM_PERIOD; // . (Period) + if (actionCode == 109) outVkCode = VK_OEM_2; // / (Forward Slash) + if (actionCode == 110) outVkCode = VK_OEM_3; // ` (Grave Accent) + if (actionCode == 111) outVkCode = VK_OEM_4; // [ (Left Bracket) + if (actionCode == 112) outVkCode = VK_OEM_5; // \ (Backslash) + if (actionCode == 113) outVkCode = VK_OEM_6; // ] (Right Bracket) + if (actionCode == 114) outVkCode = VK_OEM_7; // ' (Apostrophe) + // Extended Keys + if ((actionCode >= 14 && actionCode <= 17) || // Dedicated Arrow Keys + (actionCode >= 19 && actionCode <= 24) || // Insert, Del, Home, End, PgUp, PgDn + actionCode == 9 || // Right Control + actionCode == 12 || // Right Alt + actionCode == 88 || // Numpad Enter + actionCode == 102) + { + outIsExtended = true; + } + } + void RawInput::SendActionDelta(int deltaX, int deltaY) + { + RAWINPUT ri = {}; + ri.header.dwType = RIM_TYPEMOUSE; + ri.header.hDevice = NULL; + ri.data.mouse.usFlags = MOUSE_MOVE_RELATIVE; + ri.data.mouse.lLastX = deltaX; + ri.data.mouse.lLastY = deltaY; + RawInput::InjectFakeRawInput(ri); + } + +} \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.h b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.h new file mode 100644 index 0000000..5652943 --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +namespace ScreenshotInput { + class RawInput { + public: + // To start the RawInput method. + static void Initialize(); + + static void Shutdown(); + + static void InjectFakeRawInput(const RAWINPUT& fakeInput); + static void TranslateKeyboardAction(int actionCode, int& outVkCode, bool& outIsExtended); + static void GenerateRawMouseButton(int actionCode, bool press); + static void GenerateRawKey(int vkCode, bool press, bool isExtended); + static void SendActionDelta(int deltaX, int deltaY); + static const int RAWINPUT_BUFFER_SIZE = 20; + static RAWINPUT g_inputBuffer[RAWINPUT_BUFFER_SIZE]; + + static std::vector g_forwardingWindows; + static HWND g_rawInputHwnd; + static bool createdWindowIsOwned; + }; +} \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.cpp b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.cpp new file mode 100644 index 0000000..ed667d5 --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.cpp @@ -0,0 +1,62 @@ +//#include "pch.h" +#include "GtoMnK_RawInputHooks.h" +#include "GtoMnK_RawInput.h" +#include "KeyboardButtonFilter.h" +//#include "Mouse.h" +//#include "Keyboard.h" +#include "EasyHook.h" +// Thanks to ProtoInput. + +namespace ScreenshotInput +{ + HOOK_TRACE_INFO g_getRawInputDataHook = { NULL }; + HOOK_TRACE_INFO g_registerRawInputDevicesHook = { NULL }; + + UINT WINAPI GetRawInputDataHook(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader) { + UINT handleValue = (UINT)(UINT_PTR)hRawInput; + if ((handleValue & 0xFF000000) == 0xAB000000) { + UINT bufferIndex = handleValue & 0x00FFFFFF; + + if (bufferIndex >= ScreenshotInput::RawInput::RAWINPUT_BUFFER_SIZE) { + return GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader); + } + + if (pData == NULL) { + *pcbSize = sizeof(RAWINPUT); + return 0; + } + + RAWINPUT* storedData = &ScreenshotInput::RawInput::g_inputBuffer[bufferIndex]; + memcpy(pData, storedData, sizeof(RAWINPUT)); + return sizeof(RAWINPUT); + + } + else { + return GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader); + } + } + + BOOL WINAPI RegisterRawInputDevicesHook(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize) { + for (UINT i = 0; i < uiNumDevices; ++i) { + HWND targetHwnd = pRawInputDevices[i].hwndTarget; + + if (targetHwnd != NULL && targetHwnd != ScreenshotInput::RawInput::g_rawInputHwnd) { + auto& windows = ScreenshotInput::RawInput::g_forwardingWindows; + if (std::find(windows.begin(), windows.end(), targetHwnd) == windows.end()) { + //LOG("Captured new game window HWND: 0x%p", targetHwnd); + windows.push_back(targetHwnd); + } + } + } + return TRUE; + } + void RawInputHooks::InstallHooks() { + // Install GetRawInputData hook + HMODULE hUser32 = GetModuleHandleA("user32"); + LhInstallHook(GetProcAddress(hUser32, "GetRawInputData"), GetRawInputDataHook, NULL, &g_getRawInputDataHook); + LhInstallHook(GetProcAddress(hUser32, "RegisterRawInputDevices"), RegisterRawInputDevicesHook, NULL, &g_registerRawInputDevicesHook); + ULONG ACLEntries[1] = { 0 }; + LhSetExclusiveACL(ACLEntries, 1, &g_getRawInputDataHook); + LhSetExclusiveACL(ACLEntries, 1, &g_registerRawInputDevicesHook); + } +} \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.h b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.h new file mode 100644 index 0000000..3c1f44b --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.h @@ -0,0 +1,11 @@ +#pragma once +#include + +namespace ScreenshotInput { + class RawInputHooks { + public: + //UINT WINAPI GetRawInputDataHook(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader); + //BOOL WINAPI RegisterRawInputDevicesHook(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize); + static void InstallHooks(); + }; +} diff --git a/src/ProtoInput/ProtoInputHooks/HookManager.cpp b/src/ProtoInput/ProtoInputHooks/HookManager.cpp index 98bbca1..d581316 100644 --- a/src/ProtoInput/ProtoInputHooks/HookManager.cpp +++ b/src/ProtoInput/ProtoInputHooks/HookManager.cpp @@ -67,19 +67,16 @@ void HookManager::InstallHook(ProtoHookIDs hookID) hookManagerInstance.hooks[hookID]->Install(); else // skipping original protoinput hooks on experimental Xinput to MKB translation mode { - if (hookID == 0) ScreenshotInput::TranslateXtoMKB::registerrawinputhook = 1; - if (hookID == 1) ScreenshotInput::TranslateXtoMKB::rawinputhook = 1; - if (hookID == 2) ScreenshotInput::TranslateXtoMKB::rawinputhook = 1; //messagefilter - if (hookID == 3) ScreenshotInput::TranslateXtoMKB::getcursorposhook = 1; - if (hookID == 4) ScreenshotInput::TranslateXtoMKB::setcursorposhook = 1; - if (hookID == 5) ScreenshotInput::TranslateXtoMKB::getkeystatehook = 1; - if (hookID == 6) ScreenshotInput::TranslateXtoMKB::getasynckeystatehook = 1; - if (hookID == 7) ScreenshotInput::TranslateXtoMKB::GetKeyboardStateHook = 1; - if (hookID == 8) { - ScreenshotInput::TranslateXtoMKB::showcursorhook = 1; - ScreenshotInput::TranslateXtoMKB::setcursorhook = 1; - } - if (hookID == 9) ScreenshotInput::TranslateXtoMKB::clipcursorhook = 1; + if (hookID == 0) ScreenshotInput::TranslateXtoMKB::registerrawinputhook = true; + if (hookID == 1) ScreenshotInput::TranslateXtoMKB::rawinputhook = true; + if (hookID == 2) hookManagerInstance.hooks[hookID]->Install(); + if (hookID == 3) hookManagerInstance.hooks[hookID]->Install(); + if (hookID == 4) hookManagerInstance.hooks[hookID]->Install(); + if (hookID == 5) hookManagerInstance.hooks[hookID]->Install(); + if (hookID == 6) hookManagerInstance.hooks[hookID]->Install(); + if (hookID == 7) hookManagerInstance.hooks[hookID]->Install(); + if (hookID == 8) hookManagerInstance.hooks[hookID]->Install(); + if (hookID == 9) hookManagerInstance.hooks[hookID]->Install(); if (hookID > 9 && hookID != 15) //15 is block rawinput dont want that. hookManagerInstance.hooks[hookID]->Install(); @@ -96,8 +93,19 @@ void HookManager::UninstallHook(ProtoHookIDs hookID) { if (!RawInput::TranslateXinputtoMKB) hookManagerInstance.hooks[hookID]->Uninstall(); - else if (hookID > 9) // skipping original protoinput hooks on experimental Xinput to MKB translation mode - hookManagerInstance.hooks[hookID]->Uninstall(); + else + if (hookID == 0) ScreenshotInput::TranslateXtoMKB::registerrawinputhook = false; + if (hookID == 1) ScreenshotInput::TranslateXtoMKB::rawinputhook = false; + if (hookID == 2) hookManagerInstance.hooks[hookID]->Uninstall(); + if (hookID == 3) hookManagerInstance.hooks[hookID]->Uninstall(); + if (hookID == 4) hookManagerInstance.hooks[hookID]->Uninstall(); + if (hookID == 5) hookManagerInstance.hooks[hookID]->Uninstall(); + if (hookID == 6) hookManagerInstance.hooks[hookID]->Uninstall(); + if (hookID == 7) hookManagerInstance.hooks[hookID]->Uninstall(); + if (hookID == 8) hookManagerInstance.hooks[hookID]->Uninstall(); + if (hookID == 9) hookManagerInstance.hooks[hookID]->Uninstall(); + if (hookID > 9 && hookID != 15) //15 is block rawinput dont want that. + hookManagerInstance.hooks[hookID]->Uninstall(); } } @@ -110,11 +118,15 @@ bool HookManager::IsInstalled(ProtoHookIDs hookID) } else { - if (!RawInput::TranslateXinputtoMKB) - return hookManagerInstance.hooks[hookID]->IsInstalled(); - else if (hookID < 10) return true; - else return hookManagerInstance.hooks[hookID]->IsInstalled(); - + if(RawInput::TranslateXinputtoMKB) + { + if (hookID == 0) return true; + if (hookID == 1) return true; + if (hookID == 2) return hookManagerInstance.hooks[hookID]->IsInstalled(); + else return hookManagerInstance.hooks[hookID]->IsInstalled(); + } + else + return hookManagerInstance.hooks[hookID]->IsInstalled(); } } diff --git a/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp b/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp index a957af4..06ef942 100644 --- a/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp +++ b/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp @@ -21,12 +21,11 @@ BOOL IsMainWindow(HWND handle) { // Is top level & visible & not one of ours return - GetWindow(handle, GW_OWNER) == (HWND)0 && + GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle) && handle != (HWND)Proto::ConsoleHwnd && handle != Proto::ProtoGuiHwnd && - handle != FakeCursor::GetPointerWindow() && - handle != ScreenshotInput::TranslateXtoMKB::pointerWindows; + handle != FakeCursor::GetPointerWindow(); } BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index ef50e5c..cb5fdbc 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -324,10 +324,6 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) printf("Received message to %s fake cursor\n", body->enable ? "enable" : "disable"); FakeCursor::EnableDisableFakeCursor(body->enable); - if (body->enable) //1 game hdc //2 partial draw //3 full draw - ScreenshotInput::TranslateXtoMKB::drawfakecursor = 3; - else - ScreenshotInput::TranslateXtoMKB::drawfakecursor = 0; break; } diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj index cee13be..48e0758 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj @@ -209,6 +209,8 @@ + + @@ -270,6 +272,8 @@ + + diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters index 043b5e9..5329185 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters @@ -186,6 +186,12 @@ Source Files\Hooks\TranslateXtoMKB + + Source Files\Hooks\TranslateXtoMKB + + + Source Files\Hooks\TranslateXtoMKB + @@ -332,5 +338,11 @@ Source Files\Hooks\TranslateXtoMKB + + Source Files\Hooks\TranslateXtoMKB + + + Source Files\Hooks\TranslateXtoMKB + \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.cpp b/src/ProtoInput/ProtoInputHooks/RawInput.cpp index d2ef14f..62ac558 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.cpp +++ b/src/ProtoInput/ProtoInputHooks/RawInput.cpp @@ -42,74 +42,13 @@ const std::vector RawInput::usageTypesOfInterest HWND RawInput::rawInputHwnd = nullptr; -void RawInput::ProcessMouseInput(const RAWMOUSE& data, HANDLE deviceHandle) -{ - // Update fake mouse position - if ((data.usFlags & MOUSE_MOVE_ABSOLUTE) == MOUSE_MOVE_ABSOLUTE) - { - const bool isVirtualDesktop = (data.usFlags & MOUSE_VIRTUAL_DESKTOP) == MOUSE_VIRTUAL_DESKTOP; - - // const int width = GetSystemMetrics(isVirtualDesktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN); - // const int height = GetSystemMetrics(isVirtualDesktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN); - - static int widthVirtual = GetSystemMetrics(SM_CXVIRTUALSCREEN); - static int widthNonVirtual = GetSystemMetrics(SM_CXSCREEN); - static int heightVirtual = GetSystemMetrics(SM_CYVIRTUALSCREEN); - static int heightNonVirtual = GetSystemMetrics(SM_CYSCREEN); - - const int absoluteX = int((data.lLastX / 65535.0f) * (isVirtualDesktop ? widthVirtual : widthNonVirtual)); - const int absoluteY = int((data.lLastY / 65535.0f) * (isVirtualDesktop ? heightVirtual : heightNonVirtual)); - - static std::unordered_map> oldPositions{}; - - if (const auto find = oldPositions.find(deviceHandle); find != oldPositions.end()) - { - FakeMouseKeyboard::AddMouseDelta(absoluteX - find->second.first, absoluteY - find->second.second); - } - else - { - oldPositions.emplace(std::make_pair( deviceHandle, std::pair{ absoluteX, absoluteY } )); - } - } - else if (data.lLastX != 0 || data.lLastY != 0) - { - const int relativeX = data.lLastX; - const int relativeY = data.lLastY; - FakeMouseKeyboard::AddMouseDelta(relativeX, relativeY); - } - - // Set vkeys (GetKeyState/etc can be used to get the mouse buttons state) - if ((data.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) != 0) - FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_LBUTTON, true); - if ((data.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) != 0) - FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_LBUTTON, false); - - if ((data.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) != 0) - FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_MBUTTON, true); - if ((data.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) != 0) - FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_MBUTTON, false); - - if ((data.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) != 0) - FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_RBUTTON, true); - if ((data.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) != 0) - FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_RBUTTON, false); - - if ((data.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) != 0) - FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_XBUTTON1, true); - if ((data.usButtonFlags & RI_MOUSE_BUTTON_4_UP) != 0) - FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_XBUTTON1, false); - - if ((data.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) != 0) - FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_XBUTTON2, true); - if ((data.usButtonFlags & RI_MOUSE_BUTTON_5_UP) != 0) - FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_XBUTTON2, false); - - +void RawInput::SendInputMessages(const RAWMOUSE& data) +{ // This is used a lot in sending messages const unsigned int mouseMkFlags = FakeMouseKeyboard::GetMouseMkFlags(); const unsigned int mousePointLparam = MAKELPARAM(FakeMouseKeyboard::GetMouseState().x, FakeMouseKeyboard::GetMouseState().y); - - + + // Send mouse wheel if (rawInputState.sendMouseWheelMessages) { @@ -173,7 +112,7 @@ void RawInput::ProcessMouseInput(const RAWMOUSE& data, HANDLE deviceHandle) } // Send mouse button messages else if (rawInputState.sendMouseButtonMessages) - { + { if ((data.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) != 0) PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_LBUTTONDOWN, mouseMkFlags | MouseButtonFilter::signature, mousePointLparam); if ((data.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) != 0) @@ -207,42 +146,100 @@ void RawInput::ProcessMouseInput(const RAWMOUSE& data, HANDLE deviceHandle) { PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_MOUSEMOVE, mouseMkFlags, mousePointLparam); } + FakeCursor::NotifyUpdatedCursorPosition(); + +} + +void RawInput::ProcessMouseInput(const RAWMOUSE& data, HANDLE deviceHandle) +{ + // Update fake mouse position + if ((data.usFlags & MOUSE_MOVE_ABSOLUTE) == MOUSE_MOVE_ABSOLUTE) + { + const bool isVirtualDesktop = (data.usFlags & MOUSE_VIRTUAL_DESKTOP) == MOUSE_VIRTUAL_DESKTOP; + + // const int width = GetSystemMetrics(isVirtualDesktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN); + // const int height = GetSystemMetrics(isVirtualDesktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN); + + static int widthVirtual = GetSystemMetrics(SM_CXVIRTUALSCREEN); + static int widthNonVirtual = GetSystemMetrics(SM_CXSCREEN); + static int heightVirtual = GetSystemMetrics(SM_CYVIRTUALSCREEN); + static int heightNonVirtual = GetSystemMetrics(SM_CYSCREEN); + + const int absoluteX = int((data.lLastX / 65535.0f) * (isVirtualDesktop ? widthVirtual : widthNonVirtual)); + const int absoluteY = int((data.lLastY / 65535.0f) * (isVirtualDesktop ? heightVirtual : heightNonVirtual)); + + static std::unordered_map> oldPositions{}; + + if (const auto find = oldPositions.find(deviceHandle); find != oldPositions.end()) + { + FakeMouseKeyboard::AddMouseDelta(absoluteX - find->second.first, absoluteY - find->second.second); + } + else + { + oldPositions.emplace(std::make_pair( deviceHandle, std::pair{ absoluteX, absoluteY } )); + } + } + else if (data.lLastX != 0 || data.lLastY != 0) + { + const int relativeX = data.lLastX; + const int relativeY = data.lLastY; + FakeMouseKeyboard::AddMouseDelta(relativeX, relativeY); + } + + // Set vkeys (GetKeyState/etc can be used to get the mouse buttons state) + if ((data.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) != 0) + FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_LBUTTON, true); + if ((data.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) != 0) + FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_LBUTTON, false); + if ((data.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) != 0) + FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_MBUTTON, true); + if ((data.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) != 0) + FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_MBUTTON, false); + if ((data.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) != 0) + FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_RBUTTON, true); + if ((data.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) != 0) + FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_RBUTTON, false); - // Fake cursor - FakeCursor::NotifyUpdatedCursorPosition(); + if ((data.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) != 0) + FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_XBUTTON1, true); + if ((data.usButtonFlags & RI_MOUSE_BUTTON_4_UP) != 0) + FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_XBUTTON1, false); + + if ((data.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) != 0) + FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_XBUTTON2, true); + if ((data.usButtonFlags & RI_MOUSE_BUTTON_5_UP) != 0) + FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_XBUTTON2, false); + RawInput::SendInputMessages(data); } -void RawInput::ProcessKeyboardInput(const RAWKEYBOARD& data, HANDLE deviceHandle) +void RawInput::SendKeyMessage(const RAWKEYBOARD& data, bool pressed) { - const bool released = (data.Flags & RI_KEY_BREAK) != 0; - const bool pressed = !released; - - if (pressed && FakeCursor::GetToggleVisilbityShorcutEnabled() && data.VKey == FakeCursor::GetToggleVisibilityVkey()) + if (pressed && FakeCursor::GetToggleVisilbityShorcutEnabled() && data.VKey == FakeCursor::GetToggleVisibilityVkey()) { FakeCursor::SetCursorVisibility(!FakeCursor::GetCursorVisibility()); return; } - + if (rawInputState.sendKeyboardPressMessages) { if (pressed) { unsigned int lparam = 0; - + lparam |= 1; // Repeat bit lparam |= (data.MakeCode << 16); // Scan code - + if (FakeMouseKeyboard::IsKeyStatePressed(data.VKey)) { lparam |= (1 << 30); } - - PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYDOWN, - MessageFilterHook::IsKeyboardButtonFilterEnabled() ? data.VKey | KeyboardButtonFilter::signature : data.VKey, + + PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYDOWN, + MessageFilterHook::IsKeyboardButtonFilterEnabled() ? data.VKey | KeyboardButtonFilter::signature : data.VKey, lparam); - + // if (data.VKey == VK_SHIFT || data.VKey == VK_LSHIFT) // { // PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYDOWN, VK_SHIFT, lparam); @@ -253,7 +250,7 @@ void RawInput::ProcessKeyboardInput(const RAWKEYBOARD& data, HANDLE deviceHandle // PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYDOWN, data.VKey, lparam); // } } - else if (released) + else { unsigned int lparam = 0; lparam |= 1; // Repeat count (always 1 for key up) @@ -261,10 +258,10 @@ void RawInput::ProcessKeyboardInput(const RAWKEYBOARD& data, HANDLE deviceHandle lparam |= (1 << 30); // Previous key state (always 1 for key up) lparam |= (1 << 31); // Transition state (always 1 for key up) - PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYUP, + PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYUP, MessageFilterHook::IsKeyboardButtonFilterEnabled() ? data.VKey | KeyboardButtonFilter::signature : data.VKey, lparam); - + // if (data.VKey == VK_SHIFT || data.VKey == VK_LSHIFT) // { // PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYUP, VK_SHIFT, lparam); @@ -274,9 +271,16 @@ void RawInput::ProcessKeyboardInput(const RAWKEYBOARD& data, HANDLE deviceHandle // { // PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYUP, data.VKey, lparam); // } - + } } +} +void RawInput::ProcessKeyboardInput(const RAWKEYBOARD& data, HANDLE deviceHandle) +{ + const bool released = (data.Flags & RI_KEY_BREAK) != 0; + const bool pressed = !released; + + RawInput::SendKeyMessage(data, pressed); FakeMouseKeyboard::ReceivedKeyPressOrRelease(data.VKey, pressed); } @@ -339,7 +343,7 @@ void RawInput::ProcessRawInput(HRAWINPUT rawInputHandle, bool inForeground, cons { //TODO: This may waste CPU? (But need a way to update window otherwise) //if (HwndSelector::GetSelectedHwnd() == 0) - HwndSelector::UpdateMainHwnd(false); + HwndSelector::UpdateMainHwnd(false); HwndSelector::UpdateWindowBounds(); } diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.h b/src/ProtoInput/ProtoInputHooks/RawInput.h index 7a9af34..3d80ab7 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.h +++ b/src/ProtoInput/ProtoInputHooks/RawInput.h @@ -44,6 +44,8 @@ class RawInput static void ProcessKeyboardInput(const RAWKEYBOARD& data, HANDLE deviceHandle); public: + static void SendInputMessages(const RAWMOUSE& data); + static void SendKeyMessage(const RAWKEYBOARD& data, bool pressed); static RawInputState rawInputState; static HWND rawInputHwnd; static bool forwardRawInput; diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp index bb99821..2e6fc8a 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -3,6 +3,7 @@ #include #include "Gui.h" #include +#include //#include "OpenXinputWrapper.h" #include "TranslateXtoMKB.h" #include "RawInput.h" @@ -23,9 +24,14 @@ #include #include #include "HwndSelector.h" +#include "FakeCursor.h" +#include "GtoMnK_RawInput.h" +#include "FakeMouseKeyboard.h" //#include "RawInput.h" //#include #pragma comment(lib, "dwmapi.lib") +#include + //#include "dllmain.h" //#include "PostKeyFunction.cpp" @@ -34,3417 +40,293 @@ namespace ScreenshotInput { - - std::vector staticPointA; - std::vector staticPointB; - std::vector staticPointX; - std::vector staticPointY; - - int scanAtype = 0; - int scanBtype = 0; - int scanXtype = 0; - int scanYtype = 0; - bool showcursorcounter = true; + int updatewindowtick = 300; + int mode = 1; int AxisLeftsens; int AxisRightsens; int AxisUpsens; int AxisDownsens; int scrollspeed3; + float radial_deadzone = 0.10f; // Circular/Radial Deadzone (0.0 to 0.3) + float axial_deadzone = 0.00f; // Square/Axial Deadzone (0.0 to 0.3) + const float max_threshold = 0.03f; // Max Input Threshold, an "outer deadzone" (0.0 to 0.15) + const float curve_slope = 0.16f; // The linear portion of the response curve (0.0 to 1.0) + const float curve_exponent = 5.00f; // The exponential portion of the curve (1.0 to 10.0) + float sensitivity = 12.00f; // Base sensitivity / max speed (1.0 to 30.0) + float accel_multiplier = 1.90f; // Look Acceleration Multiplier (1.0 to 3.0) + struct KeyMapEntry { + WORD makeCode; + WORD vKey; + }; + static const std::unordered_map keyMap = { + { 1, { 0x11, 0x57 } }, // W + { 2, { 0x1C, VK_RETURN } }, // Enter + { 3, { 0x4B, VK_LEFT } }, // Left Arrow + { 4, { 0x01, VK_ESCAPE } }, // Escape + { 5, { 0x1E, 0x57 } }, // A + { 6, { 0x1F, 0x57 } }, // S + { 7, { 0x20, 0x57 } }, // D + { 8, { 0x4D, VK_RIGHT } }, // Right Arrow + { 9, { 0x48, VK_UP } }, // Up Arrow + { 10, { 0x50, VK_DOWN } }, // Down Arrow + { 11, { 0x39, VK_SPACE } }, // Space + { 12, { 0x0E, VK_BACK } }, // Backspace + { 13, { 0x0F, VK_TAB } }, // Tab + { 14, { 0x2A, VK_LSHIFT } }, // Left Shift + { 15, { 0x1D, VK_LCONTROL} }, // Left Ctrl + { 16, { 0x38, VK_LMENU } }, // Left Alt + { 17, { 0x13, 0x52} }, // R - int InitialMode; - int Modechange; - int sendfocus; - int responsetime; - int doubleclicks; - int scrollenddelay; - int quickMW; - bool inithere = false; - int ShoulderNextbmp; - - int scrolloutsidewindow; - int mode = InitialMode; + }; + int Atype = 1; + int Btype = 2; + int Xtype = 17; + int Ytype = 11; + int Ctype = 2; + int Dtype = 4; + // int Etype = 7; + /// int Ftype = 8; + int uptype = 9; + int downtype = 10; + int Lefttype = 3; + int righttype = 8; ///////////////// bool movedmouse; - - HOOK_TRACE_INFO GETcursorpos = { NULL }; - HOOK_TRACE_INFO SETcursorpos = { NULL }; - HOOK_TRACE_INFO GETkeyboardstate = { NULL }; - HOOK_TRACE_INFO GETasynckeystate = { NULL }; - HOOK_TRACE_INFO GETkeystate = { NULL }; - HOOK_TRACE_INFO CLIPcursor = { NULL }; - HOOK_TRACE_INFO SETcursor = { NULL }; - HOOK_TRACE_INFO g_HookShowCursorHandle = { NULL }; - HOOK_TRACE_INFO GETcursorinfo = { NULL }; - - HOOK_TRACE_INFO SETrect = { NULL }; - HOOK_TRACE_INFO ADJUSTwindowrect = { NULL }; - - HOOK_TRACE_INFO GETrawinputdata = { NULL }; - HOOK_TRACE_INFO REGISTERrawinputdevices = { NULL }; - - HOOK_TRACE_INFO GETmessagea = { NULL }; - HOOK_TRACE_INFO GETmessagew = { NULL }; - HOOK_TRACE_INFO PEEKmessagea = { NULL }; - HOOK_TRACE_INFO PEEKmessagew = { NULL }; + bool leftPressedold = false; + bool rightPressedold = false; HMODULE g_hModule = nullptr; - bool rawmouseL = false; - bool rawmouseR = false;//0:scroll 1:left 2:right 3:up 4:down - std::vector keyState(256, 0); + CRITICAL_SECTION critical; //window thread - POINT fakecursorW; - POINT startdrag; - POINT activatewindow; - POINT scroll; bool loop = true; - HWND hwnd; int showmessage = 0; //0 = no message, 1 = initializing, 2 = bmp mode, 3 = bmp and cursor mode, 4 = edit mode - int showmessageW = 0; //0 = no message, 1 = initializing, 2 = bmp mode, 3 = bmp and cursor mode, 4 = edit mode int counter = 0; - bool scanrunning = false; - bool keys[256] = { false }; + //syncronization control HANDLE hMutex; - int getmouseonkey = 0; - int message = 0; - auto hInstance = nullptr; - POINT delta; //hooks - bool hooksenabled = false; - bool hooksinited = false; - int keystatesend = 0; //key to send - int TranslateXtoMKB::clipcursorhook = 0; - int TranslateXtoMKB::getkeystatehook = 0; - int TranslateXtoMKB::getasynckeystatehook = 0; - int TranslateXtoMKB::getcursorposhook = 0; - int TranslateXtoMKB::setcursorposhook = 0; - int TranslateXtoMKB::setcursorhook = 0; - int TranslateXtoMKB::rawinputhook = 0; - int TranslateXtoMKB::GetKeyboardStateHook = 0; - bool TranslateXtoMKB::registerrawinputhook = 0; - int TranslateXtoMKB::showcursorhook = 0; - bool nodrawcursor = false; - - int ignorerect = 0; - POINT rectignore = { 0,0 }; //for getcursorposhook - int setrecthook = 0; - - int leftrect = 0; - int toprect = 0; - int rightrect = 0; - int bottomrect = 0; - - int resize = 1; - int numphotoA = -1; - int numphotoB = -1; - int numphotoX = -1; - int numphotoY = -1; - int numphotoC = -1; - int numphotoD = -1; - int numphotoE = -1; - int numphotoF = -1; - - int numphotoAbmps; - int numphotoBbmps; - int numphotoXbmps; - int numphotoYbmps; - - bool AuseStatic = 1; - bool BuseStatic = 1; - bool XuseStatic = 1; - bool YuseStatic = 1; + //fake cursor int TranslateXtoMKB::controllerID; - int Xf = 100; - int Yf = 100; - int OldX = 0; - int OldY = 0; - int ydrag; - int xdrag; - int Xoffset = 0; //offset for cursor - int Yoffset = 0; - bool scrollmap = false; - bool pausedraw = false; - bool gotcursoryet = false; - int TranslateXtoMKB::drawfakecursor; - int alwaysdrawcursor = 0; //always draw cursor even if setcursor set cursor NULL - HICON hCursor = 0; - DWORD lastClickTime; - HDC PointerWnd; - int WoldX, WoldY; - - //bmp search - bool foundit = false; - int hooksoninit = 0; - - int cursoroffsetx, cursoroffsety; - int offsetSET; //0:sizing 1:offset 2:done - int cursorWidth = 40; - int cursorHeight = 40; - HWND ScreenshotInput::TranslateXtoMKB::pointerWindows = nullptr; - bool DrawFakeCursorFix = false; - static int transparencyKey = RGB(0, 0, 1); - - //setwindowpos - int posX; - int posY; - int resX; - int resY; - HCURSOR oldhCursor = NULL; - HCURSOR hCursorW = NULL; - bool nochange = false; - - bool oldHadShowCursor = true; - - const extern WPARAM ScreenshotInput_MOUSE_SIGNATURE = 0x10000000; - const extern LPARAM ScreenshotInput_KEYBOARD_SIGNATURE = 0x10000000; - bool g_filterRawInput = false; - bool g_filterMouseMove = false; - bool g_filterMouseActivate = false; - bool g_filterWindowActivate = false; - bool g_filterWindowActivateApp = false; - bool g_filterMouseWheel = false; - bool g_filterMouseButton = true; - bool g_filterKeyboardButton = false; - - POINT oldposcheck; - POINT oldrescheck; - - //scroll type 3 + bool TranslateXtoMKB::rawinputhook; //registerrawinputhook + bool TranslateXtoMKB::registerrawinputhook; //registerrawinputhook + int Xf = 0; + int Yf = 0; + + int tick = 0; - bool doscrollyes = false; - - bool onoroff = true; - - //remember old keystates - int oldscrollrightaxis = false; //reset - int oldscrollleftaxis = false; //reset - int oldscrollupaxis = false; //reset - int oldscrolldownaxis = false; //reset - bool Apressed = false; - bool Bpressed = false; - bool Xpressed = false; - bool Ypressed = false; - bool leftPressedold; - bool rightPressedold; - bool oldA = false; - bool oldB = false; - bool oldX = false; - bool oldY = false; + + bool rawmouseWu = false; + bool rawmouseWd = false; + int righthanded = 0; + bool oldA = false; + bool oldB = false; + bool oldX = false; + bool oldY = false; + bool oldC = false; bool oldD = false; bool oldE = false; bool oldF = false; - bool oldup = false; + bool olddown = false; + bool oldup = false; bool oldleft = false; bool oldright = false; - float radial_deadzone = 0.10f; // Circular/Radial Deadzone (0.0 to 0.3) - float axial_deadzone = 0.00f; // Square/Axial Deadzone (0.0 to 0.3) - const float max_threshold = 0.03f; // Max Input Threshold, an "outer deadzone" (0.0 to 0.15) - const float curve_slope = 0.16f; // The linear portion of the response curve (0.0 to 1.0) - const float curve_exponent = 5.00f; // The exponential portion of the curve (1.0 to 10.0) - float sensitivity = 12.00f; // Base sensitivity / max speed (1.0 to 30.0) - float accel_multiplier = 1.90f; // Look Acceleration Multiplier (1.0 to 3.0) - - bool musLB = false; - bool musRB = false; - bool rawmouseWu = false; - bool rawmouseWd = false; - - int startsearch = 0; - int startsearchA = 0; - int startsearchB = 0; - int startsearchX = 0; - int startsearchY = 0; - int startsearchC = 0; - int startsearchD = 0; - int startsearchE = 0; - int startsearchF = 0; - int skipintro = 0; - int righthanded = 0; - int scanoption = 0; - - int Atype = 0; - int Btype = 0; - int Xtype = 0; - int Ytype = 0; - int Ctype = 0; - int Dtype = 0; - int Etype = 0; - int Ftype = 0; - - POINT PointA; - POINT PointB; - POINT PointX; - POINT PointY; - - int scantick = 0; - int findwindowdelay = 0; - int bmpAtype = 0; - int bmpBtype = 0; - int bmpXtype = 0; - int bmpYtype = 0; - int bmpCtype = 0; - int bmpDtype = 0; - int bmpEtype = 0; - int bmpFtype = 0; - - int uptype = 0; - int downtype = 0; - int lefttype = 0; - int righttype = 0; - - - int x = 0; - - HBITMAP hbm; - - std::vector largePixels, smallPixels; - SIZE screenSize; - int strideLarge, strideSmall; - int smallW, smallH; - - //int sovetid = 16; - int knappsovetid = 100; - - int samekey = 0; - int samekeyA = 0; - INT WINAPI HookedShowCursor(BOOL bShow) - { //not called? - if (bShow) - { - showcursorcounter = true; - } - else - { - showcursorcounter = false; - } - return ShowCursor(bShow); - } - - HCURSOR WINAPI HookedSetCursor(HCURSOR hcursor) { - EnterCriticalSection(&critical); - hCursor = hcursor; // Store the cursor handle - - hcursor = SetCursor(hcursor); - LeaveCriticalSection(&critical); - return hcursor; - } - ////SetRect_t)(LPRECT lprc, int xLeft, int yTop, int xRight, int yBottom); - BOOL WINAPI HookedSetRect(LPRECT lprc, int xLeft, int yTop, int xRight, int yBottom) { - xLeft = leftrect; // Set the left coordinate to Xrect - yTop = toprect; // Set the top coordinate to Yrect - - xRight = rightrect; // Set the right coordinate to Xrect + 10 - yBottom = bottomrect; // Set the bottom coordinate to Yrect + 10 - - - bool result = SetRect(lprc, xLeft, yTop, xRight, yBottom); - return result; - } - - BOOL WINAPI HookedAdjustWindowRect(LPRECT lprc, DWORD dwStyle, BOOL bMenu) { - lprc->top = toprect; // Set the left coordinate to Xrect - lprc->bottom = bottomrect; // Set the left coordinate to Xrect - lprc->left = leftrect; // Set the left coordinate to Xrect - lprc->right = rightrect; // Set the left coordinate to Xrect - - bool result = AdjustWindowRect(lprc, dwStyle, bMenu); - return result; - } - - SHORT WINAPI HookedGetAsyncKeyState(int vKey) - { - if (keys[vKey] == true) { - return 0x8000; // key is down - } - else { - return 0x0000; // key is up - } - } - - HWND g_rawInputHwnd = nullptr; - - const int RAWINPUT_BUFFER_SIZE = 20; - RAWINPUT g_inputBuffer[RAWINPUT_BUFFER_SIZE]{}; - //std::vector g_forwardingWindows{}; - // Global/static counter - struct FakeKey { - USHORT vkey; - bool press; - }; - - static std::vector g_fakeKeys; - // Add a fake key event to the array - void GenerateRawKey(USHORT vk, bool press) { - g_fakeKeys.push_back({ vk, press }); - if (vk < 256) { - if (press) { - keys[vk] = true; // mark as "down" - } - else { - keys[vk] = false; // clear "down" bit - } - } - } - - BOOL WINAPI HookedGetKeyboardState(PBYTE lpKeyState) { - if (!lpKeyState) { - return FALSE; - } - - // Call the original function to get real states //disabled cause of testing - // BOOL result = fpGetKeyboardState(lpKeyState); - memset(lpKeyState, 0, 256); - // Overlay fake states - for (int vk = 0; vk < 256; ++vk) { - if (keys[vk] == true) { - lpKeyState[vk] |= 0x80; // force down - } - else { //not needed if fpGetKeyboardState - lpKeyState[vk] &= ~0x80; // force up - } - } - - return TRUE; - } - - - UINT WINAPI HookedGetRawInputData( - HRAWINPUT hRawInput, - UINT uiCommand, - LPVOID pData, - PUINT pcbSize, - UINT cbSizeHeader - ) { - // Call the original function - UINT result = GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader); - - if (uiCommand == RID_INPUT && pData != nullptr) { - RAWINPUT* raw = (RAWINPUT*)pData; - // raw->header.wParam = RIM_INPUT; // Ensure wParam indicates input - if (raw->header.dwType == RIM_TYPEMOUSE && raw->header.wParam == RIM_INPUT) { - - // if (delta.x !=0) - raw->data.mouse.lLastX =delta.x; - // if (delta.y != 0) - raw->data.mouse.lLastY =delta.y; - - if (rawmouseR == true || rawmouseL == true || rawmouseWd == true || rawmouseWu == true) - raw->data.mouse.usButtonFlags = 0; - - if (rawmouseR == true) - raw->data.mouse.usButtonFlags |= RI_MOUSE_RIGHT_BUTTON_DOWN; - else - raw->data.mouse.usButtonFlags |= RI_MOUSE_RIGHT_BUTTON_UP; - - if (rawmouseL == true) - raw->data.mouse.usButtonFlags |= RI_MOUSE_LEFT_BUTTON_DOWN; - else - raw->data.mouse.usButtonFlags |= RI_MOUSE_LEFT_BUTTON_UP; - - - - if (rawmouseWd == true) - { - raw->data.mouse.usButtonFlags |= RI_MOUSE_WHEEL; - raw->data.mouse.usButtonData = -120; - } - else if (rawmouseWu == true) - { - raw->data.mouse.usButtonFlags |= RI_MOUSE_WHEEL; - raw->data.mouse.usButtonData = 120; - } - - } - if (raw->header.dwType == RIM_TYPEKEYBOARD && !g_fakeKeys.empty()) { - // Take the first fake key from the array - FakeKey fk = g_fakeKeys.front(); - g_fakeKeys.erase(g_fakeKeys.begin()); - - raw->data.keyboard.VKey = fk.vkey; - raw->data.keyboard.MakeCode = MapVirtualKey(fk.vkey, MAPVK_VK_TO_VSC); - raw->data.keyboard.Flags = fk.press ? RI_KEY_MAKE : RI_KEY_BREAK; - raw->data.keyboard.Message = fk.press ? WM_KEYDOWN : WM_KEYUP; - } - - } - - return result; - } - - void ForceRawInputPoll() //global all processes - { - INPUT input = { 0 }; - input.type = INPUT_MOUSE; - input.mi.dx = 0; - input.mi.dy = 0; - input.mi.dwFlags = MOUSEEVENTF_MOVE; // relative move - SendInput(1, &input, sizeof(INPUT)); - input.type = INPUT_KEYBOARD; - input.ki.wVk = VK_OEM_PERIOD; - input.ki.dwFlags = KEYEVENTF_KEYUP; - SendInput(1, &input, sizeof(INPUT)); - } - // Hooked GetKeyState - SHORT WINAPI HookedGetKeyState(int nVirtKey) { - if (keys[nVirtKey] == true) { - return 0x8000; // key is down - } - else { - return 0x0000; // key is up - } - } - - BOOL WINAPI MyGetCursorPos(PPOINT lpPoint) { - if (lpPoint) - { - POINT mpos; - mpos.y = Yf; - mpos.x = Xf; - - if (scrollmap == false) - { - - if (ignorerect == 1) { - mpos.x = Xf + rectignore.x; //hwnd coordinates 0-800 on a 800x600 window - mpos.y = Yf + rectignore.y;//hwnd coordinate s0-600 on a 800x600 window - lpPoint->x = mpos.x; - lpPoint->y = mpos.y; - } - else { - if (hwnd) - { - ClientToScreen(hwnd, &mpos); - } - lpPoint->x = mpos.x; - lpPoint->y = mpos.y; - } - } - - else - { - mpos.x = scroll.x; - mpos.y = scroll.y; - if (hwnd) - { - ClientToScreen(hwnd, &mpos); - } - - lpPoint->x = mpos.x; - lpPoint->y = mpos.y; - } - return TRUE; - } - return FALSE; - } - POINT mpos; - BOOL WINAPI MySetCursorPos(int X, int Y) { - if (hwnd) - { - POINT point; - point.x = X; - point.y = Y; - ScreenToClient(hwnd, &point); - Xf = point.x; - Yf = point.y; - } - return TRUE; //fpSetCursorPos(lpPoint); // Call the original SetCursorPos function - } - BOOL WINAPI HookedClipCursor(const RECT* lpRect) { - return true; //nonzero bool or int - //return originalClipCursor(nullptr); - - } - POINT windowpos(HWND window, int ignorerect, bool getpos) //return pos if true - { - if (ignorerect == 0) - { - POINT pos = { 0,0 }; - RECT recte; - GetClientRect(window, &recte); - if (getpos) { - pos.x = recte.left; - pos.y = recte.top; - ClientToScreen(window, &pos); - } - else { - pos.x = recte.right; //- recte.left; - pos.y = recte.bottom; //- recte.top; - } - return pos; - } - else - { - POINT pos = { 0,0 }; - RECT frameBounds; - HRESULT hr = DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frameBounds, sizeof(frameBounds)); - if (SUCCEEDED(hr)) - { - if (getpos) - { - pos.x = frameBounds.left; - pos.y = frameBounds.top; - } - else - { - pos.x = frameBounds.right - frameBounds.left; - pos.y = frameBounds.bottom - frameBounds.top; - } - } - return pos; - } - } - POINT GetStaticFactor(POINT pp, int doscale, bool isnotbmp) - { - // FLOAT ny; - POINT currentres = windowpos(hwnd, ignorerect, false); - FLOAT currentwidth = static_cast(currentres.x); - FLOAT currentheight = static_cast(currentres.y); - if (doscale == 1) - { - float scalex = currentwidth / 1024.0f; - float scaley = currentheight / 768.0f; - - pp.x = static_cast(std::lround(pp.x * scalex)); - pp.y = static_cast(std::lround(pp.y * scaley)); - } - if (doscale == 2) //4:3 blackbar only x - { - float difference = 0.0f; - float newwidth = currentwidth; - float curraspect = currentheight / currentwidth; - if (curraspect < 0.75f) - { - newwidth = currentheight / 0.75f; - if (isnotbmp) //cant pluss blackbars on bmps - difference = (currentwidth - newwidth) / 2; - } - float scalex = newwidth / 1024.0f; - float scaley = currentheight / 768.0f; - pp.x = static_cast(std::lround(pp.x * scalex) + difference); - pp.y = static_cast(std::lround(pp.y * scaley)); - } - if (doscale == 3) //only vertical stretch equal - { - float difference = 0.0f; - float newwidth = currentwidth; - float curraspect = currentheight / currentwidth; - if (curraspect < 0.5625f) - { - newwidth = currentheight / 0.5625f; - if (isnotbmp) //cant pluss blackbars on bmps - difference = (currentwidth - newwidth) / 2; - } - float scalex = newwidth / 1337.0f; - float scaley = currentheight / 768.0f; - pp.x = static_cast(std::lround(pp.x * scalex) + difference); - pp.y = static_cast(std::lround(pp.y * scaley)); - } - return pp; - } - bool Mutexlock(bool lock) { - // Create a named mutex - if (lock == true) - { - hMutex = CreateMutexA( - NULL, // Default security - FALSE, // Initially not owned - "Global\\PuttingInputByMessenils" // Name of mutex - ); - if (hMutex == NULL) { - std::cerr << "CreateMutex failed: " << GetLastError() << std::endl; - MessageBoxA(NULL, "Error!", "Failed to create mutex", MB_OK | MB_ICONINFORMATION); - return false; - } - // Check if mutex already exists - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - Sleep(5); - ReleaseMutex(hMutex); - CloseHandle(hMutex); - Mutexlock(true); //is this okay? - - } - } - if (lock == false) - { - ReleaseMutex(hMutex); - - CloseHandle(hMutex); - // hMutex = nullptr; // Optional: Prevent dangling pointer - - } - return true; - } - BOOL WINAPI HookedRegisterRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize) - { - // Modify all devices in the array - // MessageBoxA(NULL, "RegisterRawInputDevices Hooked!", "Info", MB_OK | MB_ICONINFORMATION); - for (UINT i = 0; i < uiNumDevices; ++i) { - pRawInputDevices[i].dwFlags |= RIDEV_INPUTSINK; - } - BOOL result = RegisterRawInputDevices(pRawInputDevices, uiNumDevices, cbSize); - // if (pRawInputDevices[0].hwndTarget != NULL) //if null follow keyboard focus - // hwnd = pRawInputDevices[0].hwndTarget; - // if (result == FALSE) - // { - // MessageBoxA(NULL, "RegisterRawInputDevices failed!", "Error", MB_OK | MB_ICONERROR); - //} - return result; - } - void EnableHooks() - { - if (TranslateXtoMKB::getcursorposhook == 1 || TranslateXtoMKB::getcursorposhook == 2) { - ULONG ACLEntries[1] = { 0 }; - LhSetExclusiveACL(ACLEntries, 1, &GETcursorpos); - } - if (TranslateXtoMKB::setcursorposhook == 1) { - ULONG ACLEntries[1] = { 0 }; - LhSetExclusiveACL(ACLEntries, 1, &SETcursorpos); - } - if (TranslateXtoMKB::getkeystatehook == 1) { - ULONG ACLEntries[1] = { 0 }; - LhSetExclusiveACL(ACLEntries, 1, &GETkeystate); - } - if (TranslateXtoMKB::getasynckeystatehook == 1) { - ULONG ACLEntries[1] = { 0 }; LhSetExclusiveACL(ACLEntries, 1, &GETasynckeystate); - } - if (TranslateXtoMKB::clipcursorhook == 1) { - ULONG ACLEntries[1] = { 0 }; LhSetExclusiveACL(ACLEntries, 1, &CLIPcursor); - } - if (setrecthook == 1) { - ULONG ACLEntries[1] = { 0 }; - LhSetExclusiveACL(ACLEntries, 1, &SETrect); - LhSetExclusiveACL(ACLEntries, 1, &ADJUSTwindowrect); - } - if (TranslateXtoMKB::setcursorhook == 1) - { - ULONG ACLEntries[1] = { 0 }; - LhSetExclusiveACL(ACLEntries, 1, &SETcursor); - } - if (TranslateXtoMKB::rawinputhook == 1 || TranslateXtoMKB::rawinputhook == 2) - { - ULONG ACLEntries[1] = { 0 }; - LhSetExclusiveACL(ACLEntries, 1, &GETrawinputdata); - } - if (TranslateXtoMKB::GetKeyboardStateHook == 1) - { - ULONG ACLEntries[1] = { 0 }; - LhSetExclusiveACL(ACLEntries, 1, &GETkeyboardstate); - } - // if (registerrawinputhook) - // { - // ULONG ACLEntries[1] = { 0 }; - // LhSetExclusiveACL(ACLEntries, 1, ®ISTERrawinputdevices); - // } - if (g_filterRawInput || g_filterMouseMove || g_filterMouseActivate || g_filterWindowActivate - || g_filterWindowActivateApp || g_filterMouseWheel || g_filterMouseButton || g_filterKeyboardButton) // If one of them is enabled - { - ULONG ACLEntries[1] = { 0 }; - LhSetExclusiveACL(ACLEntries, 1, &GETmessagea); - LhSetExclusiveACL(ACLEntries, 1, &GETmessagew); - LhSetExclusiveACL(ACLEntries, 1, &PEEKmessagea); - LhSetExclusiveACL(ACLEntries, 1, &PEEKmessagew); - } - if (TranslateXtoMKB::showcursorhook == 1) - { - ULONG ACLEntries[1] = { 0 }; - LhSetExclusiveACL(ACLEntries, 1, &g_HookShowCursorHandle); - } - hooksenabled = true; - } - void DisableHooks() - { - ULONG ACLEntries[1] = { 0 }; - LhSetGlobalExclusiveACL(ACLEntries, 0); - hooksenabled = false; - return; - } - - void SetupHook() - { - - // Log() << "Loading " << path; - HMODULE hUser32 = GetModuleHandleA("user32"); - if (!hUser32) { - MessageBoxA(NULL, "FATAL: Could not get a handle to user32.dll! Hooks will not be installed.", "error", MB_OK); - return; - } - NTSTATUS result; - if (TranslateXtoMKB::getcursorposhook == 1 || TranslateXtoMKB::getcursorposhook == 2) { - result = LhInstallHook(GetProcAddress(hUser32, "GetCursorPos"), MyGetCursorPos, NULL, &GETcursorpos); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetCursorPos hook", "Error", MB_OK | MB_ICONERROR); - } - if (TranslateXtoMKB::setcursorposhook == 1) { - result = LhInstallHook(GetProcAddress(hUser32, "SetCursorPos"), MySetCursorPos, NULL, &SETcursorpos); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install SetCursorPos hook", "Error", MB_OK | MB_ICONERROR); - } - if (TranslateXtoMKB::getkeystatehook == 1) { - result = LhInstallHook(GetProcAddress(hUser32, "GetKeyState"), HookedGetKeyState, NULL, &GETkeystate); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetKeyState hook", "Error", MB_OK | MB_ICONERROR); - } - if (TranslateXtoMKB::getasynckeystatehook == 1) { - result = LhInstallHook(GetProcAddress(hUser32, "GetAsyncKeyState"), HookedGetAsyncKeyState, NULL, &GETasynckeystate); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetAsyncKeyState hook", "Error", MB_OK | MB_ICONERROR); - } - if (TranslateXtoMKB::clipcursorhook == 1) { - result = LhInstallHook(GetProcAddress(hUser32, "ClipCursor"), HookedClipCursor, NULL, &CLIPcursor); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install ClipCursor hook", "Error", MB_OK | MB_ICONERROR); - } - if (setrecthook == 1) { - result = LhInstallHook(GetProcAddress(hUser32, "SetRect"), HookedSetRect, NULL, &SETrect); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install SetRect hook", "Error", MB_OK | MB_ICONERROR); - result = LhInstallHook(GetProcAddress(hUser32, "AdjustWindowRect"), HookedAdjustWindowRect, NULL, &ADJUSTwindowrect); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install AdjustWindowRect hook", "Error", MB_OK | MB_ICONERROR); - } - if (TranslateXtoMKB::setcursorhook == 1) - { - result = LhInstallHook(GetProcAddress(hUser32, "SetCursor"), HookedSetCursor, NULL, &SETcursor); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install SetCursor hook", "Error", MB_OK | MB_ICONERROR); - } - if (TranslateXtoMKB::rawinputhook == 1 || TranslateXtoMKB::rawinputhook == 2) - { - result = LhInstallHook(GetProcAddress(hUser32, "GetRawInputData"), HookedGetRawInputData, NULL, &GETrawinputdata); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetRawInputData hook", "Error", MB_OK | MB_ICONERROR); - } - if (TranslateXtoMKB::GetKeyboardStateHook == 1) - { - result = LhInstallHook(GetProcAddress(hUser32, "GetKeyboardState"), HookedGetKeyboardState, NULL, &GETkeyboardstate); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetKeyboardState hook", "Error", MB_OK | MB_ICONERROR); - } - - // if (registerrawinputhook) - // { - // result = LhInstallHook(GetProcAddress(hUser32, "RegisterRawInputDevices"), HookedRegisterRawInputDevices, NULL, ®ISTERrawinputdevices); - // if (FAILED(result)) MessageBoxA(NULL, "Failed to install RegisterRawInputDevices hook", "Error", MB_OK | MB_ICONERROR); - // } - if (g_filterRawInput || g_filterMouseMove || g_filterMouseActivate || g_filterWindowActivate - || g_filterWindowActivateApp || g_filterMouseWheel || g_filterMouseButton || g_filterKeyboardButton) // If one of them is enabled - { - // result = LhInstallHook(GetProcAddress(hUser32, "GetMessageA"), ScreenshotInput::MessageFilterHook::Hook_GetMessageA, NULL, &GETmessagea); - // if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetMessageA hook", "Error", MB_OK | MB_ICONERROR); - // result = LhInstallHook(GetProcAddress(hUser32, "GetMessageW"), ScreenshotInput::MessageFilterHook::Hook_GetMessageW, NULL, &GETmessagew); - // if (FAILED(result)) MessageBoxA(NULL, "Failed to install GetMessageW hook", "Error", MB_OK | MB_ICONERROR); - // result = LhInstallHook(GetProcAddress(hUser32, "PeekMessageA"), ScreenshotInput::MessageFilterHook::Hook_PeekMessageA, NULL, &PEEKmessagea); - // if (FAILED(result)) MessageBoxA(NULL, "Failed to install PeekMessageA hook", "Error", MB_OK | MB_ICONERROR); - // result = LhInstallHook(GetProcAddress(hUser32, "PeekMessageW"), ScreenshotInput::MessageFilterHook::Hook_PeekMessageW, NULL, &PEEKmessagew); - // if (FAILED(result)) MessageBoxA(NULL, "Failed to install PeekMessageW hook", "Error", MB_OK | MB_ICONERROR); - } - if (TranslateXtoMKB::showcursorhook == 1) - { - result = LhInstallHook(GetProcAddress(hUser32, "ShowCursor"), HookedShowCursor, NULL, &g_HookShowCursorHandle); - if (FAILED(result)) MessageBoxA(NULL, "Failed to install ShowCursor hook", "Error", MB_OK | MB_ICONERROR); - } - hooksinited = true; - //MH_EnableHook(MH_ALL_HOOKS); - return; - } - - - void vibrateController(int controllerId, WORD strength) - { - XINPUT_VIBRATION vibration = {}; - vibration.wLeftMotorSpeed = strength; // range: 0 - 65535 - vibration.wRightMotorSpeed = strength; - - // Activate vibration - OpenXInputSetState(controllerId, &vibration); - - // Keep vibration on for 1 second - Sleep(50); // milliseconds - - // Stop vibration - vibration.wLeftMotorSpeed = 0; - vibration.wRightMotorSpeed = 0; - OpenXInputSetState(controllerId, &vibration); - } - - bool SendMouseClick(int x, int y, int z, int many) { + bool SendMouseClick(int x, int y, int z) { // Create a named mutex - + RAWMOUSE muusjn = { 0 }; POINT heer; + muusjn.usButtonFlags = 0; - unsigned int sig = ScreenshotInput_MOUSE_SIGNATURE; - - heer.x = x; - heer.y = y; - if (TranslateXtoMKB::getcursorposhook == 2) - ClientToScreen(hwnd, &heer); - - LPARAM clickPos = MAKELPARAM(heer.x, heer.y); - if (z == 1) { - - unsigned int wParamDown = VK_LBUTTON | sig; // Add signature - unsigned int wParamUp = 0 | sig; // Add signature - - PostMessage(hwnd, WM_LBUTTONDOWN, wParamDown, clickPos); - PostMessage(hwnd, WM_LBUTTONUP, wParamUp, clickPos); - keystatesend = VK_LEFT; - } - if (z == 2) { - - unsigned int wParamDown = VK_RBUTTON | sig; - unsigned int wParamUp = 0 | sig; - - PostMessage(hwnd, WM_RBUTTONDOWN, wParamDown, clickPos); - PostMessage(hwnd, WM_RBUTTONUP, wParamUp, clickPos); - } - if (z == 3) { - unsigned int wParamDown = VK_LBUTTON | sig; - - unsigned int mouseMkFlags = VK_LBUTTON | sig; - PostMessage(hwnd, WM_LBUTTONDOWN, mouseMkFlags, clickPos); - keystatesend = VK_LEFT; - musLB = true; - } - if (z == 4) - { - unsigned int wParamUp = 0 | sig; - PostMessage(hwnd, WM_LBUTTONUP, wParamUp, clickPos); - musLB = false; - - } - if (z == 5) { - unsigned int wParamDown = VK_RBUTTON | sig; - - PostMessage(hwnd, WM_RBUTTONDOWN, wParamDown, clickPos); - keystatesend = VK_RIGHT; - musRB = true; - } - if (z == 6) - { - unsigned int wParamUp = 0 | sig; - PostMessage(hwnd, WM_RBUTTONUP, wParamUp, clickPos); - musRB = false; - - } - if (z == 20 || z == 21) //WM_mousewheel need desktop coordinates - { - - ClientToScreen(hwnd, &heer); - LPARAM clickPos = MAKELPARAM(heer.x, heer.y); - WPARAM wParam = 0; - if (z == 20) { - wParam = MAKEWPARAM(0, -120); - rawmouseWd = true; - } - if (z == 21) { - wParam = MAKEWPARAM(0, 120); - rawmouseWu = true; - } - wParam |= sig; // - PostMessage(hwnd, WM_MOUSEWHEEL, wParam, clickPos); - } - if (z == 30) //WM_LBUTTONDBLCLK - { - unsigned int wParam = 0 | sig; - PostMessage(hwnd, WM_LBUTTONDBLCLK, wParam, clickPos); - } - else if (z == 8 || z == 10 || z == 11) //only mousemove - { - unsigned int wParam = 0 | sig; - PostMessage(hwnd, WM_MOUSEMOVE, wParam, clickPos); - //PostMessage(hwnd, WM_SETCURSOR, (WPARAM)hwnd, MAKELPARAM(HTCLIENT, WM_MOUSEMOVE)); - - } - return true; - } - - std::string UGetExecutableFolder() { - char path[MAX_PATH]; - GetModuleFileNameA(NULL, path, MAX_PATH); - - std::string exePath(path); - - size_t lastSlash = exePath.find_last_of("\\/"); - return exePath.substr(0, lastSlash); - } - - - std::wstring WGetExecutableFolder() { - wchar_t path[MAX_PATH]; - GetModuleFileNameW(NULL, path, MAX_PATH); - std::wstring exePath(path); - size_t lastSlash = exePath.find_last_of(L"\\/"); - - if (lastSlash == std::wstring::npos) - return L""; - return exePath.substr(0, lastSlash); - } - - bool FindSubImage24( - const BYTE* largeData, int largeW, int largeH, int strideLarge, - const BYTE* smallData, int smallW, int smallH, int strideSmall, - POINT& foundAt, int Xstart, int Ystart - ) { - for (int y = Ystart; y <= largeH - smallH; ++y) { - for (int x = Xstart; x <= largeW - smallW; ++x) { - bool match = true; - for (int j = 0; j < smallH && match; ++j) { - const BYTE* pLarge = largeData + (y + j) * strideLarge + x * 3; - const BYTE* pSmall = smallData + j * strideSmall; - if (memcmp(pLarge, pSmall, smallW * 3) != 0) { - match = false; - } - } - if (match) { - foundAt.x = x; - foundAt.y = y; - return true; - } - } - } - return false; - } - - int CalculateStride(int width) { - return ((width * 3 + 3) & ~3); - } - - - bool Save24BitBMP(std::wstring filename, const BYTE* pixels, int width, int height) { //for testing purposes - int stride = ((width * 3 + 3) & ~3); - int imageSize = stride * height; - - BITMAPFILEHEADER bfh = {}; - bfh.bfType = 0x4D42; // "BM" - bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - bfh.bfSize = bfh.bfOffBits + imageSize; - - BITMAPINFOHEADER bih = {}; - bih.biSize = sizeof(BITMAPINFOHEADER); - bih.biWidth = width; - bih.biHeight = -height; // bottom-up BMP (positive height) - bih.biPlanes = 1; - bih.biBitCount = 24; - bih.biCompression = BI_RGB; - bih.biSizeImage = imageSize; - - HANDLE hFile = CreateFileW(filename.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) return false; - - DWORD written; - WriteFile(hFile, &bfh, sizeof(bfh), &written, NULL); - WriteFile(hFile, &bih, sizeof(bih), &written, NULL); - WriteFile(hFile, pixels, imageSize, &written, NULL); - CloseHandle(hFile); - - return true; - } - - bool IsTriggerPressed(BYTE triggerValue) { - BYTE threshold = 175; - return triggerValue > threshold; - } - bool LoadBMP24Bit(std::wstring filename, std::vector& pixels, int& width, int& height, int& stride) { - HBITMAP hbm = (HBITMAP)LoadImageW(NULL, filename.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION); - if (!hbm) return false; - - //BITMAP scaledbmp; - BITMAP bmp; - GetObject(hbm, sizeof(BITMAP), &bmp); - width = bmp.bmWidth - 1; - height = bmp.bmHeight - 1; - stride = CalculateStride(width); - - pixels.resize(stride * height); - - BITMAPINFO bmi = {}; - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = width; - bmi.bmiHeader.biHeight = -height; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 24; - bmi.bmiHeader.biCompression = BI_RGB; - - BYTE* pBits = nullptr; - HDC hdc = GetDC(NULL); - GetDIBits(hdc, hbm, 0, height, pixels.data(), &bmi, DIB_RGB_COLORS); - - if (hdc) DeleteDC(hdc); - if (hbm) DeleteObject(hbm); - return true; - } - - bool SaveWindow10x10BMP(HWND hwnd, std::wstring filename, int x, int y) { - HDC hdcWindow = GetDC(hwnd); - HDC hdcMem = CreateCompatibleDC(hdcWindow); - - // Size: 10x10 - int width = 10; - int height = 10; - int stride = ((width * 3 + 3) & ~3); - std::vector pixels(stride * height); - - // Create a 24bpp bitmap - BITMAPINFO bmi = {}; - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = width; - bmi.bmiHeader.biHeight = -height; // top-down DIB - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 24; - bmi.bmiHeader.biCompression = BI_RGB; - - - //stretchblt - - BYTE* pBits = nullptr; - - HBITMAP hbm24 = CreateDIBSection(hdcWindow, &bmi, DIB_RGB_COLORS, (void**)&pBits, 0, 0); - if (!hbm24) { - DeleteDC(hdcMem); - ReleaseDC(hwnd, hdcWindow); - return false; - } - - HGDIOBJ oldbmp = SelectObject(hdcMem, hbm24); - - BitBlt(hdcMem, 0, 0, width, height, hdcWindow, x, y, SRCCOPY); - - // Prepare to retrieve bits - BITMAPINFOHEADER bih = {}; - bih.biSize = sizeof(BITMAPINFOHEADER); - bih.biWidth = width; - bih.biHeight = -height; // top-down for easier use - bih.biPlanes = 1; - bih.biBitCount = 24; - bih.biCompression = BI_RGB; - - GetDIBits(hdcMem, hbm24, 0, height, pixels.data(), (BITMAPINFO*)&bih, DIB_RGB_COLORS); - - // Save - bool ok = Save24BitBMP(filename.c_str(), pixels.data(), width, height); - - // Cleanup - SelectObject(hdcMem, oldbmp); - if (hbm24) DeleteObject(hbm24); - if (hdcMem)DeleteDC(hdcMem); - if (hdcWindow) ReleaseDC(hwnd, hdcWindow); - - return ok; - } - HBRUSH transparencyBrush; - - void DrawRedX(HDC hdc, int x, int y) //blue - { - HPEN hPen = CreatePen(PS_SOLID, 3, RGB(0, 0, 255)); - HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); - - MoveToEx(hdc, x - 15, y - 15, NULL); - LineTo(hdc, x + 15, y + 15); - - MoveToEx(hdc, x + 15, y - 15, NULL); - LineTo(hdc, x - 15, y + 15); - - SelectObject(hdc, hOldPen); - DeleteObject(hPen); - return; - } - void DrawBlueCircle(HDC hdc, int x, int y) //red - { - // Create a NULL brush (hollow fill) - HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH); - HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); - - HPEN hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0)); - HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); - - Ellipse(hdc, x - 15, y - 15, x + 15, y + 15); - - SelectObject(hdc, hOldBrush); - SelectObject(hdc, hOldPen); - DeleteObject(hPen); - } - void DrawGreenTriangle(HDC hdc, int x, int y) - { - // Use a NULL brush for hollow - HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH); - HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); - - HPEN hPen = CreatePen(PS_SOLID, 3, RGB(0, 255, 0)); - HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); - - POINT pts[3]; - pts[0].x = x; pts[0].y = y - 10; // top center - pts[1].x = x - 10; pts[1].y = y + 10; // bottom left - pts[2].x = x + 10; pts[2].y = y + 10; // bottom right - - Polygon(hdc, pts, 3); - - SelectObject(hdc, hOldBrush); - SelectObject(hdc, hOldPen); - DeleteObject(hPen); - } - - void DrawPinkSquare(HDC hdc, int x, int y) - { - // Create a NULL brush (hollow fill) - HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH); - HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); - - HPEN hPen = CreatePen(PS_SOLID, 3, RGB(255, 192, 203)); - HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); - - // Draw hollow rectangle (square) 20x20 - Rectangle(hdc, x - 15, y - 15, x + 15, y + 15); - - SelectObject(hdc, hOldBrush); - SelectObject(hdc, hOldPen); - DeleteObject(hPen); - } - - int moveH = 0; - int moveV = 0; //intro mainly to visualize cursor window size - bool otherway = false; - void DrawToHDC(HDC hdcWindow, int X, int Y, int showmessage) - { - - - //RECT fill{ WoldX, WoldY, WoldX + cursorWidth, WoldY + cursorHeight }; - if (TranslateXtoMKB::drawfakecursor == 2 || TranslateXtoMKB::drawfakecursor == 3) { - if (scanoption || TranslateXtoMKB::drawfakecursor == 3) - { - //erase - RECT rect; - GetClientRect(TranslateXtoMKB::pointerWindows, &rect); // client coordinates - FillRect(hdcWindow, &rect, transparencyBrush); - - } - else { - RECT rect = { WoldX, WoldY, WoldX + 32, WoldY + 32 }; //need bmp width height - WoldX = X - Xoffset; - WoldY = Y - Yoffset; - FillRect(hdcWindow, &rect, transparencyBrush); - } - } - - - if (scanoption == 1) - { - EnterCriticalSection(&critical); - POINT pos = { fakecursorW.x, fakecursorW.y }; - POINT Apos = { PointA.x, PointA.y }; - POINT Bpos = { PointB.x, PointB.y }; - POINT Xpos = { PointX.x, PointX.y }; - POINT Ypos = { PointY.x, PointY.y }; - //hCursorW = hCursor; - LeaveCriticalSection(&critical); - - //draw spots - if (Apos.x != 0 && Apos.y != 0) - DrawRedX(hdcWindow, Apos.x, Apos.y); - - if (Bpos.x != 0 && Bpos.y != 0) - DrawBlueCircle(hdcWindow, Bpos.x, Bpos.y); - - if (Xpos.x != 0 && Xpos.y != 0) - DrawGreenTriangle(hdcWindow, Xpos.x, Xpos.y); - - if (Ypos.x != 0 && Ypos.y != 0) - DrawPinkSquare(hdcWindow, Ypos.x, Ypos.y); - - } - if (showmessage == 99) //intro - { - RECT rect; - GetClientRect(TranslateXtoMKB::pointerWindows, &rect); // client coordinates - FillRect(hdcWindow, &rect, transparencyBrush); - - TextOut(hdcWindow, rect.right / 2, rect.bottom / 2, TEXT("LOADING..."), 10); - - DrawPinkSquare(hdcWindow, 20 + moveV, 20 + moveV); - DrawGreenTriangle(hdcWindow, rect.right - moveV - 20, rect.bottom - moveV - 20); - DrawBlueCircle(hdcWindow, rect.right - moveV - 20, 20 + moveV); - DrawRedX(hdcWindow, 20 + moveV, rect.bottom - moveV - 20); - - HCURSOR cursor = LoadCursor(NULL, IDC_ARROW); - DrawIcon(hdcWindow, X - Xoffset, Y - Yoffset, cursor); - - if (moveV < rect.bottom - 20 && moveV < rect.right - 20 && moveV >= 0) - { - if (!otherway) - moveV += 10; - else moveV -= 10; - } - - else if (!otherway) - { - moveV -= 10; - otherway = true; - } - else if (otherway) - { - moveV += 10; - otherway = false; - } - //showmessage will auto expire and go to 0 in mainthread - } - if (showmessage == 1) - { - TextOut(hdcWindow, X, Y, TEXT("BMP MODE"), 8); - TextOut(hdcWindow, X, Y + 17, TEXT("only mapping searches"), 21); - } - else if (showmessage == 2) - { - TextOut(hdcWindow, X, Y, TEXT("CURSOR MODE"), 11); - TextOut(hdcWindow, X, Y + 17, TEXT("mapping searches + cursor"), 25); - } - else if (showmessage == 3) - { - TextOut(hdcWindow, X, Y, TEXT("EDIT MODE"), 9); - TextOut(hdcWindow, X, Y + 15, TEXT("tap a button to bind it to coordinate"), 37); - TextOut(hdcWindow, X, Y + 30, TEXT("A,B,X,Y,R2,R3,L2,L3 can be mapped"), 32); - } - else if (showmessage == 4) - { - TextOut(hdcWindow, 20, 5, TEXT("Z0 no scale, Z1 stretch, Z2 4:3 stretch, Z3 16:9"), 49); - - TCHAR buf[32]; - wsprintf(buf, TEXT("Z0: X: %d Y: %d"), X, Y); - TextOut(hdcWindow, 20, 20, buf, lstrlen(buf)); - - - POINT staticpoint = GetStaticFactor({ X, Y }, 1, true); - TextOut(hdcWindow, staticpoint.x, staticpoint.y, TEXT("1"), 1); - - staticpoint = GetStaticFactor({ X, Y }, 2, true); - TextOut(hdcWindow, staticpoint.x, staticpoint.y, TEXT("2"), 1); - - staticpoint = GetStaticFactor({ X, Y }, 3, true); - TextOut(hdcWindow, staticpoint.x, staticpoint.y, TEXT("3"), 1); - - HCURSOR cursor = LoadCursor(NULL, IDC_ARROW); - DrawIcon(hdcWindow, X - Xoffset, Y - Yoffset, cursor); - } - else if (showmessage == 10) - { - TextOut(hdcWindow, X, Y, TEXT("BUTTON MAPPED"), 13); - } - else if (showmessage == 11) - { - TextOut(hdcWindow, X, Y, TEXT("WAIT FOR MESSAGE EXPIRE!"), 24); - } - else if (showmessage == 12) - { - TextOut(hdcWindow, 20, 20, TEXT("DISCONNECTED!"), 14); //14 - } - else if (showmessage == 69) - { - TextOut(hdcWindow, X, Y, TEXT("SHUTTING DOWN"), 13); - } - else if (showmessage == 70) - { - TextOut(hdcWindow, X, Y, TEXT("STARTING!"), 10); - } - else if (showmessage == 71) - { - TextOut(hdcWindow, X, Y, TEXT("WINDOW?"), 7); - } - if (nodrawcursor == false && showcursorcounter == true) // is 1 - { - if (hCursor != 0 && onoroff == true) - { - gotcursoryet = true; - if (X - Xoffset < 0 || Y - Yoffset < 0) - DrawIconEx(hdcWindow, X, Y, hCursor, 32, 32, 0, NULL, DI_NORMAL);//need bmp width height - else - DrawIconEx(hdcWindow, X - Xoffset, Y - Yoffset, hCursor, 32, 32, 0, NULL, DI_NORMAL);//need bmp width height - - } - else if (onoroff == true && (alwaysdrawcursor == 1 || gotcursoryet == false)) - { - HCURSOR cursor = LoadCursor(NULL, IDC_ARROW); - DrawIcon(hdcWindow, X - Xoffset, Y - Yoffset, cursor); - } - } - return; - } - - - - - void DblBufferAndCallDraw(HDC cursorhdc, int X, int Y, int showmessage) { - - POINT res = windowpos(hwnd, ignorerect, false); - int width = res.x; - int height = res.y; - - HDC hdcMem = CreateCompatibleDC(cursorhdc); - HBITMAP hbmMem = CreateCompatibleBitmap(cursorhdc, width, height); - HGDIOBJ oldBmp = SelectObject(hdcMem, hbmMem); - - //BitBlt(hdcMem, 0, 0, width, height, cursorhdc, 0, 0, SRCCOPY); - // SetBkMode(hdcMem, TRANSPARENT); - - DrawToHDC(hdcMem, X, Y, showmessage); - - BitBlt(cursorhdc, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY); - - // cleanup - SelectObject(hdcMem, oldBmp); - DeleteObject(hbmMem); - DeleteDC(hdcMem); - } - void GetGameHDCAndCallDraw(HWND hwnd) { - if (scanoption) - EnterCriticalSection(&critical); - HDC hdc = GetDC(hwnd); - if (hdc) - { - DrawToHDC(hdc, Xf, Yf, showmessage); - ReleaseDC(hwnd, hdc); - } - - if (scanoption) - LeaveCriticalSection(&critical); - return; - } - - bool CaptureWindow24Bit(HWND hwnd, SIZE& capturedwindow, std::vector& pixels, int& strideOut, bool draw, bool stretchblt) - { - if (scanoption && TranslateXtoMKB::drawfakecursor == 1) - EnterCriticalSection(&critical); - HDC hdcWindow = GetDC(hwnd); - HDC hdcMem = CreateCompatibleDC(hdcWindow); - - - RECT rcClient; - GetClientRect(hwnd, &rcClient); - int width = rcClient.right - rcClient.left; - int height = rcClient.bottom - rcClient.top; - capturedwindow.cx = width; - capturedwindow.cy = height; - - int stride = ((width * 3 + 3) & ~3); - strideOut = stride; - pixels.resize(stride * height); - - BITMAPINFO bmi = {}; - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = width; - bmi.bmiHeader.biHeight = -height; // top-down - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 24; - bmi.bmiHeader.biCompression = BI_RGB; - - BYTE* pBits = nullptr; - HBITMAP hbm24 = CreateDIBSection(hdcWindow, &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0); - if (hbm24) - { - HGDIOBJ oldBmp = SelectObject(hdcMem, hbm24); - BitBlt(hdcMem, 0, 0, width, height, hdcWindow, 0, 0, SRCCOPY); - GetDIBits(hdcMem, hbm24, 0, height, pixels.data(), &bmi, DIB_RGB_COLORS); - SelectObject(hdcMem, oldBmp); - DeleteObject(hbm24); - // hbm24 = nullptr; - - } //hbm24 not null - - if (hdcMem) DeleteDC(hdcMem); - if (hdcWindow) ReleaseDC(hwnd, hdcWindow); - - if (scanoption && TranslateXtoMKB::drawfakecursor == 1) - LeaveCriticalSection(&critical); - return true; - } //function end - // Helper: Get stick magnitude - float GetStickMagnitude(SHORT x, SHORT y) { - return sqrtf(static_cast(x) * x + static_cast(y) * y); - } - - // Helper: Clamp value to range [-1, 1] - float Clamp(float v) { - if (v < -1.0f) return -1.0f; - if (v > 1.0f) return 1.0f; - return v; - } - // #define DEADZONE 8000 - // #define MAX_SPEED 30.0f // Maximum pixels per poll - // #define ACCELERATION 2.0f // Controls non-linear ramp (higher = more acceleration) - - - POINT CalculateUltimateCursorMove( - SHORT stickX, SHORT stickY, - float c_deadzone, - float s_deadzone, - float max_threshold, - float curve_slope, - float curve_exponent, - float sensitivity, - float accel_multiplier - ) { - static double mouseDeltaAccumulatorX = 0.0; - static double mouseDeltaAccumulatorY = 0.0; - - double normX = static_cast(stickX) / 32767.0; - double normY = static_cast(stickY) / 32767.0; - - double magnitude = std::sqrt(normX * normX + normY * normY); - if (magnitude < c_deadzone) { - return { 0, 0 }; // Inside circular deadzone - } - if (std::abs(normX) < s_deadzone) { - normX = 0.0; // Inside axial deadzone for X - } - if (std::abs(normY) < s_deadzone) { - normY = 0.0; // Inside axial deadzone for Y - } - magnitude = std::sqrt(normX * normX + normY * normY); - if (magnitude < 1e-6) { - return { 0, 0 }; - } - - double effectiveRange = 1.0 - max_threshold - c_deadzone; - if (effectiveRange < 1e-6) effectiveRange = 1.0; - - double remappedMagnitude = (magnitude - c_deadzone) / effectiveRange; - remappedMagnitude = (std::max)(0.0, (std::min)(1.0, remappedMagnitude)); - - double curvedMagnitude = curve_slope * remappedMagnitude + (1.0 - curve_slope) * std::pow(remappedMagnitude, curve_exponent); - - double finalSpeed = sensitivity * accel_multiplier; - - double dirX = normX / magnitude; - double dirY = normY / magnitude; - double finalMouseDeltaX = dirX * curvedMagnitude * finalSpeed; - double finalMouseDeltaY = dirY * curvedMagnitude * finalSpeed; - - mouseDeltaAccumulatorX += finalMouseDeltaX; - mouseDeltaAccumulatorY += finalMouseDeltaY; - LONG integerDeltaX = static_cast(mouseDeltaAccumulatorX); - LONG integerDeltaY = static_cast(mouseDeltaAccumulatorY); - - mouseDeltaAccumulatorX -= integerDeltaX; - mouseDeltaAccumulatorY -= integerDeltaY; - - return { integerDeltaX, -integerDeltaY }; - } - - void PostKeyFunction(HWND hwnd, int keytype, bool press) { - DWORD mykey = 0; - DWORD presskey = WM_KEYDOWN; - - - - if (!press) { - presskey = WM_KEYUP; // Key up event - } - - //standard keys for dpad - if (keytype == -1) - mykey = VK_UP; - if (keytype == -2) - mykey = VK_DOWN; - if (keytype == -3) - mykey = VK_LEFT; - if (keytype == -4) - mykey = VK_RIGHT; - - if (keytype == 3) - mykey = VK_ESCAPE; - if (keytype == 4) - mykey = VK_RETURN; - if (keytype == 5) - mykey = VK_TAB; - if (keytype == 6) - mykey = VK_SHIFT; - if (keytype == 7) - mykey = VK_CONTROL; - if (keytype == 8) - mykey = VK_SPACE; - - if (keytype == 9) - mykey = 0x4D; //M - - if (keytype == 10) - mykey = 0x57; //W - - if (keytype == 11) - mykey = 0x53; //S - - if (keytype == 12) - mykey = 0x41; //A - - if (keytype == 13) - mykey = 0x44; //D - - if (keytype == 14) - mykey = 0x45; //E - - if (keytype == 15) - mykey = 0x46; //F - - if (keytype == 16) - mykey = 0x47; //G - - if (keytype == 17) - mykey = 0x48; //H - - if (keytype == 18) - mykey = 0x49; //I - - if (keytype == 19) - mykey = 0x51; //Q - - if (keytype == 20) - mykey = VK_OEM_PERIOD; - - if (keytype == 21) - mykey = 0x52; //R - - if (keytype == 22) - mykey = 0x54; //T - - if (keytype == 23) - mykey = 0x42; //B - - if (keytype == 24) - mykey = 0x43; //C - - if (keytype == 25) - mykey = 0x4B; //K - - if (keytype == 26) - mykey = 0x55; //U - - if (keytype == 27) - mykey = 0x56; //V - - if (keytype == 28) - mykey = 0x57; //W - - if (keytype == 30) - mykey = 0x30; //0 - - if (keytype == 31) - mykey = 0x31; //1 - - if (keytype == 32) - mykey = 0x32; //2 - - if (keytype == 33) - mykey = 0x33; //3 - - if (keytype == 34) - mykey = 0x34; //4 - - if (keytype == 35) - mykey = 0x35; //5 - - if (keytype == 36) - mykey = 0x36; //6 - - if (keytype == 37) - mykey = 0x37; //7 - - if (keytype == 38) - mykey = 0x38; //8 - - if (keytype == 39) - mykey = 0x39; //9 - - if (keytype == 40) - mykey = VK_UP; - - if (keytype == 41) - mykey = VK_DOWN; - - if (keytype == 42) - mykey = VK_LEFT; - - if (keytype == 43) - mykey = VK_RIGHT; - - if (keytype == 44) - mykey = 0x58; //X - - if (keytype == 45) - mykey = 0x5A; //Z - - if (keytype == 46) - mykey = 0x4C; //L - - - - if (keytype == 51) - mykey = VK_F1; - - if (keytype == 52) - mykey = VK_F2; - - if (keytype == 53) - mykey = VK_F3; - - if (keytype == 54) - mykey = VK_F4; - - if (keytype == 55) - mykey = VK_F5; - - if (keytype == 56) - mykey = VK_F6; - - if (keytype == 57) - mykey = VK_F7; - - if (keytype == 58) - mykey = VK_F8; - if (keytype == 59) - mykey = VK_F9; - - if (keytype == 60) - mykey = VK_F10; - - if (keytype == 61) - mykey = VK_F11; - - if (keytype == 62) - mykey = VK_F12; - - if (keytype == 63) { //control+C - mykey = VK_CONTROL; - } - - - if (keytype == 70) - mykey = VK_NUMPAD0; - - if (keytype == 71) - mykey = VK_NUMPAD1; - - if (keytype == 72) - mykey = VK_NUMPAD2; - - if (keytype == 73) - mykey = VK_NUMPAD3; - - if (keytype == 74) - mykey = VK_NUMPAD4; - - if (keytype == 75) - mykey = VK_NUMPAD5; - - if (keytype == 76) - mykey = VK_NUMPAD6; - - if (keytype == 77) - mykey = VK_NUMPAD7; - - if (keytype == 78) - mykey = VK_NUMPAD8; - - if (keytype == 79) - mykey = VK_NUMPAD9; - - if (keytype == 80) - mykey = VK_SUBTRACT; - - if (keytype == 81) - mykey = VK_ADD; - - UINT scanCode = MapVirtualKey(mykey, MAPVK_VK_TO_VSC); - unsigned int lParam; - - BOOL isExtended = (mykey == VK_LEFT || mykey == VK_RIGHT || - mykey == VK_UP || mykey == VK_DOWN || - mykey == VK_INSERT || mykey == VK_DELETE || - mykey == VK_HOME || mykey == VK_END || - mykey == VK_PRIOR || mykey == VK_NEXT || - mykey == VK_RCONTROL || mykey == VK_RMENU); - if (isExtended) - lParam |= (1 << 24); - if (press) - { - - lParam = 1; // repeat count 1 or 0? - lParam |= (scanCode << 16); // scan code - lParam |= (0 << 30); // previous state - lParam |= (0 << 31); // transition state (0 = key down) - keys[mykey] = true; - } - else - { - - - unsigned int lparam = 0; - lparam |= 1; // Repeat count (always 1 for key up) - lParam |= (scanCode << 16); - lparam |= (1 << 30); // Previous key state (always 1 for key up) - lparam |= (1 << 31); // Transition state (always 1 for key up) - keys[mykey] = false; - keystatesend = 0; - } - - - if (g_filterKeyboardButton == 1) { - LPARAM ScreenshotInput_KEYBOARD_SIGNATUR = 0x10000000; - PostMessage(hwnd, presskey, ScreenshotInput_KEYBOARD_SIGNATUR |= mykey, lParam); - } - else PostMessage(hwnd, presskey, mykey, lParam); - - // for (HWND ahwnd : g_windows) - // { //multiwindow support - // if (IsWindow(ahwnd) && hwnd != hwnd) - // { - // PostMessage(ahwnd, presskey, mykey, lParam); - // } - // } - // PostMessage(hwnd, WM_INPUT, VK_RIGHT, lParam); - if (TranslateXtoMKB::rawinputhook == 1 || TranslateXtoMKB::rawinputhook == 2) - GenerateRawKey(mykey, press); - if (keytype == 63) { - // PostMessage(hwnd, presskey, ScreenshotInput_KEYBOARD_SIGNATUR |= 0x43, lParam); //game specific key combo. Warlords Battlecry 3 convert button - } - return; - - } - - void BmpInputAction(int X, int Y, int type) //moveclickorboth - { - - if (type == 0) //click and move - { - Xf = X; - Yf = Y; - SendMouseClick(X, Y, 8, 1); - Sleep(5); - SendMouseClick(X, Y, 3, 2); - Sleep(5); - SendMouseClick(X, Y, 4, 2); - movedmouse = true; - } - else if (type == 1) //only move - { - Xf = X; - Yf = Y; - - SendMouseClick(X, Y, 8, 1); - movedmouse = true; - } - else if (type == 2) //only click - { - SendMouseClick(X, Y, 8, 1); - Sleep(2); - SendMouseClick(X, Y, 3, 2); - Sleep(2); - SendMouseClick(X, Y, 4, 2); - Sleep(2); - SendMouseClick(Xf, Yf, 8, 1); - } - } - void Bmpfound(const char key[3], int X, int Y, int i, bool onlysearch, bool found, int store) - { - int input = 0; - if (strcmp(key, "\\A") == 0) - { - if (found) - { - // EnterCriticalSection(&critical); - - // LeaveCriticalSection(&critical); - if (onlysearch) - { - EnterCriticalSection(&critical); - startsearchA = i; - input = scanAtype; - staticPointA[i].x = X; - staticPointA[i].y = Y; - PointA.x = X; - PointA.y = Y; - LeaveCriticalSection(&critical); - } - else - { - input = scanAtype; - if (store) { - staticPointA[i].x = X; - staticPointA[i].y = Y; - - } - if (startsearchA < numphotoA - 1) - startsearchA = i + 1; - else startsearchA = 0; - } - } - else - { - if (onlysearch) - { - EnterCriticalSection(&critical); - startsearchA = 0; - PointA.x = 0; - PointA.y = 0; - LeaveCriticalSection(&critical); - } - } - } - if (strcmp(key, "\\B") == 0) - { - if (found) - { - //EnterCriticalSection(&critical); - - //LeaveCriticalSection(&critical); - if (onlysearch) - { - EnterCriticalSection(&critical); - startsearchB = i; - PointB.x = X; - staticPointB[i].x = X; - staticPointB[i].y = Y; - PointB.y = Y; - LeaveCriticalSection(&critical); - } - else - { - input = scanBtype; - if (store) { - staticPointB[i].x = X; - staticPointB[i].y = Y; - } - if (startsearchB < numphotoB - 1) - startsearchB = i + 1; - else startsearchB = 0; - } - } - else - { - if (onlysearch) - { - EnterCriticalSection(&critical); - startsearchB = 0; - PointB.x = 0; - PointB.y = 0; - LeaveCriticalSection(&critical); - } - } - } - if (strcmp(key, "\\X") == 0) - { - if (found) - { - // EnterCriticalSection(&critical); - - //LeaveCriticalSection(&critical); - if (onlysearch) - { - EnterCriticalSection(&critical); - startsearchX = i; - PointX.x = X; - PointX.y = Y; - staticPointX[i].x = X; - staticPointX[i].y = Y; - LeaveCriticalSection(&critical); - } - else - { - input = scanXtype; - startsearchX = i + 1; - if (store) { - staticPointX[i].x = X; - staticPointX[i].y = Y; - } - if (startsearchX < numphotoX - 1) - startsearchX = i + 1; - else startsearchX = 0; - } - } - else - { - if (onlysearch) - { - EnterCriticalSection(&critical); - startsearchX = 0; - PointX.x = 0; - PointX.y = 0; - LeaveCriticalSection(&critical); - } - } - } - if (strcmp(key, "\\Y") == 0) - { - //EnterCriticalSection(&critical); - - //LeaveCriticalSection(&critical); - if (found) - { - if (onlysearch) - { - EnterCriticalSection(&critical); - startsearchX = i; - staticPointY[i].x = X; - staticPointY[i].y = Y; - PointY.x = X; - PointY.y = Y; - LeaveCriticalSection(&critical); - } - else - { - input = scanYtype; - startsearchY = i + 1; - if (store) { - staticPointY[i].x = X; - staticPointY[i].y = Y; - } - if (startsearchY < numphotoY - 1) - startsearchY = i + 1; - else startsearchY = 0; - } - } - else - { - if (onlysearch) - { - EnterCriticalSection(&critical); - startsearchY = 0; - //input = scanYtype; - PointY.x = 0; - PointY.y = 0; - LeaveCriticalSection(&critical); - } - } - } - if (strcmp(key, "\\C") == 0) - { - if (found && !onlysearch) - { - startsearchC = i + 1; - input = Ctype; - } - } - if (strcmp(key, "\\D") == 0) - { - if (found && !onlysearch) - { - startsearchD = i + 1; - input = Dtype; - } - } - if (strcmp(key, "\\E") == 0) - { - if (found && !onlysearch) - { - startsearchE = i + 1; - input = Etype; - } - } - if (strcmp(key, "\\F") == 0) - { - if (found && !onlysearch) - { - startsearchF = i + 1; - input = Ftype; - } - } - if (!onlysearch) - { - if (found) - { //input sent in this function - BmpInputAction(X, Y, input); - } - } - return; - } - - POINT CheckStatics(const char abc[3], int numtocheck) - { - POINT newpoint{ 0,0 }; - if (strcmp(abc, "\\A") == 0) - { - if (staticPointA[numtocheck].x != 0) - { - // - newpoint.x = staticPointA[numtocheck].x; - newpoint.y = staticPointA[numtocheck].y; - } - } - if (strcmp(abc, "\\B") == 0) - { - if (staticPointB[numtocheck].x != 0) - { - newpoint.x = staticPointB[numtocheck].x; - newpoint.y = staticPointB[numtocheck].y; - } - } - if (strcmp(abc, "\\X") == 0) - { - if (staticPointX[numtocheck].x != 0) - { - newpoint.x = staticPointX[numtocheck].x; - newpoint.y = staticPointX[numtocheck].y; - } - } - if (strcmp(abc, "\\Y") == 0) - { - if (staticPointY[numtocheck].x != 0) - { - newpoint.x = staticPointY[numtocheck].x; - newpoint.y = staticPointY[numtocheck].y; - } - } - return newpoint; - } - bool ButtonScanAction(const char key[3], int mode, int serchnum, int startsearch, bool onlysearch, POINT currentpoint, int checkarray) - { - //HBITMAP hbbmdsktop; - //criticals - //EnterCriticalSection(&critical); - bool found = false; - //LeaveCriticalSection(&critical); - //mode // onlysearch - POINT pt = { 0,0 }; - POINT noeder = { 0,0 }; - //MessageBox(NULL, "some kind of error", "startsearch searchnum error", MB_OK | MB_ICONINFORMATION); - int numbmp = 0; - if (mode != 2) - { - int numphoto = 0; - //if (checkarray == 1) - //{ //always check static first? - noeder = CheckStatics(key, startsearch); - if (noeder.x != 0) - { - Bmpfound(key, noeder.x, noeder.y, startsearch, onlysearch, true, checkarray); //or not found - found = true; - return true; - } - //} - if (!found) - { - for (int i = startsearch; i < serchnum; i++) //memory problem here somewhere - { - if (checkarray == 1) - { - noeder = CheckStatics(key, i); - if (noeder.x != 0) - { - Bmpfound(key, noeder.x, noeder.y, i, onlysearch, true, checkarray); //or not found - found = true; - return true; - } - } - // if (checkarray) - - // MessageBox(NULL, "some kind of error", "startsearch searchnum error", MB_OK | MB_ICONINFORMATION); - std::string path = UGetExecutableFolder() + key + std::to_string(i) + ".bmp"; - std::wstring wpath(path.begin(), path.end()); - // HDC soke; - if (LoadBMP24Bit(wpath.c_str(), smallPixels, smallW, smallH, strideSmall) && !found) - { - // MessageBox(NULL, "some kind of error", "loaded bmp", MB_OK | MB_ICONINFORMATION); - // Capture screen - // HBITMAP hbbmdsktop; - if (CaptureWindow24Bit(hwnd, screenSize, largePixels, strideLarge, false, resize)) - { - if (onlysearch) - { - if (FindSubImage24(largePixels.data(), screenSize.cx, screenSize.cy, strideLarge, smallPixels.data(), smallW, smallH, strideSmall, pt, currentpoint.x, currentpoint.y)) - { - numphoto = i; - found = true; - break; - } - } - if (found == false) - { - if (FindSubImage24(largePixels.data(), screenSize.cx, screenSize.cy, strideLarge, smallPixels.data(), smallW, smallH, strideSmall, pt, 0, 0)) - { - // MessageBox(NULL, "some kind of error", "found spot", MB_OK | MB_ICONINFORMATION); - found = true; - numphoto = i; - break; - } - }//found - } //hbmdessktop - }//loadbmp - } - } - if (!found) - { - for (int i = 0; i < serchnum; i++) //memory problem here somewhere - { - if (checkarray == 1) - { - noeder = CheckStatics(key, i); - if (noeder.x != 0) - { - //MessageBox(NULL, "some kind of error", "startsearch searchnum error", MB_OK | MB_ICONINFORMATION); - Bmpfound(key, noeder.x, noeder.y, i, onlysearch, true, checkarray); //or not found - found = true; - return true; - } - } - - std::string path = UGetExecutableFolder() + key + std::to_string(i) + ".bmp"; - std::wstring wpath(path.begin(), path.end()); - if (LoadBMP24Bit(wpath.c_str(), smallPixels, smallW, smallH, strideSmall) && !found) - { - //ShowMemoryUsageMessageBox(); - if (CaptureWindow24Bit(hwnd, screenSize, largePixels, strideLarge, false, resize)) - - {// MessageBox(NULL, "some kind of error", "captured desktop", MB_OK | MB_ICONINFORMATION); - //ShowMemoryUsageMessageBox(); - if (FindSubImage24(largePixels.data(), screenSize.cx, screenSize.cy, strideLarge, smallPixels.data(), smallW, smallH, strideSmall, pt, 0, 0)) - { - // MessageBox(NULL, "some kind of error", "found spot", MB_OK | MB_ICONINFORMATION); - found = true; - numphoto = i; - break; - } - - } //hbmdessktop - }//loadbmp - } - - } - EnterCriticalSection(&critical); - bool foundit = found; - LeaveCriticalSection(&critical); - Bmpfound(key, pt.x, pt.y, numphoto, onlysearch, found, checkarray); //or not found - if (found == true) - return true; - else return false; - } - - if (mode == 2 && showmessage == 0 && onlysearch == false) //mode 2 button mapping //showmessage var to make sure no double map or map while message - { - //RepaintWindow(hwnd, NULL, FALSE); - Sleep(100); //to make sure red flicker expired - std::string path = UGetExecutableFolder() + key + std::to_string(serchnum) + ".bmp"; - std::wstring wpath(path.begin(), path.end()); - SaveWindow10x10BMP(hwnd, wpath.c_str(), Xf, Yf); - // MessageBox(NULL, "Mapped spot!", key, MB_OK | MB_ICONINFORMATION); - showmessage = 10; - return true; - } - else if (mode == 2 && onlysearch == false) - showmessage = 11;//wait for mesage expire - return true; - } - //int akkumulator = 0; - -#define WM_MOVE_pointerWindows (WM_APP + 2) - - void GetWindowDimensions(HWND pointerWindow) - { - HWND tHwnd = hwnd; - if (pointerWindow == tHwnd) - return; - - if (IsWindow(tHwnd)) - { - POINT pos = windowpos(hwnd, ignorerect, true); - POINT res = windowpos(hwnd, ignorerect, false); - - SetWindowPos(pointerWindow, HWND_TOPMOST, - pos.x, - pos.y, - res.x, - res.y, - SWP_NOACTIVATE); - ShowWindow(pointerWindow, SW_SHOW); - } - } - // Window procedure - bool neederase = false; - LRESULT CALLBACK FakeCursorWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) - { - switch (msg) - { - case WM_MOVE_pointerWindows: - { - GetWindowDimensions(hWnd); - break; - } - case WM_PAINT: - { - return 1; - break; - } - case WM_ERASEBKGND: - { - return 1; - break; - } - case WM_DESTROY: - { - PostQuitMessage(0); - return 0; - } - default: - break; - } - - return DefWindowProc(hWnd, msg, wParam, lParam); - } - bool scanloop = false; - DWORD WINAPI ScanThread(LPVOID, int Aisstatic, int Bisstatic, int Xisstatic, int Yisstatic) - { - int scantick = 0; - Sleep(3000); - int Astatic = Aisstatic; - int Bstatic = Bisstatic; - int Xstatic = Xisstatic; - int Ystatic = Yisstatic; - //scanrunning = true; - scanloop = true; - while (scanloop) - { - EnterCriticalSection(&critical); - POINT Apos = { PointA.x, PointA.y }; - POINT Bpos = { PointB.x, PointB.y }; - POINT Xpos = { PointX.x, PointX.y }; - POINT Ypos = { PointY.x, PointY.y }; - int startsearchAW = startsearchA; - int startsearchBW = startsearchB; - int startsearchXW = startsearchX; - int startsearchYW = startsearchY; - POINT PointAW = PointA; - POINT PointBW = PointB; - POINT PointXW = PointX; - POINT PointYW = PointY; - LeaveCriticalSection(&critical); - - - - if (scantick < 3) - scantick++; - else scantick = 0; - if (scanoption == 1) - { - if (scantick == 0 && numphotoA > 0) - { - if (Astatic == 1) - { - if (staticPointA[startsearchAW].x == 0 && staticPointA[startsearchAW].y == 0) - ButtonScanAction("\\A", 1, numphotoA, startsearchAW, true, PointAW, Astatic); - else - Bmpfound("\\A", staticPointA[startsearchAW].x, staticPointA[startsearchAW].y, startsearchAW, true, true, Astatic); - } - else ButtonScanAction("\\A", 1, numphotoA, startsearchAW, true, PointAW, Astatic); - } - - if (scantick == 1 && numphotoB > 0) - { - if (Bstatic == 1) - { - if (staticPointB[startsearchBW].x == 0 && staticPointB[startsearchBW].y == 0) - //MessageBoxA(NULL, "heisann", "A", MB_OK); - ButtonScanAction("\\B", 1, numphotoB, startsearchBW, true, PointAW, Bstatic); - else - Bmpfound("\\B", staticPointB[startsearchBW].x, staticPointB[startsearchBW].y, startsearchBW, true, true, Bstatic); - } - else ButtonScanAction("\\B", 1, numphotoB, startsearchBW, true, PointBW, Bstatic); - - } - if (scantick == 2 && numphotoX > 0) - { - if (Xstatic == 1) - { - if (staticPointX[startsearchXW].x == 0 && staticPointX[startsearchXW].y == 0) - ButtonScanAction("\\X", 1, numphotoX, startsearchXW, true, PointXW, Xstatic); - else Bmpfound("\\X", staticPointX[startsearchXW].x, staticPointX[startsearchXW].y, startsearchXW, true, true, Xstatic); - } - else ButtonScanAction("\\X", 1, numphotoX, startsearchXW, true, PointXW, Xstatic); - - } - if (scantick == 3 && numphotoY > 0) - { - if (Ystatic == 1) - { - if (staticPointY[startsearchYW].x == 0 && staticPointY[startsearchYW].y == 0) - //MessageBoxA(NULL, "heisann", "A", MB_OK); - ButtonScanAction("\\Y", 1, numphotoY, startsearchYW, true, PointYW, Ystatic); - else - Bmpfound("\\Y", staticPointY[startsearchYW].x, staticPointY[startsearchYW].y, startsearchYW, true, true, Ystatic); - } - ButtonScanAction("\\Y", 1, numphotoY, startsearchYW, true, PointYW, Ystatic); - } - Sleep(10); - } - //else Sleep(1000); - } - return 0; - } - //TODO: width/height probably needs to change - - - // DrawFakeCursorFix. cursor offset scan and cursor size fix - - - // Thread to create and run the window - DWORD WINAPI WindowThreadProc(LPVOID) { - // Sleep(5000); - //EnterCriticalSection(&critical); - transparencyBrush = (HBRUSH)CreateSolidBrush(transparencyKey); - WNDCLASSW wc = { }; - wc.lpfnWndProc = FakeCursorWndProc; - wc.hInstance = GetModuleHandleW(0); - wc.hbrBackground = transparencyBrush; - - std::srand(static_cast(std::time(nullptr))); - const std::wstring classNameStr = std::wstring{ L"GtoMnK_Pointer_Window" } + std::to_wstring(std::rand()); - - wc.lpszClassName = classNameStr.c_str(); - wc.style = CS_OWNDC | CS_NOCLOSE; - - RegisterClassW(&wc); - - TranslateXtoMKB::pointerWindows = CreateWindowExW(WS_EX_NOACTIVATE | WS_EX_NOINHERITLAYOUT | WS_EX_NOPARENTNOTIFY | - WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW | WS_EX_LAYERED, - wc.lpszClassName, L"classNameStr.c_str()", - WS_POPUP | WS_VISIBLE, - 0, 0, 800, 600, - nullptr, nullptr, GetModuleHandle(NULL), nullptr); - - - - - if (!TranslateXtoMKB::pointerWindows) { - MessageBoxA(NULL, "Failed to create pointer window", "Error", MB_OK | MB_ICONERROR); - - } - SetLayeredWindowAttributes(TranslateXtoMKB::pointerWindows, transparencyKey, 0, LWA_COLORKEY); - - MSG msg; - ZeroMemory(&msg, sizeof(msg)); - //LeaveCriticalSection(&critical); - while (GetMessage(&msg, nullptr, 0, 0)) - { - if (msg.message != WM_QUIT) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - } - return 0; - } - - - - void pollbuttons(WORD buttons, RECT rect) - { - if (oldA == true) - { - if (buttons & XINPUT_GAMEPAD_A && onoroff == true) - { - // keep posting? - } - else { - oldA = false; - PostKeyFunction(hwnd, Atype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_A && onoroff == true) - { - oldA = true; - - if (!scanoption) { - startsearch = startsearchA; - ButtonScanAction("\\A", mode, numphotoA, startsearch, false, { 0,0 }, AuseStatic);//buttonacton will be occupied by scanthread - } - else - { - EnterCriticalSection(&critical); - POINT Cpoint; - Cpoint.x = PointA.x; - Cpoint.y = PointA.y; - - //LeaveCriticalSection(&critical); - if (Cpoint.x != 0 && Cpoint.y != 0) - { - if (ShoulderNextbmp == 0) - { - if (startsearchA < numphotoA - 1) - startsearchA++; //dont want it to update before input done - else startsearchA = 0; - PointA.x = 0; - PointA.y = 0; - } - BmpInputAction(Cpoint.x, Cpoint.y, scanAtype); - foundit = true; - - } - LeaveCriticalSection(&critical); - } - - EnterCriticalSection(&critical); - if (foundit == false && Atype != 0) - { - PostKeyFunction(hwnd, Atype, true); - } - LeaveCriticalSection(&critical); - if (mode == 2 && showmessage != 11) - { - numphotoA++; - Sleep(500); - } - } - - - - if (oldB == true) - { - if (buttons & XINPUT_GAMEPAD_B && onoroff == true) - { - // keep posting? - } - else { - oldB = false; - PostKeyFunction(hwnd, Btype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_B && onoroff == true) - { - - - oldB = true; - if (!scanoption) { - startsearch = startsearchB; - ButtonScanAction("\\B", mode, numphotoB, startsearch, false, { 0,0 }, BuseStatic); - } - else - { - EnterCriticalSection(&critical); - POINT Cpoint; - Cpoint.x = PointB.x; - Cpoint.y = PointB.y; - - if (Cpoint.x != 0 && Cpoint.y != 0) - { - if (ShoulderNextbmp == 0) - { - if (startsearchB < numphotoB - 1) - startsearchB++; //dont want it to update before input done - else startsearchB = 0; - PointB.x = 0; - PointB.y = 0; - } - BmpInputAction(Cpoint.x, Cpoint.y, scanBtype); - } - LeaveCriticalSection(&critical); - } - EnterCriticalSection(&critical); - if (foundit == false) - { - PostKeyFunction(hwnd, Btype, true); - } - LeaveCriticalSection(&critical); - if (mode == 2 && showmessage != 11) - { - numphotoB++; - Sleep(500); - } - - } - - - - if (oldX == true) - { - if (buttons & XINPUT_GAMEPAD_X && onoroff == true) - { - // keep posting? - } - else { - oldX = false; - PostKeyFunction(hwnd, Xtype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_X && onoroff == true) - { - oldX = true; - - - if (!scanoption) - { - startsearch = startsearchX; - ButtonScanAction("\\X", mode, numphotoX, startsearch, false, { 0,0 }, XuseStatic); - } - else - { - EnterCriticalSection(&critical); - POINT Cpoint; - Cpoint.x = PointX.x; - Cpoint.y = PointX.y; - - movedmouse = true; - if (Cpoint.x != 0 && Cpoint.y != 0) - { - if (ShoulderNextbmp == 0) - { - if (startsearchX < numphotoX - 1) - startsearchX++; //dont want it to update before input done - else startsearchX = 0; - PointX.x = 0; - PointX.y = 0; - } - BmpInputAction(Cpoint.x, Cpoint.y, scanXtype); - - } - LeaveCriticalSection(&critical); - } - EnterCriticalSection(&critical); - if (foundit == false) - { - PostKeyFunction(hwnd, Xtype, true); - } - LeaveCriticalSection(&critical); - if (mode == 2 && showmessage != 11) - { - numphotoX++; - Sleep(500); - } - } - - - - if (oldY == true) - { - if (buttons & XINPUT_GAMEPAD_Y && onoroff == true) - { - // keep posting? - } - else { - oldY = false; - PostKeyFunction(hwnd, Ytype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_Y && onoroff == true) - { - oldY = true; - - - if (!scanoption) { - startsearch = startsearchY; - ButtonScanAction("\\Y", mode, numphotoY, startsearch, false, { 0,0 }, false); - } - else - { - EnterCriticalSection(&critical); - POINT Cpoint; - Cpoint.x = PointY.x; - Cpoint.y = PointY.y; - - if (Cpoint.x != 0 && Cpoint.y != 0) - { - if (ShoulderNextbmp == 0) - { - if (startsearchY < numphotoY - 1) - startsearchY++; //dont want it to update before input done - else startsearchY = 0; - PointY.x = 0; - PointY.y = 0; - } - BmpInputAction(Cpoint.x, Cpoint.y, scanYtype); - - } - LeaveCriticalSection(&critical); - } - if (mode == 2 && showmessage != 11) - { //mapping mode - numphotoY++; - Sleep(500); - } - EnterCriticalSection(&critical); - if (foundit == false) - { - PostKeyFunction(hwnd, Ytype, true); - } - LeaveCriticalSection(&critical); - } - - - - if (oldC == true) - { - if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER && onoroff == true) - { - // keep posting? - } - else { - oldC = false; - PostKeyFunction(hwnd, Ctype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER && onoroff == true) - { - oldC = true; - - if (ShoulderNextbmp == 1) - { - EnterCriticalSection(&critical); - if (startsearchA < numphotoA - 1) - startsearchA++; //dont want it to update before input done - else startsearchA = 0; - if (startsearchB < numphotoB - 1) - startsearchB++; //dont want it to update before input done - else startsearchB = 0; - if (startsearchX < numphotoX - 1) - startsearchX++; //dont want it to update before input done - else startsearchX = 0; - LeaveCriticalSection(&critical); - } - startsearch = startsearchC; - if (!scanoption) - ButtonScanAction("\\C", mode, numphotoC, startsearch, false, { 0,0 }, false); - EnterCriticalSection(&critical); - if (foundit == false) - { - PostKeyFunction(hwnd, Ctype, true); - } - LeaveCriticalSection(&critical); - if (mode == 2 && showmessage == 0) - { - numphotoC++; - Sleep(500); - } - } - - - - if (oldD == true) - { - if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER && onoroff == true) - { - // keep posting? - } - else { - oldD = false; - PostKeyFunction(hwnd, Dtype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER && onoroff == true) - { - oldD = true; - - startsearch = startsearchD; - if (!scanoption) - ButtonScanAction("\\D", mode, numphotoD, startsearch, false, { 0,0 }, false); - EnterCriticalSection(&critical); - if (ShoulderNextbmp) - { - - if (startsearchA > 0) - startsearchA--; - else startsearchA = numphotoA - 1; - if (startsearchB > 0) - startsearchB--; - else startsearchB = numphotoB - 1; - if (startsearchX > 0) - startsearchX--; - else startsearchX = numphotoX - 1; - if (startsearchY > 0) - startsearchY--; - else startsearchY = numphotoY - 1; - - } - if (foundit == false) - { - PostKeyFunction(hwnd, Dtype, true); - } - LeaveCriticalSection(&critical); - if (mode == 2 && showmessage != 11) - { - numphotoD++; - Sleep(500); - } - } - - - - if (oldE == true) - { - if (buttons & XINPUT_GAMEPAD_RIGHT_THUMB && onoroff == true) - { - // keep posting? - } - else { - oldE = false; - PostKeyFunction(hwnd, Etype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_RIGHT_THUMB && onoroff == true) - { - oldE = true; - - startsearch = startsearchE; - if (!scanoption) - ButtonScanAction("\\E", mode, numphotoE, startsearch, false, { 0,0 }, false); - EnterCriticalSection(&critical); - if (foundit == false) - { - PostKeyFunction(hwnd, Etype, true); - } - LeaveCriticalSection(&critical); - if (mode == 2 && showmessage != 11) - { - numphotoE++; - Sleep(500); - } - } - - - - if (oldF == true) - { - if (buttons & XINPUT_GAMEPAD_LEFT_THUMB && onoroff == true) - { - // keep posting? - } - else { - oldF = false; - PostKeyFunction(hwnd, Ftype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_LEFT_THUMB && onoroff == true) - { - oldF = true; - - startsearch = startsearchF; - if (!scanoption) - ButtonScanAction("\\F", mode, numphotoF, startsearch, false, { 0,0 }, false); - EnterCriticalSection(&critical); - if (foundit == false) - { - PostKeyFunction(hwnd, Ftype, true); - } - LeaveCriticalSection(&critical); - if (mode == 2 && showmessage != 11) - { - numphotoF++; - Sleep(500); - } - } - - - - - if (oldup) - { - if (buttons & XINPUT_GAMEPAD_DPAD_UP && onoroff == true) - { - //post keep? - if (scrolloutsidewindow >= 3 && quickMW == 1) { - - SendMouseClick(Xf, Yf, 20, 1); - - } - } - else { - oldup = false; - PostKeyFunction(hwnd, uptype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_DPAD_UP && onoroff == true) - { - - scroll.x = rect.left + (rect.right - rect.left) / 2; - if (scrolloutsidewindow == 0) - scroll.y = rect.top + 1; - if (scrolloutsidewindow == 1) - scroll.y = rect.top - 1; - scrollmap = true; - if (scrolloutsidewindow == 2) { - oldup = true; - PostKeyFunction(hwnd, uptype, true); - } - if (scrolloutsidewindow >= 3) { - oldup = true; - scrollmap = false; - - SendMouseClick(Xf, Yf, 20, 1); - - - } - } - - - - - else if (olddown) - { - if (buttons & XINPUT_GAMEPAD_DPAD_DOWN && onoroff == true) - { - //post keep? - if (scrolloutsidewindow >= 3 && quickMW == 1) { - - SendMouseClick(Xf, Yf, 21, 1); - - } - } - else { - olddown = false; - PostKeyFunction(hwnd, downtype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_DPAD_DOWN && onoroff == true) - { - - scroll.x = rect.left + (rect.right - rect.left) / 2; - if (scrolloutsidewindow == 0) - scroll.y = rect.bottom - 1; - if (scrolloutsidewindow == 1) - scroll.y = rect.bottom + 1; - scrollmap = true; - if (scrolloutsidewindow == 2) { - olddown = true; - PostKeyFunction(hwnd, downtype, true); - } - if (scrolloutsidewindow >= 3) { - olddown = true; - scrollmap = false; - - SendMouseClick(Xf, Yf, 21, 1); - - - } - } - - - - - - else if (oldleft) - { - if (buttons & XINPUT_GAMEPAD_DPAD_LEFT && onoroff == true) - { - //post keep? - } - else { - oldleft = false; - PostKeyFunction(hwnd, lefttype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_DPAD_LEFT && onoroff == true) - { - if (scrolloutsidewindow == 0) - scroll.x = rect.left + 1; - if (scrolloutsidewindow == 1) - scroll.x = rect.left - 1; - scroll.y = rect.top + (rect.bottom - rect.top) / 2; - - scrollmap = true; - if (scrolloutsidewindow == 2 || scrolloutsidewindow == 4) { - oldleft = true; - PostKeyFunction(hwnd, lefttype, true); - } - - } - - - - - - else if (oldright) - { - if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT && onoroff == true) - { - //post keep? - } - else { - oldright = false; - PostKeyFunction(hwnd, righttype, false); - } - } - else if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT && onoroff == true) - { - if (scrolloutsidewindow == 0) - scroll.x = rect.right - 1; - if (scrolloutsidewindow == 1) - scroll.x = rect.right + 1; - scroll.y = rect.top + (rect.bottom - rect.top) / 2; - scrollmap = true; - if (scrolloutsidewindow == 2 || scrolloutsidewindow == 4) { - oldright = true; - PostKeyFunction(hwnd, righttype, true); - } - } - else - { - scrollmap = false; - } - - - - - if (buttons & XINPUT_GAMEPAD_START && (showmessage == 0 || showmessage == 4)) - { - Sleep(100); - if (onoroff == true && buttons & XINPUT_GAMEPAD_LEFT_SHOULDER && buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) - { - //MessageBox(NULL, "Bmp mode", "shutdown", MB_OK | MB_ICONINFORMATION); - showmessage = 69; - } - else if (onoroff == false && buttons & XINPUT_GAMEPAD_LEFT_SHOULDER && buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) - { - //MessageBox(NULL, "Bmp mode", "starting", MB_OK | MB_ICONINFORMATION); - showmessage = 70; - } - else if (mode == 0 && Modechange == 1 && onoroff == true) - { - mode = 1; - - // MessageBox(NULL, "Bmp + Emulated cursor mode", "Move the flickering red dot and use right trigger for left click. left trigger for right click", MB_OK | MB_ICONINFORMATION); - showmessage = 2; - } - else if (mode == 1 && Modechange == 1 && onoroff == true) - { - mode = 2; - //MessageBox(NULL, "Edit Mode", "Button mapping. will map buttons you click with the flickering red dot as an input coordinate", MB_OK | MB_ICONINFORMATION); - showmessage = 3; - - - } - else if (mode == 2 && Modechange == 1 && onoroff == true) - { - mode = 3; - // MessageBox(NULL, "Bmp mode", "only send input on bmp match", MB_OK | MB_ICONINFORMATION); - showmessage = 4; - Sleep(1000); - } - else if (mode == 3 && Modechange == 1 && onoroff == true) - { - // mode = 0; - // MessageBox(NULL, "Bmp mode", "only send input on bmp match", MB_OK | MB_ICONINFORMATION); - showmessage = 1; - } - - else if (onoroff == true) { //assume modechange not allowed. send escape key instead - keystatesend = VK_ESCAPE; - } - // Sleep(1000); //have time to release button. this is no hurry anyway - - } - } - int HowManyBmps(std::wstring path, bool andstatics) - { - int start = -1; - - int x = 0; - std::wstring filename; - while (x < 50 && start == -1) - { - filename = path + std::to_wstring(x) + L".bmp"; - if (HBITMAP hbm = (HBITMAP)LoadImageW(NULL, filename.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION)) - { - x++; - DeleteObject(hbm); - - } - else { - start = x; - } - } - - //searching statics - x = 0; - int inistart = -1; - while (x < 50 && inistart == -1) - { - std::string iniPath = UGetExecutableFolder() + "\\Xinput.ini"; - std::string iniSettings = "Statics"; - - std::string name(path.end() - 1, path.end()); - std::string string = name.c_str() + std::to_string(x) + "X"; - - - int sjekkX = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); //simple test if settings read but write it wont work. - if (sjekkX != 0) - { - string = name.c_str() + std::to_string(x) + "X"; - x++; - } - else inistart = x; - } - if (!andstatics || inistart == 0) - return start; - else return start + inistart; - } - - - - bool initovector() - { - std::string iniPath = UGetExecutableFolder() + "\\Xinput.ini"; - std::string iniSettings = "Statics"; - std::string name = "A"; - int y = -1; - int sjekkx = 0; - bool test = false; - int x = -1; - int scalemethod = 0; - POINT inipoint; - while (x < 50 && y == -1) - { - x++; - std::string string = name + std::to_string(x) + "X"; - sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - if (sjekkx != 0) - { - test = true; - inipoint.x = sjekkx; - - string = name + std::to_string(x) + "Y"; - inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - - string = name + std::to_string(x) + "Z"; - scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - if (scalemethod != 0) - inipoint = GetStaticFactor(inipoint, scalemethod, true); - staticPointA[x + numphotoYbmps].y = inipoint.y; - staticPointA[x + numphotoYbmps].x = inipoint.x; - } - else y = 10; - } - y = -1; - name = "B"; - sjekkx = 0; - x = -1; - while (x < 50 && y == -1) - { - x++; - std::string string = name + std::to_string(x) + "X"; - sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - if (sjekkx != 0) - { - test = true; - inipoint.x = sjekkx; - - string = name + std::to_string(x) + "Y"; - inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - - string = name + std::to_string(x) + "Z"; - scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - if (scalemethod != 0) - inipoint = GetStaticFactor(inipoint, scalemethod, true); - staticPointB[x + numphotoYbmps].y = inipoint.y; - staticPointB[x + numphotoYbmps].x = inipoint.x; - } - - else y = 10; - } - y = -1; - name = "X"; - sjekkx = 0; - x = -1; - while (x < 50 && y == -1) - { - x++; - std::string string = name.c_str() + std::to_string(x) + "X"; - //MessageBoxA(NULL, "no bmps", "aaahaAAAHAA", MB_OK); - sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - if (sjekkx != 0) - { - test = true; - inipoint.x = sjekkx; - - string = name + std::to_string(x) + "Y"; - inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - - string = name + std::to_string(x) + "Z"; - scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - if (scalemethod != 0) - inipoint = GetStaticFactor(inipoint, scalemethod, true); - staticPointX[x + numphotoYbmps].y = inipoint.y; - staticPointX[x + numphotoYbmps].x = inipoint.x; - - } - - else y = 10; - } - y = -1; - name = "Y"; - sjekkx = 0; - x = -1; - while (x < 50 && y == -1) - { - x++; - std::string string = name.c_str() + std::to_string(x) + "X"; - sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - if (sjekkx != 0) - { - test = true; - inipoint.x = sjekkx; - - string = name + std::to_string(x) + "Y"; - inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - - string = name + std::to_string(x) + "Z"; - scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); - if (scalemethod != 0) - inipoint = GetStaticFactor(inipoint, scalemethod, true); - staticPointY[x + numphotoYbmps].y = inipoint.y; - staticPointY[x + numphotoYbmps].x = inipoint.x; - } - else y = 10; - } - if (test == true) - return true; - else return false; //no points - } - - - bool enumeratebmps() - { - - - std::wstring path = WGetExecutableFolder() + L"\\A"; - numphotoA = HowManyBmps(path, true); - numphotoAbmps = HowManyBmps(path, false); - path = WGetExecutableFolder() + L"\\B"; - numphotoB = HowManyBmps(path, true); - numphotoBbmps = HowManyBmps(path, false); - path = WGetExecutableFolder() + L"\\X"; - numphotoX = HowManyBmps(path, true); - numphotoXbmps = HowManyBmps(path, false); - path = WGetExecutableFolder() + L"\\Y"; - numphotoY = HowManyBmps(path, true); - numphotoYbmps = HowManyBmps(path, false); - path = WGetExecutableFolder() + L"\\C"; - numphotoC = HowManyBmps(path, false); - path = WGetExecutableFolder() + L"\\D"; - numphotoD = HowManyBmps(path, false); - path = WGetExecutableFolder() + L"\\E"; - numphotoE = HowManyBmps(path, false); - path = WGetExecutableFolder() + L"\\F"; - numphotoF = HowManyBmps(path, false); - - if (numphotoA < 0 && numphotoB < 0 && numphotoX < 0 && numphotoY < 00) - { - - return false; - } - - return true; - } - std::wstring ToWString(const std::string& s) - { - return std::wstring(s.begin(), s.end()); - } - bool readsettings() { - char buffer[16]; //or only 4 maybe - - // settings reporting - std::string iniPath = UGetExecutableFolder() + "\\Xinput.ini"; - std::string iniSettings = "Settings"; - - //controller settings - //controllerID = GetPrivateProfileIntA(iniSettings.c_str(), "Controllerid", -9000, iniPath.c_str()); //simple test if settings read - AxisLeftsens = GetPrivateProfileIntA(iniSettings.c_str(), "AxisLeftsens", -9000, iniPath.c_str()); - AxisRightsens = GetPrivateProfileIntA(iniSettings.c_str(), "AxisRightsens", 9000, iniPath.c_str()); - AxisUpsens = GetPrivateProfileIntA(iniSettings.c_str(), "AxisUpsens", 9000, iniPath.c_str()); - AxisDownsens = GetPrivateProfileIntA(iniSettings.c_str(), "AxisDownsens", -9000, iniPath.c_str()); - scrollspeed3 = GetPrivateProfileIntA(iniSettings.c_str(), "Scrollspeed", 150, iniPath.c_str()); - righthanded = GetPrivateProfileIntA(iniSettings.c_str(), "Righthanded", 1, iniPath.c_str()); - scanoption = GetPrivateProfileIntA(iniSettings.c_str(), "Scan", 0, iniPath.c_str()); - GetPrivateProfileStringA(iniSettings.c_str(), "Radial_Deadzone", "0.0", buffer, sizeof(buffer), iniPath.c_str()); - radial_deadzone = std::stof(buffer); //sensitivity - - //window set pos - posX = GetPrivateProfileIntA(iniSettings.c_str(), "posX", 0, iniPath.c_str()); - posY = GetPrivateProfileIntA(iniSettings.c_str(), "posY", 0, iniPath.c_str()); - resX = GetPrivateProfileIntA(iniSettings.c_str(), "resX", 0, iniPath.c_str()); - resY = GetPrivateProfileIntA(iniSettings.c_str(), "resY", 0, iniPath.c_str()); - - GetPrivateProfileStringA(iniSettings.c_str(), "Axial_Deadzone", "0.0", buffer, sizeof(buffer), iniPath.c_str()); - axial_deadzone = std::stof(buffer); //sensitivity - - GetPrivateProfileStringA(iniSettings.c_str(), "Sensitivity", "12.0", buffer, sizeof(buffer), iniPath.c_str()); - sensitivity = std::stof(buffer); //sensitivity //accel_multiplier - - GetPrivateProfileStringA(iniSettings.c_str(), "Accel_Multiplier", "2.0", buffer, sizeof(buffer), iniPath.c_str()); - accel_multiplier = std::stof(buffer); - - Xoffset = GetPrivateProfileIntA(iniSettings.c_str(), "Xoffset", 0, iniPath.c_str()); - Yoffset = GetPrivateProfileIntA(iniSettings.c_str(), "Yoffset", 0, iniPath.c_str()); - - //mode - InitialMode = GetPrivateProfileIntA(iniSettings.c_str(), "Initial Mode", 1, iniPath.c_str()); - Modechange = GetPrivateProfileIntA(iniSettings.c_str(), "Allow modechange", 0, iniPath.c_str()); - - sendfocus = GetPrivateProfileIntA(iniSettings.c_str(), "Sendfocus", 0, iniPath.c_str()); - responsetime = GetPrivateProfileIntA(iniSettings.c_str(), "Responsetime", 1, iniPath.c_str()); - doubleclicks = GetPrivateProfileIntA(iniSettings.c_str(), "Doubleclicks", 0, iniPath.c_str()); - scrollenddelay = GetPrivateProfileIntA(iniSettings.c_str(), "DelayEndScroll", 50, iniPath.c_str()); - quickMW = GetPrivateProfileIntA(iniSettings.c_str(), "MouseWheelContinous", 0, iniPath.c_str()); - - //clicknotmove 2000 + keyboard key code - //movenotclick 1000 + keyboard key code - Atype = GetPrivateProfileIntA(iniSettings.c_str(), "A", 0, iniPath.c_str()); - Btype = GetPrivateProfileIntA(iniSettings.c_str(), "B", 0, iniPath.c_str()); - Xtype = GetPrivateProfileIntA(iniSettings.c_str(), "X", 1, iniPath.c_str()); - Ytype = GetPrivateProfileIntA(iniSettings.c_str(), "Y", 0, iniPath.c_str()); - Ctype = GetPrivateProfileIntA(iniSettings.c_str(), "RightShoulder", 2, iniPath.c_str()); - Dtype = GetPrivateProfileIntA(iniSettings.c_str(), "LeftShoulder", 0, iniPath.c_str()); - Etype = GetPrivateProfileIntA(iniSettings.c_str(), "RightThumb", 0, iniPath.c_str()); - Ftype = GetPrivateProfileIntA(iniSettings.c_str(), "LeftThumb", 0, iniPath.c_str()); - AuseStatic = GetPrivateProfileIntA(iniSettings.c_str(), "ScanAstatic", 0, iniPath.c_str()); - BuseStatic = GetPrivateProfileIntA(iniSettings.c_str(), "ScanBstatic", 0, iniPath.c_str()); - XuseStatic = GetPrivateProfileIntA(iniSettings.c_str(), "ScanXstatic", 0, iniPath.c_str()); - YuseStatic = GetPrivateProfileIntA(iniSettings.c_str(), "ScanYstatic", 0, iniPath.c_str()); - skipintro = GetPrivateProfileIntA(iniSettings.c_str(), "SkipIntro", 0, iniPath.c_str()); - - wchar_t buffers[256] = { 0 }; - - //setting bmp search type like flag values - if (Atype > 1999) - { - bmpAtype = 2; - scanAtype = 2; - Atype = Atype - 2000; + muusjn.lLastX = x; + muusjn.lLastY = y; + if (z == 3) { + muusjn.usButtonFlags |= RI_MOUSE_LEFT_BUTTON_DOWN; + Proto::FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_LBUTTON, true); + RawInput::GenerateRawMouseButton(-1, true); } - else if (Atype > 999) - { - bmpAtype = 1; - scanAtype = 1; - Atype = Atype - 1000; - } - else - { - bmpAtype = 0; - scanAtype = 0; - } - - if (Btype > 1999) + if (z == 4) { - bmpBtype = 2; - scanBtype = 2; - Btype = Btype - 2000; + muusjn.usButtonFlags |= RI_MOUSE_LEFT_BUTTON_UP; + Proto::FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_LBUTTON, false); + RawInput::GenerateRawMouseButton(-1, false); } - else if (Btype > 999) - { - bmpBtype = 1; - scanBtype = 1; - Btype = Btype - 1000; + if (z == 5) { + muusjn.usButtonFlags |= RI_MOUSE_RIGHT_BUTTON_DOWN; + Proto::FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_RBUTTON, true); + RawInput::GenerateRawMouseButton(-2, true); } - else + if (z == 6) { - bmpBtype = 0; - scanBtype = 0; - } + muusjn.usButtonFlags |= RI_MOUSE_RIGHT_BUTTON_UP; + Proto::FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_RBUTTON, false); + RawInput::GenerateRawMouseButton(-2, false); - if (Xtype > 1999) - { - scanXtype = 2; - bmpXtype = 2; - Xtype = Xtype - 2000; } - else if (Xtype > 999) + if (z == 20 || z == 21) //WM_mousewheel need desktop coordinates { - bmpXtype = 1; - scanXtype = 1; - Xtype = Xtype - 1000; } - else + else if (z == 8 || z == 10 || z == 11) //only mousemove { - bmpXtype = 0; - scanXtype = 0; - } + RawInput::SendActionDelta(x, y); + Proto::FakeMouseKeyboard::AddMouseDelta(x, y); - if (Ytype > 1999) - { - bmpYtype = 2; - scanYtype = 2; - Ytype = Ytype - 2000; } - else if (Ytype > 999) + Proto::RawInput::SendInputMessages(muusjn); + return true; + } + void ButtonStateImpulse(int button, bool state) + { + RAWKEYBOARD data{}; + data.Reserved = 0; + data.ExtraInformation = 0; + if (state) { - bmpYtype = 1; - scanYtype = 1; - Ytype = Ytype - 1000; + data.Flags = RI_KEY_MAKE; + data.Message = WM_KEYDOWN; } else { - bmpYtype = 0; - scanYtype = 0; - } + data.Flags = RI_KEY_BREAK; + data.Message = WM_KEYUP; + } - if (Ctype > 1999) - { - bmpCtype = 2; - Ctype = Ctype - 2000; - } - else if (Ctype > 999) - { - bmpCtype = 1; - Ctype = Ctype - 1000; - } - else + auto it = keyMap.find(button); + if (it != keyMap.end()) { - bmpCtype = 0; + data.MakeCode = it->second.makeCode; + data.VKey = it->second.vKey; + Proto::RawInput::SendKeyMessage(data, state); + RawInput::GenerateRawKey(data.VKey, state, false); } + else MessageBoxA(NULL, "Invalid button mapping", "Error", MB_OK | MB_ICONERROR); - if (Dtype > 1999) - { - bmpDtype = 2; - Dtype = Dtype - 2000; - } - else if (Dtype > 999) - { - bmpDtype = 1; - Dtype = Dtype - 1000; - } - else - { - bmpDtype = 0; - } + } + std::string UGetExecutableFolder() { + char path[MAX_PATH]; + GetModuleFileNameA(NULL, path, MAX_PATH); - if (Etype > 1999) - { - bmpEtype = 2; - Etype = Etype - 2000; - } - else if (Etype > 999) - { - bmpEtype = 1; - Etype = Etype - 1000; - } - else - { - bmpEtype = 0; - } + std::string exePath(path); - if (Ftype > 1999) - { - Ftype = Ftype - 2000; + size_t lastSlash = exePath.find_last_of("\\/"); + return exePath.substr(0, lastSlash); + } + + + std::wstring WGetExecutableFolder() { + wchar_t path[MAX_PATH]; + GetModuleFileNameW(NULL, path, MAX_PATH); + std::wstring exePath(path); + size_t lastSlash = exePath.find_last_of(L"\\/"); + + if (lastSlash == std::wstring::npos) + return L""; + return exePath.substr(0, lastSlash); + } + + + bool IsTriggerPressed(BYTE triggerValue) { + BYTE threshold = 175; + return triggerValue > threshold; + } + + + // Helper: Get stick magnitude + float GetStickMagnitude(SHORT x, SHORT y) { + return sqrtf(static_cast(x) * x + static_cast(y) * y); + } + + // Helper: Clamp value to range [-1, 1] + float Clamp(float v) { + if (v < -1.0f) return -1.0f; + if (v > 1.0f) return 1.0f; + return v; + } + // #define DEADZONE 8000 + // #define MAX_SPEED 30.0f // Maximum pixels per poll + // #define ACCELERATION 2.0f // Controls non-linear ramp (higher = more acceleration) + + + POINT CalculateUltimateCursorMove( + SHORT stickX, SHORT stickY, + float c_deadzone, + float s_deadzone, + float max_threshold, + float curve_slope, + float curve_exponent, + float sensitivity, + float accel_multiplier + ) { + static double mouseDeltaAccumulatorX = 0.0; + static double mouseDeltaAccumulatorY = 0.0; + + double normX = static_cast(stickX) / 32767.0; + double normY = static_cast(stickY) / 32767.0; + + double magnitude = std::sqrt(normX * normX + normY * normY); + if (magnitude < c_deadzone) { + return { 0, 0 }; // Inside circular deadzone } - else if (Ftype > 999) - { - bmpFtype = 1; - Ftype = Ftype - 1000; + if (std::abs(normX) < s_deadzone) { + normX = 0.0; // Inside axial deadzone for X } - else - { - bmpFtype = 0; + if (std::abs(normY) < s_deadzone) { + normY = 0.0; // Inside axial deadzone for Y + } + magnitude = std::sqrt(normX * normX + normY * normY); + if (magnitude < 1e-6) { + return { 0, 0 }; } - uptype = GetPrivateProfileIntA(iniSettings.c_str(), "Upkey", -1, iniPath.c_str()); - downtype = GetPrivateProfileIntA(iniSettings.c_str(), "Downkey", -2, iniPath.c_str()); - lefttype = GetPrivateProfileIntA(iniSettings.c_str(), "Leftkey", -3, iniPath.c_str()); - righttype = GetPrivateProfileIntA(iniSettings.c_str(), "Rightkey", -4, iniPath.c_str()); - ShoulderNextbmp = GetPrivateProfileIntA(iniSettings.c_str(), "ShouldersNextBMP", 0, iniPath.c_str()); + double effectiveRange = 1.0 - max_threshold - c_deadzone; + if (effectiveRange < 1e-6) effectiveRange = 1.0; + + double remappedMagnitude = (magnitude - c_deadzone) / effectiveRange; + remappedMagnitude = (std::max)(0.0, (std::min)(1.0, remappedMagnitude)); + + double curvedMagnitude = curve_slope * remappedMagnitude + (1.0 - curve_slope) * std::pow(remappedMagnitude, curve_exponent); + + double finalSpeed = sensitivity * accel_multiplier; + + double dirX = normX / magnitude; + double dirY = normY / magnitude; + double finalMouseDeltaX = dirX * curvedMagnitude * finalSpeed; + double finalMouseDeltaY = dirY * curvedMagnitude * finalSpeed; + + mouseDeltaAccumulatorX += finalMouseDeltaX; + mouseDeltaAccumulatorY += finalMouseDeltaY; + LONG integerDeltaX = static_cast(mouseDeltaAccumulatorX); + LONG integerDeltaY = static_cast(mouseDeltaAccumulatorY); + + mouseDeltaAccumulatorX -= integerDeltaX; + mouseDeltaAccumulatorY -= integerDeltaY; + + return { integerDeltaX, -integerDeltaY }; + } - //TranslateXtoMKB::drawfakecursor = GetPrivateProfileIntA(iniSettings.c_str(), "DrawFakeCursor", 3, iniPath.c_str()); - alwaysdrawcursor = GetPrivateProfileIntA(iniSettings.c_str(), "DrawFakeCursorAlways", 0, iniPath.c_str()); - ignorerect = GetPrivateProfileIntA(iniSettings.c_str(), "IgnoreRect", 0, iniPath.c_str()); + + std::wstring ToWString(const std::string& s) + { + return std::wstring(s.begin(), s.end()); + } + bool readsettings() { + char buffer[16]; //or only 4 maybe - scrolloutsidewindow = GetPrivateProfileIntA(iniSettings.c_str(), "Scrollmapfix", 1, iniPath.c_str()); //scrolloutsidewindow - mode = InitialMode; + // settings reporting + std::string iniPath = UGetExecutableFolder() + "\\Xinput.ini"; + std::string iniSettings = "Settings"; return true; } @@ -3452,593 +334,296 @@ namespace ScreenshotInput { Proto::AddThreadToACL(GetCurrentThreadId()); - if (hooksoninit == 1) //if 2 then just after window found - { - SetupHook(); - EnableHooks(); - } Sleep(2000); if (readsettings() == false) { //messagebox? settings not read } - if (findwindowdelay > 0) - Sleep(findwindowdelay * 1000); //delaying windowsearch - RECT rect; - bool Aprev = false; - if (scanoption == 1) - { //starting bmp conttinous scanner - std::thread tree(ScanThread, g_hModule, AuseStatic, BuseStatic, XuseStatic, YuseStatic); - tree.detach(); - } - if (TranslateXtoMKB::drawfakecursor == 0) - { - TranslateXtoMKB::drawfakecursor = 1; - nodrawcursor = true; - } - bool window = false; - bool gotwindow = false; - if (skipintro == 0) - showmessage = 99; - int retrynum = 0; while (loop == true) { - rawmouseWu = false; //reset - rawmouseWd = false; //reset movedmouse = false; //reset - keystatesend = 0; //reset keystate - foundit = false; //reset foundit the bmp search found or not - if (!hwnd) - hwnd = (HWND)Proto::HwndSelector::GetSelectedHwnd(); - else + XINPUT_STATE state; + ZeroMemory(&state, sizeof(XINPUT_STATE)); + // Check controller 0 + DWORD dwResult = OpenXInputGetState(TranslateXtoMKB::controllerID, &state); + if (dwResult == ERROR_SUCCESS) { - if (hooksoninit == 2 && hooksinited == false) - { - SetupHook(); - if (!hooksenabled) - EnableHooks(); - } + WORD buttons = state.Gamepad.wButtons; - if (!inithere) + if (mode > 0) { - if (!enumeratebmps()) //always this before initovector + //fake cursor poll + int Xaxis = 0; + int Yaxis = 0; + int scrollXaxis = 0; + int scrollYaxis = 0; + int Yscroll = 0; + int Xscroll = 0; + bool leftPressed = IsTriggerPressed(state.Gamepad.bLeftTrigger); + bool rightPressed = IsTriggerPressed(state.Gamepad.bRightTrigger); + + if (righthanded == 1) { + Xaxis = state.Gamepad.sThumbRX; + Yaxis = state.Gamepad.sThumbRY; + scrollXaxis = state.Gamepad.sThumbLX; + scrollYaxis = state.Gamepad.sThumbLY; + } + else { - if (scanoption) - { - MessageBoxA(NULL, "Error. scanoption without bmps", "No BMPS found", MB_OK); - scanloop = false; //force stop scan thread - scanoption = 0; - } + Xaxis = state.Gamepad.sThumbLX; + Yaxis = state.Gamepad.sThumbLY; + scrollXaxis = state.Gamepad.sThumbRX; + scrollYaxis = state.Gamepad.sThumbRY; + } + + delta = CalculateUltimateCursorMove( + Xaxis, Yaxis, + radial_deadzone, axial_deadzone, max_threshold, + curve_slope, curve_exponent, + sensitivity, accel_multiplier + ); + if (delta.x != 0 || delta.y != 0) { + Xf += delta.x; + Yf += delta.y; + movedmouse = true; } - //resize window if set in ini - if (resX != 0) + if (movedmouse == true) //fake cursor move message { - SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE); - SetWindowPos(hwnd, NULL, posX, posY, resX, resY, SWP_NOZORDER | SWP_NOACTIVATE); + SendMouseClick(delta.x, delta.y, 8); + + Proto::FakeCursor::NotifyUpdatedCursorPosition(); } - staticPointA.assign(numphotoA + 1, POINT{ 0, 0 }); - staticPointB.assign(numphotoB + 1, POINT{ 0, 0 }); - staticPointX.assign(numphotoX + 1, POINT{ 0, 0 }); - staticPointY.assign(numphotoY + 1, POINT{ 0, 0 }); - initovector(); - inithere = true; - } - // - POINT poscheck = windowpos(hwnd, ignorerect, true); - POINT rescheck = windowpos(hwnd, ignorerect, false); - if (TranslateXtoMKB::drawfakecursor == 2 || TranslateXtoMKB::drawfakecursor == 3) - {//fake cursor window creation - - if (!window) + if (leftPressedold) { - std::thread two(WindowThreadProc, g_hModule); - two.detach(); - Sleep(100); //give time to create window - EnterCriticalSection(&critical); - while (!TranslateXtoMKB::pointerWindows) { - MessageBoxA(NULL, "No pointerwindow", "ohno,try drawfakecursor 1 instead", MB_OK); - Sleep(1000); - } - if (TranslateXtoMKB::pointerWindows) { - //Sleep(500); - PointerWnd = GetDC(TranslateXtoMKB::pointerWindows); - SendMessage(TranslateXtoMKB::pointerWindows, WM_MOVE_pointerWindows, 0, 0); //focus to avoid alt tab issues - LeaveCriticalSection(&critical); + if (!leftPressed) + { + + SendMouseClick(Xf, Yf, 6); //double click + leftPressedold = false; } - window = true; } - else if (poscheck.x != oldposcheck.x || oldposcheck.y != oldposcheck.y || oldrescheck.y != oldrescheck.y || oldrescheck.x != oldrescheck.x) + else if (leftPressed) { - EnterCriticalSection(&critical); - if (TranslateXtoMKB::pointerWindows) - SendMessage(TranslateXtoMKB::pointerWindows, WM_MOVE_pointerWindows, 0, 0); - //clearing points and reinit on window move or resize - staticPointA.clear(); - staticPointB.clear(); - staticPointX.clear(); - staticPointY.clear(); - initovector(); //this also call for scaling if needed - LeaveCriticalSection(&critical); - Sleep(1000); //pause renderiing + if (leftPressedold == false) + { + SendMouseClick(Xf, Yf, 5); //4 skal vere 3 + leftPressedold = true; + } } - oldposcheck.x = poscheck.x; - oldposcheck.y = poscheck.y; - - oldrescheck.x = rescheck.x; - oldrescheck.y = rescheck.y; - - } - - if (ignorerect == 1) - { - // These are the actual visible edges of the window in client coordinates - POINT upper = windowpos(hwnd, ignorerect, true); - POINT lower = windowpos(hwnd, ignorerect, false); - - //used in getcursrorpos - rectignore.x = upper.x; - rectignore.y = upper.y; //+titlebar if any? - - rect.right = lower.x + upper.x; //+ upper? - rect.bottom = lower.y + upper.y;//+ upper? - rect.left = 0; //upper? - rect.top = 0; - - } - else - { - GetClientRect(hwnd, &rect); - } - XINPUT_STATE state; - ZeroMemory(&state, sizeof(XINPUT_STATE)); - // Check controller 0 - DWORD dwResult = OpenXInputGetState(TranslateXtoMKB::controllerID, &state); - bool leftPressed = IsTriggerPressed(state.Gamepad.bLeftTrigger); - bool rightPressed = IsTriggerPressed(state.Gamepad.bRightTrigger); - + if (rightPressedold) + { + if (!rightPressed) + { + SendMouseClick(Xf, Yf, 4); + rightPressedold = false; + } + } //if rightpress + else if (rightPressed) + { + if (rightPressedold == false) + { + SendMouseClick(Xf, Yf, 3); + rightPressedold = true; - if (dwResult == ERROR_SUCCESS) - { + } + } - //criticals for windowthread // now only scanthread. - // //window rendering handled by current thread - EnterCriticalSection(&critical); - fakecursorW.x = Xf; - fakecursorW.y = Yf; - showmessageW = showmessage; - LeaveCriticalSection(&critical); - - // Controller is connected - WORD buttons = state.Gamepad.wButtons; - pollbuttons(buttons, rect); //all buttons exept triggers and axises - if (showmessage == 12) //was disconnected last scan? + //buttons + if (oldA) + { + if (buttons & XINPUT_GAMEPAD_A) + { + } + else{ + oldA = false; + ButtonStateImpulse(Atype, false);//release + } + } + else if (buttons & XINPUT_GAMEPAD_A) { - showmessage = 0; + oldA = true; + ButtonStateImpulse(Atype, true);//down } - if (mode > 0 && onoroff == true) + + if (oldB) { - //fake cursor poll - int Xaxis = 0; - int Yaxis = 0; - int scrollXaxis = 0; - int scrollYaxis = 0; - POINT resw = windowpos(hwnd, ignorerect, false); - int width = resw.x; - int height = resw.y; - int Yscroll = 0; - int Xscroll = 0; - bool didscroll = false; - - - if (righthanded == 1) { - Xaxis = state.Gamepad.sThumbRX; - Yaxis = state.Gamepad.sThumbRY; - scrollXaxis = state.Gamepad.sThumbLX; - scrollYaxis = state.Gamepad.sThumbLY; - } - else + if (buttons & XINPUT_GAMEPAD_B) { - Xaxis = state.Gamepad.sThumbLX; - Yaxis = state.Gamepad.sThumbLY; - scrollXaxis = state.Gamepad.sThumbRX; - scrollYaxis = state.Gamepad.sThumbRY; } + else { + oldB = false; + ButtonStateImpulse(Btype, false);//release + } + } + else if (buttons & XINPUT_GAMEPAD_B) + { + oldB = true; + ButtonStateImpulse(Btype, true);//down + } - if (scrolloutsidewindow == 2 || scrolloutsidewindow == 3 || scrolloutsidewindow == 4) - { - if (oldscrollleftaxis) - { - if (scrollXaxis < AxisLeftsens) //left - { - if (scrolloutsidewindow == 3) - { //keep - scrollXaxis = scrollXaxis - AxisLeftsens; //zero input - doscrollyes = true; - Xscroll = +scrollXaxis / scrollspeed3; - didscroll = true; - } - // PostKeyFunction(hwnd, 42, true); - } - else - { //stop - oldscrollleftaxis = false; - if (scrolloutsidewindow == 2) - PostKeyFunction(hwnd, 42, false); - if (scrolloutsidewindow == 4) - PostKeyFunction(hwnd, 12, false); - } - } - else if (scrollXaxis < AxisLeftsens) //left - { - if (scrolloutsidewindow == 2) - PostKeyFunction(hwnd, 42, true); - if (scrolloutsidewindow == 4) - PostKeyFunction(hwnd, 12, true); - if (scrolloutsidewindow == 3 && doscrollyes == false) - {//start - tick = 0; - SendMouseClick(Xf, Yf, 8, 1); - SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 - } - oldscrollleftaxis = true; - //keystatesend = VK_LEFT; - } - - - if (oldscrollrightaxis) - { - if (scrollXaxis > AxisRightsens) //right - { - if (scrolloutsidewindow == 3) - { //keep - doscrollyes = true; - scrollXaxis = scrollXaxis - AxisRightsens; //zero input - Xscroll = scrollXaxis / scrollspeed3; - didscroll = true; - } - } - else { - oldscrollrightaxis = false; - if (scrolloutsidewindow == 2) - PostKeyFunction(hwnd, 43, false); - if (scrolloutsidewindow == 4) - PostKeyFunction(hwnd, 13, false); - } - } - else if (scrollXaxis > AxisRightsens) //right - { - if (scrolloutsidewindow == 2) - PostKeyFunction(hwnd, 43, true); - if (scrolloutsidewindow == 4) - PostKeyFunction(hwnd, 13, true); - if (scrolloutsidewindow == 3 && doscrollyes == false) - {//start - tick = 0; - SendMouseClick(Xf, Yf, 8, 1); - SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 - } - oldscrollrightaxis = true; - //keystatesend = VK_RIGHT; - - } - - - - if (oldscrolldownaxis) - { - if (scrollYaxis < AxisDownsens) - { - // PostKeyFunction(hwnd, 41, true); - if (scrolloutsidewindow == 3) - { //keep - scrollYaxis = scrollYaxis - AxisDownsens; //zero input - doscrollyes = true; - Yscroll = scrollYaxis / scrollspeed3; - didscroll = true; - } - } - else { - oldscrolldownaxis = false; - if (scrolloutsidewindow == 2) - PostKeyFunction(hwnd, 41, false); - if (scrolloutsidewindow == 4) - PostKeyFunction(hwnd, 11, false); - } - } - else if (scrollYaxis < AxisDownsens) //down - { //start - if (scrolloutsidewindow == 2) - PostKeyFunction(hwnd, 41, true); - if (scrolloutsidewindow == 4) - PostKeyFunction(hwnd, 11, true); - if (scrolloutsidewindow == 3 && doscrollyes == false) - {//start - tick = 0; - SendMouseClick(Xf, Yf, 8, 1); - SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 - } - oldscrolldownaxis = true; - } - - - - - - if (oldscrollupaxis) - { - if (scrollYaxis > AxisUpsens) - { - // PostKeyFunction(hwnd, 40, true); - if (scrolloutsidewindow == 3) - { //keep - scrollYaxis = scrollYaxis - AxisUpsens; //zero input - doscrollyes = true; - - Yscroll = scrollYaxis / scrollspeed3; //150 - didscroll = true; - } - } - else { - oldscrollupaxis = false; - if (scrolloutsidewindow == 2) - PostKeyFunction(hwnd, 40, false); - if (scrolloutsidewindow == 4) - PostKeyFunction(hwnd, 10, false); - } - } - else if (scrollYaxis > AxisUpsens) //up - { - if (scrolloutsidewindow == 2) - PostKeyFunction(hwnd, 40, true); - if (scrolloutsidewindow == 4) - PostKeyFunction(hwnd, 10, true); - if (scrolloutsidewindow == 3 && doscrollyes == false) - {//start - tick = 0; - SendMouseClick(Xf, Yf, 8, 1); - SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 - } - oldscrollupaxis = true; - } + if (oldX) + { + if (buttons & XINPUT_GAMEPAD_X) + { } + else { + oldX = false; + ButtonStateImpulse(Xtype, false);//release + } + } + else if (buttons & XINPUT_GAMEPAD_X) + { + oldX = true; + ButtonStateImpulse(Xtype, true);//down + } - //mouse left click and drag scrollfunction //scrolltype 3 - - if (doscrollyes) { - SendMouseClick(Xf + Xscroll, Yf - Yscroll, 8, 1); //4 skal vere 3 - if (!didscroll && tick == scrollenddelay) - { - //MessageBox(NULL, "Scroll stopped", "Info", MB_OK | MB_ICONINFORMATION); - doscrollyes = false; - SendMouseClick(Xf, Yf, 6, 2); //4 skal vere 3 - } + if (oldY) + { + if (buttons & XINPUT_GAMEPAD_Y) + { } + else { + oldY = false; + ButtonStateImpulse(Ytype, false);//release + } + } + else if (buttons & XINPUT_GAMEPAD_Y) + { + oldY = true; + ButtonStateImpulse(Ytype, true);//down + } - - if (scrolloutsidewindow < 2 && scrollmap == false) //was 2 + if (oldC) + { + if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) { - if (scrollXaxis < AxisLeftsens - 10000) //left - { - if (scrolloutsidewindow == 0) - scroll.x = rect.left + 1; - if (scrolloutsidewindow == 1) - scroll.x = rect.left - 1; - if (scrolloutsidewindow == 3) - scroll.x = (rect.left + (rect.right - rect.left) / 2) - 100; - scroll.y = rect.top + (rect.bottom - rect.top) / 2; - - scrollmap = true; - - } - else if (scrollXaxis > AxisRightsens + 10000) //right - { - if (scrolloutsidewindow == 0) - scroll.x = rect.right - 1; - if (scrolloutsidewindow == 1) - scroll.x = rect.right + 1; - if (scrolloutsidewindow == 3) - scroll.x = (rect.left + (rect.right - rect.left) / 2) + 100; - scroll.y = rect.top + (rect.bottom - rect.top) / 2; - - scrollmap = true; - - } - else if (scrollYaxis < AxisDownsens - 10000) //down - { - scroll.x = rect.left + (rect.right - rect.left) / 2; - if (scrolloutsidewindow == 0) - scroll.y = rect.bottom - 1; - if (scrolloutsidewindow == 1) - scroll.y = rect.bottom + 1; - if (scrolloutsidewindow == 3) - scroll.y = (rect.top + (rect.bottom - rect.top) / 2) + 100; - scrollmap = true; - - - } - - else if (scrollYaxis > AxisUpsens + 10000) //up - { - scroll.x = rect.left + (rect.right - rect.left) / 2; - if (scrolloutsidewindow == 0) - scroll.y = rect.top + 1; - if (scrolloutsidewindow == 1) - scroll.y = rect.top - 1; - if (scrolloutsidewindow == 3) - scroll.y = (rect.top + (rect.bottom - rect.top) / 2) - 100; - scrollmap = true; - } - - else { - scrollmap = false; - } } - - delta = CalculateUltimateCursorMove( - Xaxis, Yaxis, - radial_deadzone, axial_deadzone, max_threshold, - curve_slope, curve_exponent, - sensitivity, accel_multiplier - ); - if (delta.x != 0 || delta.y != 0) { - Xf += delta.x; - Yf += delta.y; - movedmouse = true; + else { + oldC = false; + ButtonStateImpulse(Ctype, false); //release } + } + else if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) + { + oldC = true; + ButtonStateImpulse(Ctype, true); //down + } - //may freeze cursor here. dont know why yet - if (Xf > width - 1) Xf = width - 1; - if (Yf > height - 1) Yf = height - 1; - if (Yf < 1) Yf = 1; - if (Xf < 1) Xf = 1; - if (movedmouse == true) //fake cursor move message + if (oldD) + { + if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) { - SendMouseClick(Xf, Yf, 8, 1); } + else { + oldD = false; + ButtonStateImpulse(Ctype, false);//release + } + } + else if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) + { + oldD = true; + ButtonStateImpulse(Ctype, true);//down + } + - if (leftPressed) + if (oldleft) + { + if (buttons & XINPUT_GAMEPAD_DPAD_LEFT) { + } + else { + oldleft = false; + ButtonStateImpulse(Lefttype, false); //release + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_LEFT) + { + oldleft = true; + ButtonStateImpulse(Lefttype, true);//down + } - if (leftPressedold == false) - { - //save coordinates - startdrag.x = Xf; - startdrag.y = Yf; - leftPressedold = true; - rawmouseR = true; - if (scrolloutsidewindow == 3) - { - SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 - SendMouseClick(Xf, Yf, 6, 2); //double click - } - else - SendMouseClick(Xf, Yf, 5, 2); //4 skal vere 3 - } - } - else if (leftPressedold) + if (oldright) + { + if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) { - if (!leftPressed) - { + } + else { + oldright = false; + ButtonStateImpulse(righttype, false);//release + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) + { + oldright = true; + ButtonStateImpulse(righttype, true);//down + } - SendMouseClick(Xf, Yf, 6, 2); //double click - leftPressedold = false; - rawmouseR = false; - } - } - if (rightPressed) + if (oldup) + { + if (buttons & XINPUT_GAMEPAD_DPAD_UP) { - if (rightPressedold == false) - { - //save coordinates - //start - if (hooksinited == false) - { - SetupHook(); - if (!hooksenabled) - EnableHooks(); - } - startdrag.x = Xf; - startdrag.y = Yf; - rightPressedold = true; - rawmouseL = true; - - DWORD currentTime = GetTickCount64(); - if (currentTime - lastClickTime < GetDoubleClickTime() && doubleclicks == 1) //movedmouse? - { - SendMouseClick(Xf, Yf, 30, 2); //4 skal vere 3 - } - else - { - SendMouseClick(Xf, Yf, 3, 2); //4 skal vere 3 - } - lastClickTime = currentTime; - - - } } - else if (rightPressedold) - { - if (!rightPressed) - { - SendMouseClick(Xf, Yf, 4, 2); - rightPressedold = false; - rawmouseL = false; - } - } //if rightpress - - } //if mode above 0 - } //if controller - else { - showmessage = 12; - //MessageBoxA(NULL, "Controller not connected", "Error", MB_OK | MB_ICONERROR); - } - - - //rendering. 3 methods. 1 direct draw. 2 partial on own window. 3 full redraw double buffer on own window - if (TranslateXtoMKB::drawfakecursor == 1) - GetGameHDCAndCallDraw(hwnd); //calls DrawToHdc in here - else if (TranslateXtoMKB::drawfakecursor == 2) - { - if (scanoption) - DblBufferAndCallDraw(PointerWnd, Xf, Yf, showmessage); //full redraw - else if (movedmouse) DrawToHDC(PointerWnd, Xf, Yf, showmessage); //partial, much faster. may not erase correctly on staticpoints and messages yet - } - else if (TranslateXtoMKB::drawfakecursor == 3) - DblBufferAndCallDraw(PointerWnd, Xf, Yf, showmessage); //full redraw + else { + oldup = false; + ButtonStateImpulse(uptype, false);//release + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_UP) + { + oldup = true; + ButtonStateImpulse(uptype, true);//down + } - } // if hwnd - if (showmessage != 0 && showmessage != 12) - { - counter++; - if (counter > 400) - { - if (showmessage == 1) { - mode = 0; - showmessage = 0; - } - if (showmessage == 69) { //disabling dll - onoroff = false; - if (hooksenabled) - DisableHooks(); + if (olddown) + { + if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) + { + } + else { + olddown = false; + ButtonStateImpulse(downtype, false);//release + } } - if (showmessage == 70) { //enabling dll - onoroff = true; - if (!hooksenabled) - EnableHooks(); + else if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) + { + olddown = true; + ButtonStateImpulse(downtype, true);//down } - if (mode != 3) - showmessage = 0; - counter = 0; - } + + } //if mode above 0 + } //if controller + else { + showmessage = 12; } - // if (pointerWindow) { - // ReleaseDC(pointerWindow, PointerWnd); - // } - if (TranslateXtoMKB::rawinputhook == 1) //to make game poll rawinput + + if (TranslateXtoMKB::rawinputhook == 1) { - //need only 1 - ForceRawInputPoll(); //global all processes + } - // showcursorcounter = IsCursorVisible(); - if (tick < scrollenddelay) + if (tick < updatewindowtick) tick++; + else { + Proto::HwndSelector::UpdateMainHwnd(false); + Proto::HwndSelector::UpdateWindowBounds(); + tick = 0; + } if (mode == 0) Sleep(10); if (mode > 0) { - Sleep(1 + responsetime); + Sleep(1); } if (showmessage == 99) Sleep(15); @@ -4048,47 +633,11 @@ namespace ScreenshotInput void TranslateXtoMKB::Initialize(HMODULE hModule) { - + RawInput::Initialize(); g_hModule = hModule; - - std::string iniPath = UGetExecutableFolder() + "\\Xinput.ini"; - std::string iniSettings = "Hooks"; - // controllerID = - //hook settings - //TranslateXtoMKB::clipcursorhook = GetPrivateProfileIntA(iniSettings.c_str(), "ClipCursorHook", 1, iniPath.c_str()); - /// TranslateXtoMKB::getkeystatehook = GetPrivateProfileIntA(iniSettings.c_str(), "GetKeystateHook", 1, iniPath.c_str()); - // TranslateXtoMKB::getasynckeystatehook = GetPrivateProfileIntA(iniSettings.c_str(), "GetAsynckeystateHook", 1, iniPath.c_str()); - // TranslateXtoMKB::getcursorposhook = GetPrivateProfileIntA(iniSettings.c_str(), "GetCursorposHook", 1, iniPath.c_str()); - // TranslateXtoMKB::setcursorposhook = GetPrivateProfileIntA(iniSettings.c_str(), "SetCursorposHook", 1, iniPath.c_str()); - // TranslateXtoMKB::setcursorhook = GetPrivateProfileIntA(iniSettings.c_str(), "SetCursorHook", 1, iniPath.c_str()); - // TranslateXtoMKB::rawinputhook = GetPrivateProfileIntA(iniSettings.c_str(), "RawInputHook", 1, iniPath.c_str()); - // TranslateXtoMKB::GetKeyboardStateHook = GetPrivateProfileIntA(iniSettings.c_str(), "GetKeyboardStateHook", 1, iniPath.c_str()); - setrecthook = GetPrivateProfileIntA(iniSettings.c_str(), "SetRectHook", 0, iniPath.c_str()); - leftrect = GetPrivateProfileIntA(iniSettings.c_str(), "SetRectLeft", 0, iniPath.c_str()); - toprect = GetPrivateProfileIntA(iniSettings.c_str(), "SetRectTop", 0, iniPath.c_str()); - rightrect = GetPrivateProfileIntA(iniSettings.c_str(), "SetRectRight", 800, iniPath.c_str()); - bottomrect = GetPrivateProfileIntA(iniSettings.c_str(), "SetRectBottom", 600, iniPath.c_str()); - // TranslateXtoMKB::registerrawinputhook = GetPrivateProfileIntA(iniSettings.c_str(), "RegisterRawInputHook", 1, iniPath.c_str()); - TranslateXtoMKB::showcursorhook = GetPrivateProfileIntA(iniSettings.c_str(), "ShowCursorHook", 1, iniPath.c_str()); - - // [MessageFilter] - g_filterRawInput = GetPrivateProfileIntA(iniSettings.c_str(), "RawInputFilter", 0, iniPath.c_str()); - g_filterMouseMove = GetPrivateProfileIntA(iniSettings.c_str(), "MouseMoveFilter", 0, iniPath.c_str()); - g_filterMouseActivate = GetPrivateProfileIntA(iniSettings.c_str(), "MouseActivateFilter", 0, iniPath.c_str()); - g_filterWindowActivate = GetPrivateProfileIntA(iniSettings.c_str(), "WindowActivateFilter", 0, iniPath.c_str()); - g_filterWindowActivateApp = GetPrivateProfileIntA(iniSettings.c_str(), "WindowActivateAppFilter", 0, iniPath.c_str()); - g_filterMouseWheel = GetPrivateProfileIntA(iniSettings.c_str(), "MouseWheelFilter", 0, iniPath.c_str()); - g_filterMouseButton = GetPrivateProfileIntA(iniSettings.c_str(), "MouseButtonFilter", 0, iniPath.c_str()); - g_filterKeyboardButton = GetPrivateProfileIntA(iniSettings.c_str(), "KeyboardButtonFilter", 0, iniPath.c_str()); - hwnd = (HWND)Proto::HwndSelector::GetSelectedHwnd(); - - //hook at once or wait for input - hooksoninit = GetPrivateProfileIntA(iniSettings.c_str(), "hooksoninit", 1, iniPath.c_str()); - InitializeCriticalSection(&critical); std::thread one(ThreadFunction, g_hModule); one.detach(); - //CloseHandle(one); return; } } \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h index 8a00493..5b9ce04 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h @@ -11,31 +11,10 @@ namespace ScreenshotInput // static bool usetraqnslation; public: - //static bool TranslateXinputtoMKB; - //static POINT delta; - //static bool LMB; - //static bool RMB; - static HWND pointerWindows; - static int clipcursorhook; static void Initialize(HMODULE g_hModule); static int controllerID; - static int drawfakecursor; - static int getkeystatehook; - static int getasynckeystatehook; - static int getcursorposhook; - static int setcursorposhook; - static int setcursorhook; - static int rawinputhook; - static int GetKeyboardStateHook; + static bool rawinputhook; static bool registerrawinputhook; - static int showcursorhook; - - //void PollLoop(); - //void Sendinput(); - // bool HasGuiStatus() const override { return true; } - // void ShowGuiStatus() override; - // void InstallImpl() override; - // void UninstallImpl() override; }; } \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/dllmain.cpp b/src/ProtoInput/ProtoInputHooks/dllmain.cpp index 2ec94ca..6c67a4c 100644 --- a/src/ProtoInput/ProtoInputHooks/dllmain.cpp +++ b/src/ProtoInput/ProtoInputHooks/dllmain.cpp @@ -46,37 +46,30 @@ DWORD WINAPI StartThread(LPVOID lpParameter) Proto::StartPipeCommunication(); Sleep(50); //let pipe finish + Proto::AddThreadToACL(GetCurrentThreadId()); Proto::RawInput::InitialiseRawInput(); // Useful to add a pause if we need to attach a debugger // MessageBoxW(NULL, L"Press OK to start", L"", MB_OK); - Proto::HwndSelector::UpdateMainHwnd(); Proto::FocusMessageLoop::SetupThread(); - Proto::AddThreadToACL(GetCurrentThreadId()); - - if (!Proto::RawInput::TranslateXinputtoMKB) - { - + Proto::FakeCursor::Initialise(); + + if (Proto::RawInput::TranslateXinputtoMKB) + ScreenshotInput::TranslateXtoMKB::Initialize(dll_hModule); + HANDLE hGuiThread = CreateThread(nullptr, 0, + (LPTHREAD_START_ROUTINE)GuiThread, dll_hModule, CREATE_SUSPENDED, &Proto::GuiThreadID); - Proto::FakeCursor::Initialise(); + ResumeThread(hGuiThread); + if (hGuiThread != nullptr) + CloseHandle(hGuiThread); + std::cout << "Reached end of startup thread\n"; - HANDLE hGuiThread = CreateThread(nullptr, 0, - (LPTHREAD_START_ROUTINE)GuiThread, dll_hModule, CREATE_SUSPENDED, &Proto::GuiThreadID); - - ResumeThread(hGuiThread); - - if (hGuiThread != nullptr) - CloseHandle(hGuiThread); - - std::cout << "Reached end of startup thread\n"; - } - else ScreenshotInput::TranslateXtoMKB::Initialize(dll_hModule); return 0; } From 35c8d019a1d6ad0f4d6f6af9c2b32b3928e5225e Mon Sep 17 00:00:00 2001 From: messenils Date: Sun, 8 Feb 2026 16:05:57 +0100 Subject: [PATCH 05/20] mapping for TranslateXinputtoMKB in UI + fixed some button problems --- .../ProtoInputHooks/PipeCommunication.cpp | 28 + src/ProtoInput/ProtoInputHooks/RawInput.cpp | 21 - .../ProtoInputHooks/TranslateXtoMKB.cpp | 165 +++--- .../ProtoInputHooks/TranslateXtoMKB.h | 20 + .../ProtoInputHooks/pipeinclude/pipeinclude.h | 23 + src/ProtoInput/ProtoInputHost/Gui.cpp | 526 +++++++++++++++++- src/ProtoInput/ProtoInputHost/Profiles.h | 20 + src/ProtoInput/ProtoInputHost/RawInput.cpp | 27 +- src/ProtoInput/ProtoInputHost/RawInput.h | 8 + src/ProtoInput/ProtoInputLoader/Inject.cpp | 35 ++ .../ProtoInputLoader/include/protoloader.h | 3 + 11 files changed, 766 insertions(+), 110 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index cb5fdbc..bdc46d5 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -162,6 +162,34 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) } break; } + case ProtoPipe::PipeMessageType::SetXinputtoMKBkeys: + { + const auto body = reinterpret_cast(messageBuffer); + ScreenshotInput::TranslateXtoMKB::Amapping = body->XinputtoMKBAkey; + ScreenshotInput::TranslateXtoMKB::Bmapping = body->XinputtoMKBBkey; + ScreenshotInput::TranslateXtoMKB::Xmapping = body->XinputtoMKBXkey; + ScreenshotInput::TranslateXtoMKB::Ymapping = body->XinputtoMKBYkey; + ScreenshotInput::TranslateXtoMKB::RSmapping = body->XinputtoMKBRSkey; + ScreenshotInput::TranslateXtoMKB::LSmapping = body->XinputtoMKBLSkey; + ScreenshotInput::TranslateXtoMKB::RSmapping = body->XinputtoMKBRSkey; + + ScreenshotInput::TranslateXtoMKB::rightmapping = body->XinputtoMKBrightkey; + ScreenshotInput::TranslateXtoMKB::leftmapping = body->XinputtoMKBleftkey; + ScreenshotInput::TranslateXtoMKB::upmapping = body->XinputtoMKBupkey; + ScreenshotInput::TranslateXtoMKB::downmapping = body->XinputtoMKBdownkey; + + ScreenshotInput::TranslateXtoMKB::stickRpressmapping = body->XinputtoMKBstickR; + ScreenshotInput::TranslateXtoMKB::stickLpressmapping = body->XinputtoMKBstickL; + ScreenshotInput::TranslateXtoMKB::stickrightmapping = body->XinputtoMKBstickright; + ScreenshotInput::TranslateXtoMKB::stickleftmapping = body->XinputtoMKBstickleft; + ScreenshotInput::TranslateXtoMKB::stickupmapping = body->XinputtoMKBstickup; + ScreenshotInput::TranslateXtoMKB::stickdownmapping = body->XinputtoMKBstickdown; + + ScreenshotInput::TranslateXtoMKB::optionmapping = body->XinputtoMKBoption; + ScreenshotInput::TranslateXtoMKB::startmapping = body->XinputtoMKBstart; + ScreenshotInput::TranslateXtoMKB::lefthanded = body->XinputtoMKBstickinvert; + break; + } case ProtoPipe::PipeMessageType::SetupHook: { const auto body = reinterpret_cast(messageBuffer); diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.cpp b/src/ProtoInput/ProtoInputHooks/RawInput.cpp index 62ac558..ae56c54 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.cpp +++ b/src/ProtoInput/ProtoInputHooks/RawInput.cpp @@ -239,16 +239,6 @@ void RawInput::SendKeyMessage(const RAWKEYBOARD& data, bool pressed) PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYDOWN, MessageFilterHook::IsKeyboardButtonFilterEnabled() ? data.VKey | KeyboardButtonFilter::signature : data.VKey, lparam); - - // if (data.VKey == VK_SHIFT || data.VKey == VK_LSHIFT) - // { - // PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYDOWN, VK_SHIFT, lparam); - // PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYDOWN, VK_LSHIFT, lparam); - // } - // else - // { - // PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYDOWN, data.VKey, lparam); - // } } else { @@ -261,17 +251,6 @@ void RawInput::SendKeyMessage(const RAWKEYBOARD& data, bool pressed) PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYUP, MessageFilterHook::IsKeyboardButtonFilterEnabled() ? data.VKey | KeyboardButtonFilter::signature : data.VKey, lparam); - - // if (data.VKey == VK_SHIFT || data.VKey == VK_LSHIFT) - // { - // PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYUP, VK_SHIFT, lparam); - // PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYUP, VK_LSHIFT, lparam); - // } - // else - // { - // PostMessageW((HWND)HwndSelector::GetSelectedHwnd(), WM_KEYUP, data.VKey, lparam); - // } - } } } diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp index 2e6fc8a..51f5041 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -40,6 +40,31 @@ namespace ScreenshotInput { + //from tunnell + int TranslateXtoMKB::controllerID; + bool TranslateXtoMKB::rawinputhook; //registerrawinputhook + bool TranslateXtoMKB::registerrawinputhook; //registerrawinputhook + + int TranslateXtoMKB::Amapping; + int TranslateXtoMKB::Bmapping; + int TranslateXtoMKB::Xmapping; + int TranslateXtoMKB::Ymapping; + int TranslateXtoMKB::RSmapping; + int TranslateXtoMKB::LSmapping; + int TranslateXtoMKB::rightmapping; + int TranslateXtoMKB::leftmapping; + int TranslateXtoMKB::upmapping; + int TranslateXtoMKB::downmapping; + int TranslateXtoMKB::stickRpressmapping; + int TranslateXtoMKB::stickLpressmapping; + int TranslateXtoMKB::stickrightmapping; + int TranslateXtoMKB::stickleftmapping; + int TranslateXtoMKB::stickupmapping; + int TranslateXtoMKB::stickdownmapping; + int TranslateXtoMKB::optionmapping; + int TranslateXtoMKB::startmapping; + bool TranslateXtoMKB::lefthanded; + int updatewindowtick = 300; int mode = 1; int AxisLeftsens; @@ -54,43 +79,7 @@ namespace ScreenshotInput const float curve_exponent = 5.00f; // The exponential portion of the curve (1.0 to 10.0) float sensitivity = 12.00f; // Base sensitivity / max speed (1.0 to 30.0) float accel_multiplier = 1.90f; // Look Acceleration Multiplier (1.0 to 3.0) - struct KeyMapEntry { - WORD makeCode; - WORD vKey; - }; - - static const std::unordered_map keyMap = { - { 1, { 0x11, 0x57 } }, // W - { 2, { 0x1C, VK_RETURN } }, // Enter - { 3, { 0x4B, VK_LEFT } }, // Left Arrow - { 4, { 0x01, VK_ESCAPE } }, // Escape - { 5, { 0x1E, 0x57 } }, // A - { 6, { 0x1F, 0x57 } }, // S - { 7, { 0x20, 0x57 } }, // D - { 8, { 0x4D, VK_RIGHT } }, // Right Arrow - { 9, { 0x48, VK_UP } }, // Up Arrow - { 10, { 0x50, VK_DOWN } }, // Down Arrow - { 11, { 0x39, VK_SPACE } }, // Space - { 12, { 0x0E, VK_BACK } }, // Backspace - { 13, { 0x0F, VK_TAB } }, // Tab - { 14, { 0x2A, VK_LSHIFT } }, // Left Shift - { 15, { 0x1D, VK_LCONTROL} }, // Left Ctrl - { 16, { 0x38, VK_LMENU } }, // Left Alt - { 17, { 0x13, 0x52} }, // R - - }; - int Atype = 1; - int Btype = 2; - int Xtype = 17; - int Ytype = 11; - int Ctype = 2; - int Dtype = 4; - // int Etype = 7; - /// int Ftype = 8; - int uptype = 9; - int downtype = 10; - int Lefttype = 3; - int righttype = 8; + ///////////////// bool movedmouse; bool leftPressedold = false; @@ -113,9 +102,7 @@ namespace ScreenshotInput //fake cursor - int TranslateXtoMKB::controllerID; - bool TranslateXtoMKB::rawinputhook; //registerrawinputhook - bool TranslateXtoMKB::registerrawinputhook; //registerrawinputhook + int Xf = 0; int Yf = 0; @@ -124,7 +111,6 @@ namespace ScreenshotInput bool rawmouseWu = false; bool rawmouseWd = false; - int righthanded = 0; bool oldA = false; bool oldB = false; bool oldX = false; @@ -187,31 +173,40 @@ namespace ScreenshotInput Proto::RawInput::SendInputMessages(muusjn); return true; } - void ButtonStateImpulse(int button, bool state) - { - RAWKEYBOARD data{}; - data.Reserved = 0; - data.ExtraInformation = 0; - if (state) - { - data.Flags = RI_KEY_MAKE; - data.Message = WM_KEYDOWN; - } - else - { - data.Flags = RI_KEY_BREAK; - data.Message = WM_KEYUP; - } - auto it = keyMap.find(button); - if (it != keyMap.end()) + void ButtonStateImpulse(int vk, bool state) { - data.MakeCode = it->second.makeCode; - data.VKey = it->second.vKey; - Proto::RawInput::SendKeyMessage(data, state); - RawInput::GenerateRawKey(data.VKey, state, false); - } - else MessageBoxA(NULL, "Invalid button mapping", "Error", MB_OK | MB_ICONERROR); + RAWKEYBOARD data{}; + data.MakeCode = MapVirtualKey(vk, MAPVK_VK_TO_VSC); + data.VKey = vk; + data.ExtraInformation = 0; + + data.Flags = state ? 0 : RI_KEY_BREAK; + data.Message = state ? WM_KEYDOWN : WM_KEYUP; + + // Extended key? + switch (vk) + { + case VK_LEFT: + case VK_RIGHT: + case VK_UP: + case VK_DOWN: + case VK_INSERT: + case VK_DELETE: + case VK_HOME: + case VK_END: + case VK_PRIOR: + case VK_NEXT: + case VK_RCONTROL: + case VK_RMENU: + case VK_DIVIDE: + case VK_NUMLOCK: + data.Flags |= RI_KEY_E0; + break; + } + Proto::FakeMouseKeyboard::ReceivedKeyPressOrRelease(vk, state); + Proto::RawInput::SendKeyMessage(data, state); + RawInput::GenerateRawKey(vk, state, false); } std::string UGetExecutableFolder() { @@ -362,7 +357,7 @@ namespace ScreenshotInput bool leftPressed = IsTriggerPressed(state.Gamepad.bLeftTrigger); bool rightPressed = IsTriggerPressed(state.Gamepad.bRightTrigger); - if (righthanded == 1) { + if (TranslateXtoMKB::lefthanded == 1) { Xaxis = state.Gamepad.sThumbRX; Yaxis = state.Gamepad.sThumbRY; scrollXaxis = state.Gamepad.sThumbLX; @@ -440,13 +435,13 @@ namespace ScreenshotInput } else{ oldA = false; - ButtonStateImpulse(Atype, false);//release + ButtonStateImpulse(TranslateXtoMKB::Amapping, false);//release } } else if (buttons & XINPUT_GAMEPAD_A) { oldA = true; - ButtonStateImpulse(Atype, true);//down + ButtonStateImpulse(TranslateXtoMKB::Amapping, true);//down } @@ -457,13 +452,13 @@ namespace ScreenshotInput } else { oldB = false; - ButtonStateImpulse(Btype, false);//release + ButtonStateImpulse(TranslateXtoMKB::Bmapping, false);//release } } else if (buttons & XINPUT_GAMEPAD_B) { oldB = true; - ButtonStateImpulse(Btype, true);//down + ButtonStateImpulse(TranslateXtoMKB::Bmapping, true);//down } @@ -474,13 +469,13 @@ namespace ScreenshotInput } else { oldX = false; - ButtonStateImpulse(Xtype, false);//release + ButtonStateImpulse(TranslateXtoMKB::Xmapping, false);//release } } else if (buttons & XINPUT_GAMEPAD_X) { oldX = true; - ButtonStateImpulse(Xtype, true);//down + ButtonStateImpulse(TranslateXtoMKB::Xmapping, true);//down } @@ -491,13 +486,13 @@ namespace ScreenshotInput } else { oldY = false; - ButtonStateImpulse(Ytype, false);//release + ButtonStateImpulse(TranslateXtoMKB::Ymapping, false);//release } } else if (buttons & XINPUT_GAMEPAD_Y) { oldY = true; - ButtonStateImpulse(Ytype, true);//down + ButtonStateImpulse(TranslateXtoMKB::Ymapping, true);//down } @@ -508,13 +503,13 @@ namespace ScreenshotInput } else { oldC = false; - ButtonStateImpulse(Ctype, false); //release + ButtonStateImpulse(TranslateXtoMKB::RSmapping, false); //release } } else if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) { oldC = true; - ButtonStateImpulse(Ctype, true); //down + ButtonStateImpulse(TranslateXtoMKB::RSmapping, true); //down } @@ -525,13 +520,13 @@ namespace ScreenshotInput } else { oldD = false; - ButtonStateImpulse(Ctype, false);//release + ButtonStateImpulse(TranslateXtoMKB::LSmapping, false);//release } } else if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) { oldD = true; - ButtonStateImpulse(Ctype, true);//down + ButtonStateImpulse(TranslateXtoMKB::LSmapping, true);//down } @@ -542,13 +537,13 @@ namespace ScreenshotInput } else { oldleft = false; - ButtonStateImpulse(Lefttype, false); //release + ButtonStateImpulse(TranslateXtoMKB::leftmapping, false); //release } } else if (buttons & XINPUT_GAMEPAD_DPAD_LEFT) { oldleft = true; - ButtonStateImpulse(Lefttype, true);//down + ButtonStateImpulse(TranslateXtoMKB::leftmapping, true);//down } @@ -559,13 +554,13 @@ namespace ScreenshotInput } else { oldright = false; - ButtonStateImpulse(righttype, false);//release + ButtonStateImpulse(TranslateXtoMKB::rightmapping, false);//release } } else if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) { oldright = true; - ButtonStateImpulse(righttype, true);//down + ButtonStateImpulse(TranslateXtoMKB::rightmapping, true);//down } @@ -576,13 +571,13 @@ namespace ScreenshotInput } else { oldup = false; - ButtonStateImpulse(uptype, false);//release + ButtonStateImpulse(TranslateXtoMKB::upmapping, false);//release } } else if (buttons & XINPUT_GAMEPAD_DPAD_UP) { oldup = true; - ButtonStateImpulse(uptype, true);//down + ButtonStateImpulse(TranslateXtoMKB::upmapping, true);//down } @@ -593,13 +588,13 @@ namespace ScreenshotInput } else { olddown = false; - ButtonStateImpulse(downtype, false);//release + ButtonStateImpulse(TranslateXtoMKB::downmapping, false);//release } } else if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) { olddown = true; - ButtonStateImpulse(downtype, true);//down + ButtonStateImpulse(TranslateXtoMKB::downmapping, true);//down } } //if mode above 0 diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h index 5b9ce04..59de6ca 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h @@ -15,6 +15,26 @@ namespace ScreenshotInput static int controllerID; static bool rawinputhook; static bool registerrawinputhook; + + static int Amapping; + static int Bmapping; + static int Xmapping; + static int Ymapping; + static int RSmapping; + static int LSmapping; + static int rightmapping; + static int leftmapping; + static int upmapping; + static int downmapping; + static int stickRpressmapping; + static int stickLpressmapping; + static int stickrightmapping; + static int stickleftmapping; + static int stickupmapping; + static int stickdownmapping; + static int optionmapping; + static int startmapping; + static bool lefthanded; }; } \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h index 6ca78a4..5668f44 100644 --- a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h +++ b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h @@ -9,6 +9,7 @@ enum class PipeMessageType { AddSelectedMouseOrKeyboard, SetTranslateXinputtoMKB, + SetXinputtoMKBkeys, SetupHook, WakeUpProcess, SetupMessageFilter, @@ -61,6 +62,28 @@ struct PipeMessageSetTranslateXinputtoMKB { bool TranslateXinputtoMKB; }; +struct PipeMessageSetXinputtoMKBkeys +{ + int XinputtoMKBAkey; + int XinputtoMKBBkey; + int XinputtoMKBXkey; + int XinputtoMKBYkey; + int XinputtoMKBRSkey; + int XinputtoMKBLSkey; + int XinputtoMKBrightkey; + int XinputtoMKBleftkey; + int XinputtoMKBupkey; + int XinputtoMKBdownkey; + int XinputtoMKBstickR; + int XinputtoMKBstickL; + int XinputtoMKBstickright; +int XinputtoMKBstickleft; + int XinputtoMKBstickup; + int XinputtoMKBstickdown; + int XinputtoMKBoption; + int XinputtoMKBstart; + bool XinputtoMKBstickinvert; +}; struct PipeMessageSetupHook { diff --git a/src/ProtoInput/ProtoInputHost/Gui.cpp b/src/ProtoInput/ProtoInputHost/Gui.cpp index 5e727e5..8c20a67 100644 --- a/src/ProtoInput/ProtoInputHost/Gui.cpp +++ b/src/ProtoInput/ProtoInputHost/Gui.cpp @@ -52,6 +52,39 @@ StartupInjectionType selectedStartupInjectionType = StartupInjectionType::EASYHO std::vector trackedInstanceHandles{}; static bool isInputCurrentlyLocked = false; +std::string VkToKeyName(int vk) +{ + + UINT scan = MapVirtualKey(vk, MAPVK_VK_TO_VSC); + UINT flags = scan << 16; + + // Add extended-key flag when needed + switch (vk) + { + case VK_LEFT: + case VK_RIGHT: + case VK_UP: + case VK_DOWN: + case VK_INSERT: + case VK_DELETE: + case VK_HOME: + case VK_END: + case VK_PRIOR: // Page Up + case VK_NEXT: // Page Down + case VK_RCONTROL: + case VK_RMENU: // Right Alt + case VK_DIVIDE: + case VK_NUMLOCK: + flags |= (1 << 24); + break; + } + + char name[64] = { 0 }; + GetKeyNameTextA(flags, name, sizeof(name)); + return std::string(name); +} + + void OnInputLockChange(bool locked) { isInputCurrentlyLocked = locked; @@ -140,6 +173,11 @@ bool Launch() if (instance.keyboardHandle != -1) AddSelectedKeyboardHandle(instanceHandle, instance.keyboardHandle); SetTranslateXinputtoMKB(instanceHandle, currentProfile.TranslateXinputtoMKB); + //keys + SetXinputtoMKBkeys(instanceHandle, currentProfile.XinputtoMKBAkey, currentProfile.XinputtoMKBBkey, currentProfile.XinputtoMKBXkey, currentProfile.XinputtoMKBYkey, currentProfile.XinputtoMKBRSkey, currentProfile.XinputtoMKBLSkey, currentProfile.XinputtoMKBrightkey, currentProfile.XinputtoMKBleftkey, currentProfile.XinputtoMKBupkey, currentProfile.XinputtoMKBdownkey, + currentProfile.XinputtoMKBstickR, currentProfile.XinputtoMKBstickL, currentProfile.XinputtoMKBstickright, currentProfile.XinputtoMKBstickleft, currentProfile.XinputtoMKBstickup, currentProfile.XinputtoMKBstickdown, + currentProfile.XinputtoMKBoption, currentProfile.XinputtoMKBstart, currentProfile.XinputtoMKBstickinvert); + if (hookEnabled(RegisterRawInputHookID)) InstallHook(instanceHandle, RegisterRawInputHookID); if (hookEnabled(GetRawInputDataHookID)) InstallHook(instanceHandle, GetRawInputDataHookID); if (hookEnabled(MessageFilterHookID)) InstallHook(instanceHandle, MessageFilterHookID); @@ -676,13 +714,495 @@ void SelectedInstanceWindow() ImGui::Separator(); ImGui::SliderInt("", (int*)&instance.controllerIndex, 0, 16, "%d", ImGuiSliderFlags_AlwaysClamp); ImGui::Separator(); + ImGui::Spacing(); ImGui::TextWrapped("Controller index"); ImGui::Separator(); + ImGui::Spacing(); + ImGui::Checkbox("Use OpenXinput", ¤tProfile.useOpenXinput); // + ImGui::Separator(); + ImGui::TextWrapped("If Translate X to MKB is selected, then it will emulate mouse and keyboard from selected ControllerIndex." + "Option will automatically deactivate if a keyboard or mouse is selected for the instance. " + "Also you should make sure ControllerIndex is not zero, as zero still implies no controller" + "UseOpenXinput hook or Xinput hook are not needed, as it will use OpenXinput already and poll selected controllerindex" + ""); ImGui::Checkbox("Translate X to MKB", ¤tProfile.TranslateXinputtoMKB); // ImGui::Separator(); - ImGui::Checkbox("Use OpenXinput", ¤tProfile.useOpenXinput); // - - + ImGui::Spacing(); + ImGui::Spacing(); + ImGui::TextWrapped("Options and mappings for Xinput controller if Translate X to MKB is enabled." + "Option will automatically deactivate if a keyboard or mouse is selected for the instance. " + ""); + // A key + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBAkey); + ImGui::TextWrapped("A is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressA = false; + + if (waitingKeyPressA) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##A"); //these need unique IDs or text + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressA = false; + currentProfile.XinputtoMKBAkey = lastVKcode; + } + } + else if (ImGui::Button("Click to change##A1"))//these need unique IDs or text + { + waitingKeyPressA = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + // B key + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBBkey); + ImGui::TextWrapped("B is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressB = false; + + if (waitingKeyPressB) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##B"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressB = false; + currentProfile.XinputtoMKBBkey = lastVKcode; + } + } + else if (ImGui::Button("Click to change##B1")) + { + waitingKeyPressB = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + // X key + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBXkey); + ImGui::TextWrapped("X is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressX = false; + + if (waitingKeyPressX) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##C"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressX = false; + currentProfile.XinputtoMKBXkey = lastVKcode; + } + } + else if (ImGui::Button("Click to change##C1")) + { + waitingKeyPressX = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + // Y key + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBYkey); + ImGui::TextWrapped("Y is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressY = false; + + if (waitingKeyPressY) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##D1"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressY = false; + currentProfile.XinputtoMKBYkey = lastVKcode; + } + } + else if (ImGui::Button("Click to change##D1")) + { + waitingKeyPressY = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + // RS key + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBRSkey); + ImGui::TextWrapped("Right Shoulder is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressRS = false; + + if (waitingKeyPressRS) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##E"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressRS = false; + currentProfile.XinputtoMKBRSkey = lastVKcode; + } + } + else if (ImGui::Button("Click to change##E1")) + { + waitingKeyPressRS = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + // LS key + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBLSkey); + ImGui::TextWrapped("Left Shoulder is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressLS = false; + + if (waitingKeyPressLS) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##F"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressLS = false; + currentProfile.XinputtoMKBLSkey = lastVKcode; + } + } + else if (ImGui::Button("Click to change##F1")) + { + waitingKeyPressLS = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///right + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBrightkey); + ImGui::TextWrapped("right is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressright = false; + + if (waitingKeyPressright) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##G"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressright = false; + currentProfile.XinputtoMKBrightkey = lastVKcode; + } + } + else if (ImGui::Button("Click to change##G1")) + { + waitingKeyPressright = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///left + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBleftkey); + ImGui::TextWrapped("left is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressleft = false; + + if (waitingKeyPressleft) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##H"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressleft = false; + currentProfile.XinputtoMKBleftkey = lastVKcode; + } + } + else if (ImGui::Button("Click to change##H1")) + { + waitingKeyPressleft = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///up + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBupkey); + ImGui::TextWrapped("up is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressup = false; + + if (waitingKeyPressup) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##I"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressup = false; + currentProfile.XinputtoMKBupkey = lastVKcode; + } + } + else if (ImGui::Button("Click to change##I1")) + { + waitingKeyPressup = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///down + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBdownkey); + ImGui::TextWrapped("down is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressdown = false; + + if (waitingKeyPressdown) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##J"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressdown = false; + currentProfile.XinputtoMKBdownkey = lastVKcode; + } + } + else if (ImGui::Button("Click to change##J2")) + { + waitingKeyPressdown = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///right stick press + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBstickR); + ImGui::TextWrapped("Right Stick Press is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressstickR = false; + + if (waitingKeyPressstickR) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##K"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressstickR = false; + currentProfile.XinputtoMKBstickR = lastVKcode; + } + } + else if (ImGui::Button("Click to change##K1")) + { + waitingKeyPressstickR = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///left stick press + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBstickL); + ImGui::TextWrapped("Left Stick Press is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressstickL = false; + + if (waitingKeyPressstickL) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##L"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressstickL = false; + currentProfile.XinputtoMKBstickL = lastVKcode; + } + } + else if (ImGui::Button("Click to change##L1")) + { + waitingKeyPressstickL = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///stick move right + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBstickright); + ImGui::TextWrapped("stick move right is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressstickright = false; + + if (waitingKeyPressstickright) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##M2"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressstickright = false; + currentProfile.XinputtoMKBstickright = lastVKcode; + } + } + else if (ImGui::Button("Click to change##M")) + { + waitingKeyPressstickright = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///stick move left + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBstickleft); + ImGui::TextWrapped("stick move left is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressstickleft = false; + + if (waitingKeyPressstickleft) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##N"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressstickleft = false; + currentProfile.XinputtoMKBstickleft = lastVKcode; + } + } + else if (ImGui::Button("Click to change##N1")) + { + waitingKeyPressstickleft = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///stick move up + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBstickup); + ImGui::TextWrapped("stick move up is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressstickup = false; + + if (waitingKeyPressstickup) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##O"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressstickup = false; + currentProfile.XinputtoMKBstickup = lastVKcode; + } + } + else if (ImGui::Button("Click to change##O1")) + { + waitingKeyPressstickup = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///stick move up + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBstickdown); + ImGui::TextWrapped("stick move Down is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressstickdown = false; + + if (waitingKeyPressstickdown) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##P"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressstickdown = false; + currentProfile.XinputtoMKBstickdown = lastVKcode; + } + } + else if (ImGui::Button("Click to change##P1")) + { + waitingKeyPressstickdown = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///start button + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBstart); + ImGui::TextWrapped("Start button is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressstart = false; + + if (waitingKeyPressstart) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##Q"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressstart = false; + currentProfile.XinputtoMKBstart = lastVKcode; + } + } + else if (ImGui::Button("Click to change##Q1")) + { + waitingKeyPressstart = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ///option button + { + const auto XAString = VkToKeyName(currentProfile.XinputtoMKBoption); + ImGui::TextWrapped("option button is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressoption = false; + + if (waitingKeyPressoption) + { + PushDisabled(); + ImGui::Button("Press Keyboard button...##R"); + PopDisabled(); + + if (lastVKcode != -1) + { + waitingKeyPressoption = false; + currentProfile.XinputtoMKBoption = lastVKcode; + } + } + else if (ImGui::Button("Click to change##R2")) + { + waitingKeyPressoption = true; + lastVKcode = -1; + } + } + ImGui::Separator(); + ImGui::Checkbox("Lefthanded Stick. moves mouse with left stick and button map on right stick. or opposite if disabled", ¤tProfile.XinputtoMKBstickinvert); // + ImGui::Separator(); + ImGui::PopID(); } diff --git a/src/ProtoInput/ProtoInputHost/Profiles.h b/src/ProtoInput/ProtoInputHost/Profiles.h index a3a4f26..17327ea 100644 --- a/src/ProtoInput/ProtoInputHost/Profiles.h +++ b/src/ProtoInput/ProtoInputHost/Profiles.h @@ -74,6 +74,26 @@ struct Profile bool useOpenXinput = false; bool TranslateXinputtoMKB = false; + int XinputtoMKBAkey = 0x52; //R + int XinputtoMKBBkey = 0x47; //G + int XinputtoMKBXkey = 0x45; //E + int XinputtoMKBYkey = 0x43; //C + int XinputtoMKBRSkey = 0x10; + int XinputtoMKBLSkey = 0x20; + int XinputtoMKBrightkey = 0x27; + int XinputtoMKBleftkey = 0x25; + int XinputtoMKBupkey = 0x26; + int XinputtoMKBdownkey = 0x28; + int XinputtoMKBstickR = 0x5A; //Z + int XinputtoMKBstickL = 0x4D; //M + int XinputtoMKBstickright = 0x41; //A + int XinputtoMKBstickleft = 0x44; //D + int XinputtoMKBstickup = 0x57; //W + int XinputtoMKBstickdown = 0x53; //S + int XinputtoMKBoption = 0x1B; // + int XinputtoMKBstart = 0x0D; + bool XinputtoMKBstickinvert = false; + bool useFakeClipCursor = true; bool showCursorWhenImageUpdated = false; diff --git a/src/ProtoInput/ProtoInputHost/RawInput.cpp b/src/ProtoInput/ProtoInputHost/RawInput.cpp index ebcdc68..34f8285 100644 --- a/src/ProtoInput/ProtoInputHost/RawInput.cpp +++ b/src/ProtoInput/ProtoInputHost/RawInput.cpp @@ -13,6 +13,13 @@ namespace ProtoHost intptr_t lastKeypressKeyboardHandle = -1; intptr_t lastMouseClicked = -1; +int lastVKcode = 0; +//int Akey = 0x57; //wasd +//int Bkey = 0x53; +//int Xkey = 0x41; +//int Ykey = 0x44; +//int RSkey = VK_RETURN; +//int LSkey = VK_SPACE; bool lockInputWithTheEndKey = true; bool lockInputSuspendsExplorer = true; bool freezeGameInputWhileInputNotLocked = true; @@ -22,6 +29,8 @@ HWND rawInputHwnd; std::vector keyboardHandles{}; std::vector mouseHandles{}; + + void ProcessRawInput(HRAWINPUT rawInputHandle) { RAWINPUT rawinput; @@ -37,10 +46,26 @@ void ProcessRawInput(HRAWINPUT rawInputHandle) return; if (rawinput.header.dwType == RIM_TYPEKEYBOARD && - rawinput.data.keyboard.Flags == RI_KEY_MAKE) + (rawinput.data.keyboard.Flags & RI_KEY_BREAK) == 0) // key down { + USHORT vkey = rawinput.data.keyboard.VKey; + //if (vkey == VK_LEFT) + // MessageBoxA(nullptr, "E0 key detected", "Info", MB_OK); + // If VKey is missing or invalid, reconstruct it + //if (vkey == 0 || vkey == 255) + //{ + // if ((rawinput.data.keyboard.Flags & RI_KEY_E0) != 0) + // { + // vkey = MapVirtualKey(rawinput.data.keyboard.MakeCode, MAPVK_VSC_TO_VK_EX); + + // } + // else + // vkey = MapVirtualKey(rawinput.data.keyboard.MakeCode, MAPVK_VSC_TO_VK); + //} + lastVKcode = vkey; lastKeypressKeyboardHandle = (intptr_t)rawinput.header.hDevice; } + else if (rawinput.header.dwType == RIM_TYPEMOUSE && rawinput.data.mouse.usButtonFlags != 0) { diff --git a/src/ProtoInput/ProtoInputHost/RawInput.h b/src/ProtoInput/ProtoInputHost/RawInput.h index 1be5a76..0667f91 100644 --- a/src/ProtoInput/ProtoInputHost/RawInput.h +++ b/src/ProtoInput/ProtoInputHost/RawInput.h @@ -10,6 +10,14 @@ extern HWND rawInputHwnd; extern intptr_t lastKeypressKeyboardHandle; extern intptr_t lastMouseClicked; +extern int lastVKcode; +//extern int Akey; +//extern int Bkey; +//extern int Xkey; +//extern int Ykey; +//extern int RSkey; +//extern int LSkey; + extern bool lockInputWithTheEndKey; extern bool lockInputSuspendsExplorer; extern bool freezeGameInputWhileInputNotLocked; diff --git a/src/ProtoInput/ProtoInputLoader/Inject.cpp b/src/ProtoInput/ProtoInputLoader/Inject.cpp index 89bd676..def9a88 100644 --- a/src/ProtoInput/ProtoInputLoader/Inject.cpp +++ b/src/ProtoInput/ProtoInputLoader/Inject.cpp @@ -88,6 +88,41 @@ void SetTranslateXinputtoMKB(ProtoInstanceHandle instanceHandle, bool TranslateX ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetTranslateXinputtoMKB, &message); } } +void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright,int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, bool XinputtoMKBstickinvert) +{ + if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) + { + auto& instance = find->second; + + WaitClientConnect(instance); + + ProtoPipe::PipeMessageSetXinputtoMKBkeys message + { + XinputtoMKBAkey, + XinputtoMKBBkey, + XinputtoMKBXkey, + XinputtoMKBYkey, + XinputtoMKBRSkey, + XinputtoMKBLSkey, + XinputtoMKBrightkey, + XinputtoMKBleftkey, + XinputtoMKBupkey, + XinputtoMKBdownkey, + XinputtoMKBstickR, + XinputtoMKBstickL, + XinputtoMKBstickright, + XinputtoMKBstickleft, + XinputtoMKBstickup, + XinputtoMKBstickdown, + XinputtoMKBoption, + XinputtoMKBstart, + XinputtoMKBstickinvert + + }; + + ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetXinputtoMKBkeys, &message); + } +} extern "C" __declspec(dllexport) void StartFocusMessageLoop(ProtoInstanceHandle instanceHandle, int milliseconds, diff --git a/src/ProtoInput/ProtoInputLoader/include/protoloader.h b/src/ProtoInput/ProtoInputLoader/include/protoloader.h index cf5daa2..833f936 100644 --- a/src/ProtoInput/ProtoInputLoader/include/protoloader.h +++ b/src/ProtoInput/ProtoInputLoader/include/protoloader.h @@ -59,6 +59,9 @@ extern "C" __declspec(dllexport) ProtoInstanceHandle EasyHookInjectStartup( extern "C" __declspec(dllexport) void AddSelectedMouseHandle(ProtoInstanceHandle instanceHandle, unsigned int mouseHandle); extern "C" __declspec(dllexport) void AddSelectedKeyboardHandle(ProtoInstanceHandle instanceHandle, unsigned int keyboardHandle); extern "C" __declspec(dllexport) void SetTranslateXinputtoMKB(ProtoInstanceHandle instanceHandle, bool TranslateXinputtoMKB); + +extern "C" __declspec(dllexport) void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright, int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, bool XinputtoMKBstickinvert); + extern "C" __declspec(dllexport) void InstallHook(ProtoInstanceHandle instanceHandle, ProtoHookIDs hookID); extern "C" __declspec(dllexport) void UninstallHook(ProtoInstanceHandle instanceHandle, ProtoHookIDs hookID); From 08c58faff8f7e28440baafa1bc905f84f58f3773 Mon Sep 17 00:00:00 2001 From: messenils Date: Mon, 9 Feb 2026 22:16:33 +0100 Subject: [PATCH 06/20] Integrated coordinate scanning in the XinputtoMKB option --- src/ProtoInput/ProtoInputHooks/FakeCursor.cpp | 140 ++ .../ProtoInputHooks/GetRawInputDataHook.cpp | 16 +- .../ProtoInputHooks/GetRawInputDataHook.h | 2 +- .../ProtoInputHooks/GtoMnK_RawInput.cpp | 9 +- .../ProtoInputHooks/GtoMnK_RawInput.h | 1 + .../ProtoInputHooks/GtoMnK_RawInputHooks.cpp | 30 +- .../ProtoInputHooks/GtoMnK_RawInputHooks.h | 6 +- src/ProtoInput/ProtoInputHooks/Gui.cpp | 623 +++++++- .../ProtoInputHooks/HookManager.cpp | 12 +- .../ProtoInputHooks/PipeCommunication.cpp | 5 +- .../ProtoInputHooks/ProtoInputHooks.vcxproj | 2 + .../ProtoInputHooks.vcxproj.filters | 6 + src/ProtoInput/ProtoInputHooks/RawInput.cpp | 41 +- src/ProtoInput/ProtoInputHooks/RawInput.h | 5 +- .../ProtoInputHooks/RegisterRawInputHook.cpp | 12 +- src/ProtoInput/ProtoInputHooks/ScanThread.cpp | 1273 +++++++++++++++++ src/ProtoInput/ProtoInputHooks/ScanThread.h | 28 + .../ProtoInputHooks/TranslateXtoMKB.cpp | 268 +++- .../ProtoInputHooks/TranslateXtoMKB.h | 4 +- src/ProtoInput/ProtoInputHost/Gui.cpp | 16 +- src/ProtoInput/ProtoInputHost/Profiles.h | 2 +- src/ProtoInput/ProtoInputHost/RawInput.cpp | 13 - 22 files changed, 2383 insertions(+), 131 deletions(-) create mode 100644 src/ProtoInput/ProtoInputHooks/ScanThread.cpp create mode 100644 src/ProtoInput/ProtoInputHooks/ScanThread.h diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp index 63b76e0..3f4e693 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp @@ -3,6 +3,8 @@ #include "InstallHooks.h" #include "FakeMouseKeyboard.h" #include "HwndSelector.h" +#include "ScanThread.h" +#include "TranslateXtoMKB.h" #include namespace Proto @@ -10,6 +12,11 @@ namespace Proto FakeCursor FakeCursor::state{}; +//TranslateXtoMKB +POINT OldspotA, OldspotB, OldspotX, OldspotY; +int showmessage = 0; +bool erasemessage = false; + LRESULT WINAPI FakeCursorWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) @@ -40,6 +47,127 @@ BOOL CALLBACK EnumWindowsProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMoni } return true; } +void DrawRedX(HDC hdc, int x, int y) //blue +{ + HPEN hPen = CreatePen(PS_SOLID, 3, RGB(0, 0, 255)); + HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); + + MoveToEx(hdc, x - 15, y - 15, NULL); + LineTo(hdc, x + 15, y + 15); + + MoveToEx(hdc, x + 15, y - 15, NULL); + LineTo(hdc, x - 15, y + 15); + + SelectObject(hdc, hOldPen); + DeleteObject(hPen); + return; +} +void DrawBlueCircle(HDC hdc, int x, int y) //red +{ + // Create a NULL brush (hollow fill) + HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH); + HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); + + HPEN hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0)); + HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); + + Ellipse(hdc, x - 15, y - 15, x + 15, y + 15); + + SelectObject(hdc, hOldBrush); + SelectObject(hdc, hOldPen); + DeleteObject(hPen); +} +void DrawGreenTriangle(HDC hdc, int x, int y) +{ + // Use a NULL brush for hollow + HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH); + HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); + + HPEN hPen = CreatePen(PS_SOLID, 3, RGB(0, 255, 0)); + HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); + + POINT pts[3]; + pts[0].x = x; pts[0].y = y - 10; // top center + pts[1].x = x - 10; pts[1].y = y + 10; // bottom left + pts[2].x = x + 10; pts[2].y = y + 10; // bottom right + + Polygon(hdc, pts, 3); + + SelectObject(hdc, hOldBrush); + SelectObject(hdc, hOldPen); + DeleteObject(hPen); +} + +void DrawPinkSquare(HDC hdc, int x, int y) +{ + // Create a NULL brush (hollow fill) + HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH); + HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); + + HPEN hPen = CreatePen(PS_SOLID, 3, RGB(255, 192, 203)); + HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); + + // Draw hollow rectangle (square) 20x20 + Rectangle(hdc, x - 15, y - 15, x + 15, y + 15); + + SelectObject(hdc, hOldBrush); + SelectObject(hdc, hOldPen); + DeleteObject(hPen); +} +void DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, POINT spotY, HBRUSH Brush) +{ + + bool erased = false; + if (OldspotA.x != spotA.x || OldspotA.y != spotA.y) + { + RECT fill{ OldspotA.x - 20, OldspotA.y - 20, OldspotA.x + 20, OldspotA.y + 20 }; + FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! + erased = true; + } + if (OldspotB.x != spotB.x || OldspotB.y != spotB.y) + { + RECT fill{ OldspotB.x - 20, OldspotB.y - 20, OldspotB.x + 20, OldspotB.y + 20 }; + FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! + erased = true; + } + if (OldspotX.x != spotX.x || OldspotX.y != spotX.y) + { + RECT fill{ OldspotX.x - 20, OldspotX.y - 20, OldspotX.x + 20, OldspotX.y + 20 }; + FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! + erased = true; + } + if (OldspotY.x != spotY.x || OldspotY.y != spotY.y) + { + RECT fill{ OldspotY.x - 20, OldspotY.y - 20, OldspotY.x + 20, OldspotY.y + 20 }; + FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! + erased = true; + } + if (spotA.x != 0 && spotA.y != 0 && erased == true) + { + ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &spotA); + DrawRedX(hdc, spotA.x, spotA.y); + } + if (spotB.x != 0 && spotB.y != 0 && erased == true) + { + ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &spotB); + DrawBlueCircle(hdc, spotB.x, spotB.y); + } + if (spotX.x != 0 && spotX.y != 0 && erased == true) + { + ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &spotX); + DrawGreenTriangle(hdc, spotX.x, spotX.y); + } + if (spotY.x != 0 && spotY.y != 0 && erased == true) + { + ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &spotY); + DrawPinkSquare(hdc, spotY.x, spotY.y); + } + + OldspotA = spotA; + OldspotB = spotB; + OldspotX = spotX; + OldspotY = spotY; +} void FakeCursor::DrawCursor() { @@ -49,7 +177,19 @@ void FakeCursor::DrawCursor() FillRect(hdc, &fill, transparencyBrush); // Note: window, not screen coordinates! } + if (ScreenshotInput::ScanThread::scanoption == 1) + { + EnterCriticalSection(&ScreenshotInput::ScanThread::critical); + showmessage = ScreenshotInput::TranslateXtoMKB::showmessage; + POINT Apos = { ScreenshotInput::ScanThread::PointA.x, ScreenshotInput::ScanThread::PointA.y }; + POINT Bpos = { ScreenshotInput::ScanThread::PointB.x, ScreenshotInput::ScanThread::PointB.y }; + POINT Xpos = { ScreenshotInput::ScanThread::PointX.x, ScreenshotInput::ScanThread::PointX.y }; + POINT Ypos = { ScreenshotInput::ScanThread::PointY.x, ScreenshotInput::ScanThread::PointY.y }; + LeaveCriticalSection(&ScreenshotInput::ScanThread::critical); + DrawFoundSpots(hdc, Apos, Bpos, Xpos, Ypos, transparencyBrush); + + } oldHadShowCursor = showCursor; POINT pos = { FakeMouseKeyboard::GetMouseState().x,FakeMouseKeyboard::GetMouseState().y }; diff --git a/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp b/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp index 4d4f57a..cb1fb84 100644 --- a/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.cpp @@ -3,9 +3,13 @@ #include "RegisterRawInputHook.h" #include #include "RawInput.h" +#include "GtoMnK_RawInputHooks.h" //GtoMnK_RawInput.cpp +#include "GtoMnK_RawInput.h" //GtoMnK_RawInput.cpp//TranslateXtoMKB.h +//#include "TranslateXtoMKB.h" //GtoMnK_RawInput.cpp//TranslateXtoMKB.h namespace Proto { + UINT WINAPI Hook_GetRawInputData( HRAWINPUT hRawInput, @@ -15,6 +19,7 @@ UINT WINAPI Hook_GetRawInputData( UINT cbSizeHeader ) { + unsigned int h = (unsigned int)hRawInput; // Only care about first 4 bytes. bool hasSignature = (h & 0xFF000000) == 0xAB000000; if (!hasSignature) @@ -51,14 +56,13 @@ UINT WINAPI Hook_GetRawInputData( } } -// void GetRawInputDataHook::ShowGuiStatus() -// { -// } - void GetRawInputDataHook::InstallImpl() { - //MessageBoxA(NULL, "Installing GetRawInputData Hook", "Info", MB_OK); - hookInfo = std::get<1>(InstallNamedHook(L"user32", "GetRawInputData", Hook_GetRawInputData)); + if (RawInput::TranslateXinputtoMKB) + hookInfo = std::get<1>(InstallNamedHook(L"user32", "GetRawInputData", ScreenshotInput::RawInputHooks::GetRawInputDataHookX)); + else + hookInfo = std::get<1>(InstallNamedHook(L"user32", "GetRawInputData", Hook_GetRawInputData)); + } void GetRawInputDataHook::UninstallImpl() diff --git a/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.h b/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.h index b600bba..19cf9f8 100644 --- a/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.h +++ b/src/ProtoInput/ProtoInputHooks/GetRawInputDataHook.h @@ -18,7 +18,7 @@ class GetRawInputDataHook final : public Hook "This hook forwards the raw input received by Proto Input to the game. " "This is required for any game that uses raw input, or Proto Input will consume all the input."; } - + static int lastVKcode; //keymapping GUI bool HasGuiStatus() const override { return false; } // void ShowGuiStatus() override; void InstallImpl() override; diff --git a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.cpp b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.cpp index c2ed913..8bd9e3f 100644 --- a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.cpp +++ b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.cpp @@ -65,7 +65,7 @@ namespace ScreenshotInput { WaitForSingleObject(hWindowReadyEvent, 2000); CloseHandle(hThread); } - RawInputHooks::InstallHooks(); + // RawInputHooks::InstallHooks(); CloseHandle(hWindowReadyEvent); } @@ -78,9 +78,10 @@ namespace ScreenshotInput { } - - LRESULT WINAPI RawInputWindowWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - switch (msg) { + LRESULT WINAPI RawInputWindowWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch (msg) + { case WM_DESTROY: { PostQuitMessage(0); return 0; diff --git a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.h b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.h index 5652943..c2125f3 100644 --- a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.h +++ b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInput.h @@ -17,6 +17,7 @@ namespace ScreenshotInput { static void SendActionDelta(int deltaX, int deltaY); static const int RAWINPUT_BUFFER_SIZE = 20; static RAWINPUT g_inputBuffer[RAWINPUT_BUFFER_SIZE]; + static std::vector g_forwardingWindows; static HWND g_rawInputHwnd; diff --git a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.cpp b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.cpp index ed667d5..bb8f6c3 100644 --- a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.cpp +++ b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.cpp @@ -5,18 +5,20 @@ //#include "Mouse.h" //#include "Keyboard.h" #include "EasyHook.h" +#include "gui.h" // Thanks to ProtoInput. namespace ScreenshotInput { - HOOK_TRACE_INFO g_getRawInputDataHook = { NULL }; - HOOK_TRACE_INFO g_registerRawInputDevicesHook = { NULL }; + // HOOK_TRACE_INFO g_getRawInputDataHook = { NULL }; + // HOOK_TRACE_INFO g_registerRawInputDevicesHook = { NULL }; - UINT WINAPI GetRawInputDataHook(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader) { + + UINT WINAPI RawInputHooks::GetRawInputDataHookX(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader) { UINT handleValue = (UINT)(UINT_PTR)hRawInput; if ((handleValue & 0xFF000000) == 0xAB000000) { - UINT bufferIndex = handleValue & 0x00FFFFFF; + UINT bufferIndex = handleValue & 0x00FFFFFF; if (bufferIndex >= ScreenshotInput::RawInput::RAWINPUT_BUFFER_SIZE) { return GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader); } @@ -36,7 +38,7 @@ namespace ScreenshotInput } } - BOOL WINAPI RegisterRawInputDevicesHook(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize) { + BOOL WINAPI RawInputHooks::RegisterRawInputDevicesHookX(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize) { for (UINT i = 0; i < uiNumDevices; ++i) { HWND targetHwnd = pRawInputDevices[i].hwndTarget; @@ -50,13 +52,13 @@ namespace ScreenshotInput } return TRUE; } - void RawInputHooks::InstallHooks() { - // Install GetRawInputData hook - HMODULE hUser32 = GetModuleHandleA("user32"); - LhInstallHook(GetProcAddress(hUser32, "GetRawInputData"), GetRawInputDataHook, NULL, &g_getRawInputDataHook); - LhInstallHook(GetProcAddress(hUser32, "RegisterRawInputDevices"), RegisterRawInputDevicesHook, NULL, &g_registerRawInputDevicesHook); - ULONG ACLEntries[1] = { 0 }; - LhSetExclusiveACL(ACLEntries, 1, &g_getRawInputDataHook); - LhSetExclusiveACL(ACLEntries, 1, &g_registerRawInputDevicesHook); - } + // void RawInputHooks::InstallHooks() { + // // Install GetRawInputData hook + // HMODULE hUser32 = GetModuleHandleA("user32"); + // LhInstallHook(GetProcAddress(hUser32, "GetRawInputData"), GetRawInputDataHook, NULL, &g_getRawInputDataHook); + // LhInstallHook(GetProcAddress(hUser32, "RegisterRawInputDevices"), RegisterRawInputDevicesHook, NULL, &g_registerRawInputDevicesHook); + // ULONG ACLEntries[1] = { 0 }; + // LhSetExclusiveACL(ACLEntries, 1, &g_getRawInputDataHook); + // LhSetExclusiveACL(ACLEntries, 1, &g_registerRawInputDevicesHook); + // } } \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.h b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.h index 3c1f44b..b5bd24d 100644 --- a/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.h +++ b/src/ProtoInput/ProtoInputHooks/GtoMnK_RawInputHooks.h @@ -4,8 +4,8 @@ namespace ScreenshotInput { class RawInputHooks { public: - //UINT WINAPI GetRawInputDataHook(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader); - //BOOL WINAPI RegisterRawInputDevicesHook(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize); - static void InstallHooks(); + static UINT WINAPI GetRawInputDataHookX(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader); + static BOOL WINAPI RegisterRawInputDevicesHookX(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize); + //static void InstallHooks(); }; } diff --git a/src/ProtoInput/ProtoInputHooks/Gui.cpp b/src/ProtoInput/ProtoInputHooks/Gui.cpp index 8bc1c21..95cb275 100644 --- a/src/ProtoInput/ProtoInputHooks/Gui.cpp +++ b/src/ProtoInput/ProtoInputHooks/Gui.cpp @@ -13,6 +13,8 @@ #include "FocusMessageLoop.h" #include "StateInfo.h" #include "FakeCursor.h" +#include "TranslateXtoMKB.h" +#include "GtoMnK_RawInput.h" namespace Proto { @@ -85,7 +87,583 @@ void HandleSelectableDualList(std::vector& selected, std::vector& deselect for (const auto x : removeB) deselected.erase(x); } +std::string VkToKeyName(int vk) +{ + + UINT scan = MapVirtualKey(vk, MAPVK_VK_TO_VSC); + UINT flags = scan << 16; + + // Add extended-key flag when needed + switch (vk) + { + case VK_LEFT: + case VK_RIGHT: + case VK_UP: + case VK_DOWN: + case VK_INSERT: + case VK_DELETE: + case VK_HOME: + case VK_END: + case VK_PRIOR: // Page Up + case VK_NEXT: // Page Down + case VK_RCONTROL: + case VK_RMENU: // Right Alt + case VK_DIVIDE: + case VK_NUMLOCK: + flags |= (1 << 24); + break; + } + + char name[64] = { 0 }; + GetKeyNameTextA(flags, name, sizeof(name)); + return std::string(name); +} +bool mappingrefreshed = false; +USHORT X_A; +USHORT X_B; +USHORT X_X; +USHORT X_Y; + +USHORT X_RS; +USHORT X_LS; +USHORT X_right; +USHORT X_left; +USHORT X_up; +USHORT X_down; + +USHORT X_stickLpress; +USHORT X_stickRpress; +USHORT X_stickright; +USHORT X_stickleft; +USHORT X_stickup; +USHORT X_stickdown; + +USHORT X_option; +USHORT X_start; +//bool + + + +int lastVKkey; +void XTranslatefreshmapping(bool read) { + if (read) { + //collision danger if remote read each frame + X_A = ScreenshotInput::TranslateXtoMKB::Amapping; + X_B = ScreenshotInput::TranslateXtoMKB::Bmapping; + X_X = ScreenshotInput::TranslateXtoMKB::Xmapping; + X_Y = ScreenshotInput::TranslateXtoMKB::Ymapping; + + X_RS = ScreenshotInput::TranslateXtoMKB::RSmapping; + X_LS = ScreenshotInput::TranslateXtoMKB::LSmapping; + X_right = ScreenshotInput::TranslateXtoMKB::rightmapping; + X_left = ScreenshotInput::TranslateXtoMKB::leftmapping; + X_up = ScreenshotInput::TranslateXtoMKB::upmapping; + X_down = ScreenshotInput::TranslateXtoMKB::downmapping; + + X_stickRpress = ScreenshotInput::TranslateXtoMKB::stickRpressmapping; + X_stickLpress = ScreenshotInput::TranslateXtoMKB::stickLpressmapping; + X_stickright = ScreenshotInput::TranslateXtoMKB::stickrightmapping; + X_stickleft = ScreenshotInput::TranslateXtoMKB::stickleftmapping; + X_stickup = ScreenshotInput::TranslateXtoMKB::stickupmapping; + X_stickdown = ScreenshotInput::TranslateXtoMKB::stickdownmapping; + + X_option = ScreenshotInput::TranslateXtoMKB::optionmapping; + X_start = ScreenshotInput::TranslateXtoMKB::optionmapping; + X_stickdown = ScreenshotInput::TranslateXtoMKB::stickdownmapping; + }//ImGui::SliderFloat("Slider", &sliderValue, 0.0f, 1.0f); + +} +void GetVK() +{ + BYTE keys[256]; + GetKeyboardState(keys); + for (int vk = 0; vk < 256; vk++) + { + if (keys[vk] & 0x80) + { + lastVKkey = vk; + return; + } + } +} + +void XTranslateMenu() +{ + if (!mappingrefreshed) + XTranslatefreshmapping(true); + { + const auto XAString = VkToKeyName(X_A); + ImGui::TextWrapped("A is mapped to: %s", (XAString.c_str())); + + static bool waitingKeyPressA = false; + + if (waitingKeyPressA) + { + //PushDisabled(); + GetVK(); + ImGui::Button("Press Keyboard button...##A"); //these need unique IDs or text + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressA = false; + X_A = lastVKkey; + ScreenshotInput::TranslateXtoMKB::Amapping = X_A; + } + } + + else if (ImGui::Button("Click to change##A1"))//these need unique IDs or text + { + waitingKeyPressA = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XBString = VkToKeyName(X_B); + ImGui::TextWrapped("B is mapped to: %s", (XBString.c_str())); + + static bool waitingKeyPressB = false; + if (waitingKeyPressB) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##B"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressB = false; + X_B = lastVKkey; + ScreenshotInput::TranslateXtoMKB::Bmapping = X_B; + } + } + else if (ImGui::Button("Click to change##B1"))//these need unique IDs or text + { + waitingKeyPressB = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XXString = VkToKeyName(X_X); + ImGui::TextWrapped("X is mapped to: %s", (XXString.c_str())); + + static bool waitingKeyPressX = false; + if (waitingKeyPressX) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##B"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressX = false; + X_X = lastVKkey; + ScreenshotInput::TranslateXtoMKB::Xmapping = X_X; + } + } + else if (ImGui::Button("Click to change##X1"))//these need unique IDs or text + { + waitingKeyPressX = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XYString = VkToKeyName(X_Y); + ImGui::TextWrapped("Y is mapped to: %s", (XYString.c_str())); + + static bool waitingKeyPressY = false; + if (waitingKeyPressY) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressY = false; + X_Y = lastVKkey; + ScreenshotInput::TranslateXtoMKB::Ymapping = X_Y; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressY = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XRSString = VkToKeyName(X_RS); + ImGui::TextWrapped("Right Shoulder is mapped to: %s", (XRSString.c_str())); + + static bool waitingKeyPressRS = false; + if (waitingKeyPressRS) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressRS = false; + X_RS = lastVKkey; + ScreenshotInput::TranslateXtoMKB::RSmapping = X_RS; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressRS = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XLSString = VkToKeyName(X_LS); + ImGui::TextWrapped("Left Shoulder is mapped to: %s", (XLSString.c_str())); + + static bool waitingKeyPressLS = false; + if (waitingKeyPressLS) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressLS = false; + X_LS = lastVKkey; + ScreenshotInput::TranslateXtoMKB::LSmapping = X_LS; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressLS = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XrightString = VkToKeyName(X_right); + ImGui::TextWrapped("DPAD right is mapped to: %s", (XrightString.c_str())); + + static bool waitingKeyPressright = false; + if (waitingKeyPressright) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressright = false; + X_right = lastVKkey; + ScreenshotInput::TranslateXtoMKB::rightmapping = X_right; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressright = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XleftString = VkToKeyName(X_left); + ImGui::TextWrapped("DPAD left is mapped to: %s", (XleftString.c_str())); + + static bool waitingKeyPressleft = false; + if (waitingKeyPressleft) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressleft = false; + X_left = lastVKkey; + ScreenshotInput::TranslateXtoMKB::leftmapping = X_left; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressleft = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XupString = VkToKeyName(X_up); + ImGui::TextWrapped("DPAD up is mapped to: %s", (XupString.c_str())); + + static bool waitingKeyPressup = false; + if (waitingKeyPressup) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressup = false; + X_up = lastVKkey; + ScreenshotInput::TranslateXtoMKB::upmapping = X_up; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressup = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XdownString = VkToKeyName(X_down); + ImGui::TextWrapped("DPAD down is mapped to: %s", (XdownString.c_str())); + static bool waitingKeyPressdown = false; + if (waitingKeyPressdown) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressdown = false; + X_down = lastVKkey; + ScreenshotInput::TranslateXtoMKB::downmapping = X_down; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressdown = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XstickRpressString = VkToKeyName(X_stickRpress); + ImGui::TextWrapped("Right stick press is mapped to: %s", (XstickRpressString.c_str())); + + static bool waitingKeyPressstickRpress = false; + if (waitingKeyPressstickRpress) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressstickRpress = false; + X_stickRpress = lastVKkey; + ScreenshotInput::TranslateXtoMKB::stickRpressmapping = X_stickRpress; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressstickRpress = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XstickLpressString = VkToKeyName(X_stickLpress); + ImGui::TextWrapped("left stick press is mapped to: %s", (XstickLpressString.c_str())); + + static bool waitingKeyPressstickLpress = false; + if (waitingKeyPressstickLpress) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressstickLpress = false; + X_stickLpress = lastVKkey; + ScreenshotInput::TranslateXtoMKB::stickLpressmapping = X_stickLpress; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressstickLpress = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XstickrightString = VkToKeyName(X_stickright); + ImGui::TextWrapped("Stick right axis is mapped to: %s", (XstickrightString.c_str())); + + static bool waitingKeyPressstickright = false; + if (waitingKeyPressstickright) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressstickright = false; + X_stickright = lastVKkey; + ScreenshotInput::TranslateXtoMKB::stickrightmapping = X_stickright; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressstickright = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XstickleftString = VkToKeyName(X_stickleft); + ImGui::TextWrapped("Stick left axis is mapped to: %s", (XstickleftString.c_str())); + + static bool waitingKeyPressstickleft = false; + if (waitingKeyPressstickleft) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressstickleft = false; + X_stickleft = lastVKkey; + ScreenshotInput::TranslateXtoMKB::stickleftmapping = X_stickleft; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressstickleft = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XstickupString = VkToKeyName(X_stickup); + ImGui::TextWrapped("Stick up axis is mapped to: %s", (XstickupString.c_str())); + + static bool waitingKeyPressstickup = false; + if (waitingKeyPressstickup) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressstickup = false; + X_stickup = lastVKkey; + ScreenshotInput::TranslateXtoMKB::stickupmapping = X_stickup; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressstickup = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XstickdownString = VkToKeyName(X_stickdown); + ImGui::TextWrapped("Stick up axis is mapped to: %s", (XstickdownString.c_str())); + + static bool waitingKeyPressstickdown = false; + if (waitingKeyPressstickdown) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressstickdown = false; + X_stickdown = lastVKkey; + ScreenshotInput::TranslateXtoMKB::stickdownmapping = X_stickdown; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressstickdown = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XoptionString = VkToKeyName(X_option); + ImGui::TextWrapped("Stick Options button is mapped to: %s", (XoptionString.c_str())); + + static bool waitingKeyPressoption = false; + if (waitingKeyPressoption) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressoption = false; + X_option = lastVKkey; + ScreenshotInput::TranslateXtoMKB::optionmapping = X_option; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressoption = true; + lastVKkey = -1; + } + } + ImGui::Separator(); + { + const auto XstartString = VkToKeyName(X_start); + ImGui::TextWrapped("Stick Start button is mapped to: %s", (XstartString.c_str())); + + static bool waitingKeyPressstart = false; + if (waitingKeyPressstart) + { + //PushDisabled(); + ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + GetVK(); + //PopDisabled(); + // Sleep(100); + if (lastVKkey != -1) + { + waitingKeyPressstart = false; + X_start = lastVKkey; + ScreenshotInput::TranslateXtoMKB::startmapping = X_start; + } + } + else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + { + waitingKeyPressstart = true; + lastVKkey = -1; + } + } + ImGui::Separator(); //no idea if this may crash. suppose it is not safe + ImGui::Checkbox("Lefthanded Stick. moves mouse with left stick and button map on right stick. or opposite if disabled", &ScreenshotInput::TranslateXtoMKB::lefthanded); // + ImGui::Separator(); +} void HooksMenu() { const auto& hooks = HookManager::GetHooks(); @@ -211,24 +789,35 @@ void RawInputMenu() ImGui::Separator(); - if (ImGui::TreeNode("Selected mouse devices")) + + + if (RawInput::TranslateXinputtoMKB) { - HandleSelectableDualList(RawInput::rawInputState.selectedMouseHandles, RawInput::rawInputState.deselectedMouseHandles); - - ImGui::TreePop(); + ImGui::TextWrapped("XinputtoMKB ControllerID"); + ImGui::TextWrapped("0 is first controller"); + ImGui::SliderInt("XinputtoMKB ControllerID", (int*)&ScreenshotInput::TranslateXtoMKB::controllerID, 0, 16, "%d", ImGuiSliderFlags_AlwaysClamp); } - - if (ImGui::TreeNode("Selected keyboard devices")) + else { - HandleSelectableDualList(RawInput::rawInputState.selectedKeyboardHandles, RawInput::rawInputState.deselectedKeyboardHandles); + if (ImGui::TreeNode("Selected mouse devices")) + { + HandleSelectableDualList(RawInput::rawInputState.selectedMouseHandles, RawInput::rawInputState.deselectedMouseHandles); - ImGui::TreePop(); - } + ImGui::TreePop(); + } - if (ImGui::Button("Refresh devices")) - { - RawInput::RefreshDevices(); + if (ImGui::TreeNode("Selected keyboard devices")) + { + HandleSelectableDualList(RawInput::rawInputState.selectedKeyboardHandles, RawInput::rawInputState.deselectedKeyboardHandles); + + ImGui::TreePop(); + } + if (ImGui::Button("Refresh devices")) + { + RawInput::RefreshDevices(); + } } + } void ControlsMenu() @@ -288,7 +877,6 @@ void RenderImgui() { // ImGui::ShowDemoWindow(); // return; - const auto displaySize = ImGui::GetIO().DisplaySize; ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); @@ -322,6 +910,15 @@ void RenderImgui() HooksMenu(); ImGui::EndTabItem(); } + if (RawInput::TranslateXinputtoMKB) + { + if (ImGui::BeginTabItem("TranslateXtoMKB options")) + { + XTranslateMenu(); + ImGui::EndTabItem(); + } + } + if (ImGui::BeginTabItem("Message filter")) { if (ImGui::BeginTabBar("Filter tabs")) diff --git a/src/ProtoInput/ProtoInputHooks/HookManager.cpp b/src/ProtoInput/ProtoInputHooks/HookManager.cpp index d581316..5a454b9 100644 --- a/src/ProtoInput/ProtoInputHooks/HookManager.cpp +++ b/src/ProtoInput/ProtoInputHooks/HookManager.cpp @@ -67,8 +67,8 @@ void HookManager::InstallHook(ProtoHookIDs hookID) hookManagerInstance.hooks[hookID]->Install(); else // skipping original protoinput hooks on experimental Xinput to MKB translation mode { - if (hookID == 0) ScreenshotInput::TranslateXtoMKB::registerrawinputhook = true; - if (hookID == 1) ScreenshotInput::TranslateXtoMKB::rawinputhook = true; + if (hookID == 0) hookManagerInstance.hooks[hookID]->Install(); + if (hookID == 1) hookManagerInstance.hooks[hookID]->Install(); if (hookID == 2) hookManagerInstance.hooks[hookID]->Install(); if (hookID == 3) hookManagerInstance.hooks[hookID]->Install(); if (hookID == 4) hookManagerInstance.hooks[hookID]->Install(); @@ -94,8 +94,8 @@ void HookManager::UninstallHook(ProtoHookIDs hookID) if (!RawInput::TranslateXinputtoMKB) hookManagerInstance.hooks[hookID]->Uninstall(); else - if (hookID == 0) ScreenshotInput::TranslateXtoMKB::registerrawinputhook = false; - if (hookID == 1) ScreenshotInput::TranslateXtoMKB::rawinputhook = false; + if (hookID == 0) hookManagerInstance.hooks[hookID]->Uninstall(); + if (hookID == 1) hookManagerInstance.hooks[hookID]->Uninstall(); if (hookID == 2) hookManagerInstance.hooks[hookID]->Uninstall(); if (hookID == 3) hookManagerInstance.hooks[hookID]->Uninstall(); if (hookID == 4) hookManagerInstance.hooks[hookID]->Uninstall(); @@ -120,8 +120,8 @@ bool HookManager::IsInstalled(ProtoHookIDs hookID) { if(RawInput::TranslateXinputtoMKB) { - if (hookID == 0) return true; - if (hookID == 1) return true; + if (hookID == 0) return hookManagerInstance.hooks[hookID]->IsInstalled(); + if (hookID == 1) return hookManagerInstance.hooks[hookID]->IsInstalled(); if (hookID == 2) return hookManagerInstance.hooks[hookID]->IsInstalled(); else return hookManagerInstance.hooks[hookID]->IsInstalled(); } diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index bdc46d5..3c82b37 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -157,14 +157,17 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) if (gotkeyboardmouse) { RawInput::TranslateXinputtoMKB = false; - //MessageBoxA(NULL, "OOOhhhh, there is a mouse here. disabling", "tunell", MB_OK | MB_ICONWARNING); + printf("Discovered mouse or keyboard. disabling TranslateXtoMKB"); } + else printf("Enabling TranslateXtoMKB"); } + else printf("TranslateXtoMKB is set to false"); break; } case ProtoPipe::PipeMessageType::SetXinputtoMKBkeys: { const auto body = reinterpret_cast(messageBuffer); + printf("Received TranslateXtoMKB Mapping"); ScreenshotInput::TranslateXtoMKB::Amapping = body->XinputtoMKBAkey; ScreenshotInput::TranslateXtoMKB::Bmapping = body->XinputtoMKBBkey; ScreenshotInput::TranslateXtoMKB::Xmapping = body->XinputtoMKBXkey; diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj index 48e0758..3e8f536 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj @@ -234,6 +234,7 @@ + @@ -288,6 +289,7 @@ + diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters index 5329185..3923cbd 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters @@ -192,6 +192,9 @@ Source Files\Hooks\TranslateXtoMKB + + Source Files\Hooks\TranslateXtoMKB + @@ -344,5 +347,8 @@ Source Files\Hooks\TranslateXtoMKB + + Source Files\Hooks\TranslateXtoMKB + \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.cpp b/src/ProtoInput/ProtoInputHooks/RawInput.cpp index ae56c54..7ca80b3 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.cpp +++ b/src/ProtoInput/ProtoInputHooks/RawInput.cpp @@ -29,6 +29,8 @@ bool RawInput::rawInputBypass = false; RAWINPUT RawInput::inputBuffer[RawInputBufferSize]{}; std::vector RawInput::rawinputs{}; bool RawInput::TranslateXinputtoMKB; +bool RawInput::locked = false; +bool RawInput::alreadyAddToACL = false; const std::vector RawInput::usageTypesOfInterest { HID_USAGE_GENERIC_POINTER, @@ -264,6 +266,26 @@ void RawInput::ProcessKeyboardInput(const RAWKEYBOARD& data, HANDLE deviceHandle FakeMouseKeyboard::ReceivedKeyPressOrRelease(data.VKey, pressed); } + + +void RawInput::ToggleLockInput() +{ + RawInput::locked = !RawInput::locked; + static unsigned int loopThreadId = 0; + loopThreadId = LockInput(locked); + // Add the looping thread to the ACL so it can still use ClipCursor, etc + if (!RawInput::alreadyAddToACL && loopThreadId != 0) + { + RawInput::alreadyAddToACL = true; + printf("Adding loop thread %d to ACL\n", loopThreadId); + AddThreadToACL(loopThreadId); + } + if (locked) + SuspendExplorer(); + else + RestartExplorer(); +} + void RawInput::ProcessRawInput(HRAWINPUT rawInputHandle, bool inForeground, const MSG& msg) { // if (rawInputBypass) @@ -331,25 +353,8 @@ void RawInput::ProcessRawInput(HRAWINPUT rawInputHandle, bool inForeground, cons // Lock input toggle if (lockInputToggleEnabled && rawinput.header.dwType == RIM_TYPEKEYBOARD && rawinput.data.keyboard.VKey == VK_HOME && rawinput.data.keyboard.Message == WM_KEYUP) { - static bool locked = false; - locked = !locked; printf(locked ? "Locking input\n" : "Unlocking input\n"); - - // Add the looping thread to the ACL so it can still use ClipCursor, etc - static unsigned int loopThreadId = 0; - static bool alreadyAddToACL = false; - loopThreadId = LockInput(locked); - if (!alreadyAddToACL && loopThreadId != 0) - { - alreadyAddToACL = true; - printf("Adding loop thread %d to ACL\n", loopThreadId); - AddThreadToACL(loopThreadId); - } - - if (locked) - SuspendExplorer(); - else - RestartExplorer(); + RawInput::ToggleLockInput(); } diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.h b/src/ProtoInput/ProtoInputHooks/RawInput.h index 3d80ab7..07c2d00 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.h +++ b/src/ProtoInput/ProtoInputHooks/RawInput.h @@ -36,16 +36,19 @@ class RawInput { private: static std::bitset<9> usages; + static std::vector forwardingWindows; - static const std::vector usageTypesOfInterest; static void ProcessMouseInput(const RAWMOUSE& data, HANDLE deviceHandle); static void ProcessKeyboardInput(const RAWKEYBOARD& data, HANDLE deviceHandle); + static bool locked; //input lock state + static bool alreadyAddToACL; public: static void SendInputMessages(const RAWMOUSE& data); static void SendKeyMessage(const RAWKEYBOARD& data, bool pressed); + static void ToggleLockInput(); static RawInputState rawInputState; static HWND rawInputHwnd; static bool forwardRawInput; diff --git a/src/ProtoInput/ProtoInputHooks/RegisterRawInputHook.cpp b/src/ProtoInput/ProtoInputHooks/RegisterRawInputHook.cpp index cf74591..a21b821 100644 --- a/src/ProtoInput/ProtoInputHooks/RegisterRawInputHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/RegisterRawInputHook.cpp @@ -5,7 +5,8 @@ #include #include "RawInput.h" #include -#include "HwndSelector.h" +#include "HwndSelector.h" //GtoMnK_RawInputHooks +#include "GtoMnK_RawInputHooks.h" //GtoMnK_RawInputHooks namespace Proto { @@ -156,7 +157,13 @@ void RegisterRawInputHook::ShowGuiStatus() void RegisterRawInputHook::InstallImpl() { - + if (RawInput::TranslateXinputtoMKB) + { + auto [status, _hookInfo] = InstallNamedHook(L"user32", "RegisterRawInputDevices", ScreenshotInput::RawInputHooks::RegisterRawInputDevicesHookX); + this->hookInfo = _hookInfo; + } + else + { if (!installedAtLeastOnce) { installedAtLeastOnce = true; @@ -172,6 +179,7 @@ void RegisterRawInputHook::InstallImpl() FindAlreadySubscribedWindows(); RawInput::UnregisterGameFromRawInput(); RawInput::RegisterProtoForRawInput(); + } } void RegisterRawInputHook::UninstallImpl() diff --git a/src/ProtoInput/ProtoInputHooks/ScanThread.cpp b/src/ProtoInput/ProtoInputHooks/ScanThread.cpp new file mode 100644 index 0000000..c7a3a0e --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/ScanThread.cpp @@ -0,0 +1,1273 @@ +#include +//#include "pch.h" +#include +#define NOMINMAX +#include +//#include +#include +#include +#include +#include +#include +#include // for swprintf +#include +#include +#include // For strtoul +#include +#include +#include +//#include "input.h" +//#include "MainThread.h" +//#include "Mouse.h" +#include "FakeMouseKeyboard.h" +#include "ScanThread.h" +#include "TranslateXtoMKB.h" +#include "FakeCursor.h" +#include "HwndSelector.h" + +#pragma comment(lib, "dwmapi.lib") + + + + +namespace ScreenshotInput { + + //public + // extern int drawfakecursor; + int ScanThread::Aisstatic, ScanThread::Bisstatic, ScanThread::Xisstatic, ScanThread::Yisstatic; + + int ScanThread::numphotoA, ScanThread::numphotoB, ScanThread::numphotoX, ScanThread::numphotoY; + int ScanThread::numphotoC, ScanThread::numphotoD, ScanThread::numphotoE, ScanThread::numphotoF; + int ScanThread::numphotoAbmps, ScanThread::numphotoBbmps, ScanThread::numphotoXbmps, ScanThread::numphotoYbmps; + int ScanThread::startsearchA, ScanThread::startsearchB, ScanThread::startsearchX, ScanThread::startsearchY; + int ScanThread::startsearchC, ScanThread::startsearchD, ScanThread::startsearchE, ScanThread::startsearchF; + POINT ScanThread::PointA, ScanThread::PointB, ScanThread::PointX, ScanThread::PointY; + CRITICAL_SECTION ScanThread::critical; + std::vector ScanThread::staticPointA, ScanThread::staticPointB, ScanThread::staticPointX, ScanThread::staticPointY; + int ScanThread::scanAtype, ScanThread::scanBtype, ScanThread::scanXtype, ScanThread::scanYtype; + int ScanThread::Ctype, ScanThread::Dtype, ScanThread::Etype, ScanThread::Ftype; + bool ScanThread::scanloop = true; + int ScanThread::scanoption; + int ScanThread::ignorerect; + int ScanThread::ShoulderNextBMP; + int ScanThread::resize = 1; //support scaling + HWND hwndhandle; + POINT hwndres{ 0,0 }; + //private + bool PreScanningEnabled = false; + bool Astatic; + bool Bstatic; + bool Xstatic; + bool Ystatic; + HBITMAP hbm; + std::vector largePixels, smallPixels; + SIZE screenSize; + int strideLarge, strideSmall; + int smallW, smallH; + + //copies of criticals + int ModeScanThread; + int showmessageScanThread; + + std::string UGetExecutableFolder() + { + char path[MAX_PATH]; + GetModuleFileNameA(NULL, path, MAX_PATH); + std::string exePath(path); + size_t lastSlash = exePath.find_last_of("\\/"); + return exePath.substr(0, lastSlash); + } + + + std::wstring WGetExecutableFolder() { + wchar_t path[MAX_PATH]; + GetModuleFileNameW(NULL, path, MAX_PATH); + std::wstring exePath(path); + size_t lastSlash = exePath.find_last_of(L"\\/"); + + if (lastSlash == std::wstring::npos) + return L""; + return exePath.substr(0, lastSlash); + } + + int CalculateStride(int width) { + return ((width * 3 + 3) & ~3); + } + + bool LoadBMP24Bit(std::wstring filename, std::vector& pixels, int& width, int& height, int& stride) { + HBITMAP hbm = (HBITMAP)LoadImageW(NULL, filename.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION); + if (!hbm) return false; + + //BITMAP scaledbmp; + BITMAP bmp; + GetObject(hbm, sizeof(BITMAP), &bmp); + width = bmp.bmWidth - 1; + height = bmp.bmHeight - 1; + stride = CalculateStride(width); + + pixels.resize(stride * height); + + BITMAPINFO bmi = {}; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + + BYTE* pBits = nullptr; + HDC hdc = GetDC(NULL); + GetDIBits(hdc, hbm, 0, height, pixels.data(), &bmi, DIB_RGB_COLORS); + + if (hdc) DeleteDC(hdc); + if (hbm) DeleteObject(hbm); + return true; + } + + //calling fuction in critical lock + void BmpInputAction(int X, int Y, int type) //moveclickorboth + { + Proto::FakeMouseState muusjn = Proto::FakeMouseKeyboard::GetMouseState(); + int Xhold = muusjn.x; + int Yhold = muusjn.y; + if (Xhold < X) + X = X - Xhold; + else + X = X - Xhold; + if (Yhold < Y) + Y= Y - Yhold; + else + Y = Y - Yhold; + if (type == 0) //click and move + { + + TranslateXtoMKB::SendMouseClick(X, Y, 8); + // Proto::FakeMouseKeyboard::SetMousePos(X, Y); + Sleep(5); + TranslateXtoMKB::SendMouseClick(X, Y, 3); + Sleep(5); + TranslateXtoMKB::SendMouseClick(X, Y, 4); + } + else if (type == 1) //only move + { + TranslateXtoMKB::SendMouseClick(X, Y, 8); + } + else if (type == 2) //only click + { + TranslateXtoMKB::SendMouseClick(X, Y, 8); + Sleep(5); + TranslateXtoMKB::SendMouseClick(X, Y, 3); + Sleep(5); + TranslateXtoMKB::SendMouseClick(X, Y, 4); + Sleep(5); + TranslateXtoMKB::SendMouseClick(Xhold, Yhold, 8); + } + } + + void Bmpfound(const char key[3], int X, int Y, int i, bool onlysearch, bool found, int store) + { + int input = 0; + if (strcmp(key, "\\A") == 0) + { + if (found) + { + + EnterCriticalSection(&ScanThread::critical); + Proto::FakeCursor::NotifyUpdatedCursorPosition(); + LeaveCriticalSection(&ScanThread::critical); + if (onlysearch) + { + EnterCriticalSection(&ScanThread::critical); + ScanThread::startsearchA = i; + input = ScanThread::scanAtype; + ScanThread::staticPointA[i].x = X; + ScanThread::staticPointA[i].y = Y; + ScanThread::PointA.x = X; + ScanThread::PointA.y = Y; + LeaveCriticalSection(&ScanThread::critical); + } + else + { + input = ScanThread::scanAtype; + if (store) { + ScanThread::staticPointA[i].x = X; + ScanThread::staticPointA[i].y = Y; + + } + if (ScanThread::startsearchA < ScanThread::numphotoA - 1) + ScanThread::startsearchA = i + 1; + else ScanThread::startsearchA = 0; + } + } + else + { + if (onlysearch) + { + EnterCriticalSection(&ScanThread::critical); + ScanThread::startsearchA = 0; + ScanThread::PointA.x = 0; + ScanThread::PointA.y = 0; + LeaveCriticalSection(&ScanThread::critical); + } + } + } + if (strcmp(key, "\\B") == 0) + { + if (found) + { + //EnterCriticalSection(&critical); + + //LeaveCriticalSection(&critical); + if (onlysearch) + { + EnterCriticalSection(&ScanThread::critical); + ScanThread::startsearchB = i; + ScanThread::PointB.x = X; + ScanThread::staticPointB[i].x = X; + ScanThread::staticPointB[i].y = Y; + ScanThread::PointB.y = Y; + LeaveCriticalSection(&ScanThread::critical); + } + else + { + input = ScanThread::scanBtype; + if (store) { + ScanThread::staticPointB[i].x = X; + ScanThread::staticPointB[i].y = Y; + } + if (ScanThread::startsearchB < ScanThread::numphotoB - 1) + ScanThread::startsearchB = i + 1; + else ScanThread::startsearchB = 0; + } + } + else + { + if (onlysearch) + { + EnterCriticalSection(&ScanThread::critical); + ScanThread::startsearchB = 0; + ScanThread::PointB.x = 0; + ScanThread::PointB.y = 0; + LeaveCriticalSection(&ScanThread::critical); + } + } + } + if (strcmp(key, "\\X") == 0) + { + if (found) + { + // EnterCriticalSection(&critical); + + //LeaveCriticalSection(&critical); + if (onlysearch) + { + EnterCriticalSection(&ScanThread::critical); + ScanThread::startsearchX = i; + ScanThread::PointX.x = X; + ScanThread::PointX.y = Y; + ScanThread::staticPointX[i].x = X; + ScanThread::staticPointX[i].y = Y; + LeaveCriticalSection(&ScanThread::critical); + } + else + { + input = ScanThread::scanXtype; + ScanThread::startsearchX = i + 1; + if (store) { + ScanThread::staticPointX[i].x = X; + ScanThread::staticPointX[i].y = Y; + } + if (ScanThread::startsearchX < ScanThread::numphotoX - 1) + ScanThread::startsearchX = i + 1; + else ScanThread::startsearchX = 0; + } + } + else + { + if (onlysearch) + { + EnterCriticalSection(&ScanThread::critical); + ScanThread::startsearchX = 0; + ScanThread::PointX.x = 0; + ScanThread::PointX.y = 0; + LeaveCriticalSection(&ScanThread::critical); + } + } + } + if (strcmp(key, "\\Y") == 0) + { + //EnterCriticalSection(&critical); + + //LeaveCriticalSection(&critical); + if (found) + { + if (onlysearch) + { + EnterCriticalSection(&ScanThread::critical); + ScanThread::startsearchX = i; + ScanThread::staticPointY[i].x = X; + ScanThread::staticPointY[i].y = Y; + ScanThread::PointY.x = X; + ScanThread::PointY.y = Y; + LeaveCriticalSection(&ScanThread::critical); + } + else + { + input = ScanThread::scanYtype; + ScanThread::startsearchY = i + 1; + if (store) { + ScanThread::staticPointY[i].x = X; + ScanThread::staticPointY[i].y = Y; + } + if (ScanThread::startsearchY < ScanThread::numphotoY - 1) + ScanThread::startsearchY = i + 1; + else ScanThread::startsearchY = 0; + } + } + else + { + if (onlysearch) + { + EnterCriticalSection(&ScanThread::critical); + ScanThread::startsearchY = 0; + //input = scanYtype; + ScanThread::PointY.x = 0; + ScanThread::PointY.y = 0; + LeaveCriticalSection(&ScanThread::critical); + } + } + } + if (strcmp(key, "\\C") == 0) + { + if (found && !onlysearch) + { + ScanThread::startsearchC = i + 1; + input = ScanThread::Ctype; + } + } + if (strcmp(key, "\\D") == 0) + { + if (found && !onlysearch) + { + ScanThread::startsearchD = i + 1; + input = ScanThread::Dtype; + } + } + if (strcmp(key, "\\E") == 0) + { + if (found && !onlysearch) + { + ScanThread::startsearchE = i + 1; + input = ScanThread::Etype; + } + } + if (strcmp(key, "\\F") == 0) + { + if (found && !onlysearch) + { + ScanThread::startsearchF = i + 1; + input = ScanThread::Ftype; + } + } + if (!onlysearch) + { + if (found) + { //input sent in this function + BmpInputAction(X, Y, input); + } + } + return; + } + + + POINT GetStaticFactor(POINT pp, int doscale, bool isnotbmp) + { + FLOAT ny; + POINT currentres; + currentres.x = Proto::HwndSelector::windowWidth; + currentres.y = Proto::HwndSelector::windowHeight; + FLOAT currentwidth = static_cast(currentres.x); + FLOAT currentheight = static_cast(currentres.y); + if (doscale == 1) + { + float scalex = currentwidth / 1024.0f; + float scaley = currentheight / 768.0f; + + pp.x = static_cast(std::lround(pp.x * scalex)); + pp.y = static_cast(std::lround(pp.y * scaley)); + } + if (doscale == 2) //4:3 blackbar only x + { + float difference = 0.0f; + float newwidth = currentwidth; + float curraspect = currentheight / currentwidth; + if (curraspect < 0.75f) + { + newwidth = currentheight / 0.75f; + if (isnotbmp) //cant pluss blackbars on bmps + difference = (currentwidth - newwidth) / 2; + } + float scalex = newwidth / 1024.0f; + float scaley = currentheight / 768.0f; + pp.x = static_cast(std::lround(pp.x * scalex) + difference); + pp.y = static_cast(std::lround(pp.y * scaley)); + } + if (doscale == 3) //only vertical stretch equal + { + float difference = 0.0f; + float newwidth = currentwidth; + float curraspect = currentheight / currentwidth; + if (curraspect < 0.5625f) + { + newwidth = currentheight / 0.5625f; + if (isnotbmp) //cant pluss blackbars on bmps + difference = (currentwidth - newwidth) / 2; + } + float scalex = newwidth / 1337.0f; + float scaley = currentheight / 768.0f; + pp.x = static_cast(std::lround(pp.x * scalex) + difference); + pp.y = static_cast(std::lround(pp.y * scaley)); + } + return pp; + } + + bool CaptureWindow24Bit(HWND hwnd, SIZE& capturedwindow, std::vector& pixels, int& strideOut, bool draw, bool stretchblt) + { + if (PreScanningEnabled) + EnterCriticalSection(&ScanThread::critical); + HDC hdcWindow = GetDC(hwnd); + HDC hdcMem = CreateCompatibleDC(hdcWindow); + + + RECT rcClient; + GetClientRect(hwnd, &rcClient); + int width = rcClient.right - rcClient.left; + int height = rcClient.bottom - rcClient.top; + capturedwindow.cx = width; + capturedwindow.cy = height; + + int stride = ((width * 3 + 3) & ~3); + strideOut = stride; + pixels.resize(stride * height); + + BITMAPINFO bmi = {}; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; // top-down + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + + BYTE* pBits = nullptr; + HBITMAP hbm24 = CreateDIBSection(hdcWindow, &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0); + if (hbm24) + { + HGDIOBJ oldBmp = SelectObject(hdcMem, hbm24); + BitBlt(hdcMem, 0, 0, width, height, hdcWindow, 0, 0, SRCCOPY); + GetDIBits(hdcMem, hbm24, 0, height, pixels.data(), &bmi, DIB_RGB_COLORS); + SelectObject(hdcMem, oldBmp); + DeleteObject(hbm24); + // hbm24 = nullptr; + + } //hbm24 not null + + if (hdcMem) DeleteDC(hdcMem); + if (hdcWindow) ReleaseDC(hwnd, hdcWindow); + + if (PreScanningEnabled) + LeaveCriticalSection(&ScanThread::critical); + return true; + } //function end + + POINT CheckStatics(const char abc[3], int numtocheck) + { + POINT newpoint{ 0,0 }; + if (strcmp(abc, "\\A") == 0) + { + if (ScanThread::staticPointA[numtocheck].x != 0) + { + // + newpoint.x = ScanThread::staticPointA[numtocheck].x; + newpoint.y = ScanThread::staticPointA[numtocheck].y; + } + } + if (strcmp(abc, "\\B") == 0) + { + if (ScanThread::staticPointB[numtocheck].x != 0) + { + newpoint.x = ScanThread::staticPointB[numtocheck].x; + newpoint.y = ScanThread::staticPointB[numtocheck].y; + } + } + if (strcmp(abc, "\\X") == 0) + { + if (ScanThread::staticPointX[numtocheck].x != 0) + { + newpoint.x = ScanThread::staticPointX[numtocheck].x; + newpoint.y = ScanThread::staticPointX[numtocheck].y; + } + } + if (strcmp(abc, "\\Y") == 0) + { + if (ScanThread::staticPointY[numtocheck].x != 0) + { + newpoint.x = ScanThread::staticPointY[numtocheck].x; + newpoint.y = ScanThread::staticPointY[numtocheck].y; + } + } + return newpoint; + } + + bool FindSubImage24( + const BYTE* largeData, int largeW, int largeH, int strideLarge, + const BYTE* smallData, int smallW, int smallH, int strideSmall, + POINT& foundAt, int Xstart, int Ystart + ) { + for (int y = Ystart; y <= largeH - smallH; ++y) { + for (int x = Xstart; x <= largeW - smallW; ++x) { + bool match = true; + for (int j = 0; j < smallH && match; ++j) { + const BYTE* pLarge = largeData + (y + j) * strideLarge + x * 3; + const BYTE* pSmall = smallData + j * strideSmall; + if (memcmp(pLarge, pSmall, smallW * 3) != 0) { + match = false; + } + } + if (match) { + foundAt.x = x; + foundAt.y = y; + return true; + } + } + } + return false; + } + + bool Save24BitBMP(std::wstring filename, const BYTE* pixels, int width, int height) { //for testing purposes + int stride = ((width * 3 + 3) & ~3); + int imageSize = stride * height; + + BITMAPFILEHEADER bfh = {}; + bfh.bfType = 0x4D42; // "BM" + bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + bfh.bfSize = bfh.bfOffBits + imageSize; + + BITMAPINFOHEADER bih = {}; + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = width; + bih.biHeight = -height; // bottom-up BMP (positive height) + bih.biPlanes = 1; + bih.biBitCount = 24; + bih.biCompression = BI_RGB; + bih.biSizeImage = imageSize; + + HANDLE hFile = CreateFileW(filename.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) return false; + + DWORD written; + WriteFile(hFile, &bfh, sizeof(bfh), &written, NULL); + WriteFile(hFile, &bih, sizeof(bih), &written, NULL); + WriteFile(hFile, pixels, imageSize, &written, NULL); + CloseHandle(hFile); + + return true; + } + + bool SaveWindow10x10BMP(HWND hwnd, std::wstring filename, int x, int y) { + HDC hdcWindow = GetDC(hwnd); + HDC hdcMem = CreateCompatibleDC(hdcWindow); + + // Size: 10x10 + int width = 10; + int height = 10; + int stride = ((width * 3 + 3) & ~3); + std::vector pixels(stride * height); + + // Create a 24bpp bitmap + BITMAPINFO bmi = {}; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; // top-down DIB + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + + //stretchblt + + BYTE* pBits = nullptr; + + HBITMAP hbm24 = CreateDIBSection(hdcWindow, &bmi, DIB_RGB_COLORS, (void**)&pBits, 0, 0); + if (!hbm24) { + DeleteDC(hdcMem); + ReleaseDC(hwnd, hdcWindow); + return false; + } + + HGDIOBJ oldbmp = SelectObject(hdcMem, hbm24); + + BitBlt(hdcMem, 0, 0, width, height, hdcWindow, x, y, SRCCOPY); + + // Prepare to retrieve bits + BITMAPINFOHEADER bih = {}; + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = width; + bih.biHeight = -height; // top-down for easier use + bih.biPlanes = 1; + bih.biBitCount = 24; + bih.biCompression = BI_RGB; + + GetDIBits(hdcMem, hbm24, 0, height, pixels.data(), (BITMAPINFO*)&bih, DIB_RGB_COLORS); + + // Save + bool ok = Save24BitBMP(filename.c_str(), pixels.data(), width, height); + + // Cleanup + SelectObject(hdcMem, oldbmp); + if (hbm24) DeleteObject(hbm24); + if (hdcMem)DeleteDC(hdcMem); + if (hdcWindow) ReleaseDC(hwnd, hdcWindow); + + return ok; + } + int HowManyBmps(std::wstring path, bool andstatics) + { + int start = -1; + + int x = 0; + std::wstring filename; + while (x < 50 && start == -1) + { + filename = path + std::to_wstring(x) + L".bmp"; + if (HBITMAP hbm = (HBITMAP)LoadImageW(NULL, filename.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION)) + { + x++; + DeleteObject(hbm); + + } + else { + start = x; + } + } + + //searching statics + x = 0; + int inistart = -1; + while (x < 50 && inistart == -1) + { + std::string iniPath = UGetExecutableFolder() + "\\GtoMnK.ini"; + std::string iniSettings = "Statics"; + + std::string name(path.end() - 1, path.end()); + std::string string = name.c_str() + std::to_string(x) + "X"; + + + int sjekkX = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); //simple test if settings read but write it wont work. + if (sjekkX != 0) + { + string = name.c_str() + std::to_string(x) + "X"; + x++; + } + else inistart = x; + } + if (!andstatics || inistart == 0) + return start; + else return start + inistart; + } + bool ScanThread::initovector() + { + std::string iniPath = UGetExecutableFolder() + "\\GtoMnK.ini"; + std::string iniSettings = "Statics"; + std::string name = "A"; + int y = -1; + int sjekkx = 0; + bool test = false; + int x = -1; + int scalemethod = 0; + POINT inipoint; + while (x < 50 && y == -1) + { + x++; + std::string string = name + std::to_string(x) + "X"; + sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (sjekkx != 0) + { + test = true; + inipoint.x = sjekkx; + + string = name + std::to_string(x) + "Y"; + inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + + string = name + std::to_string(x) + "Z"; + scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (scalemethod != 0) + inipoint = GetStaticFactor(inipoint, scalemethod, true); + ScanThread::staticPointA[x + ScanThread::numphotoAbmps].y = inipoint.y; + ScanThread::staticPointA[x + ScanThread::numphotoAbmps].x = inipoint.x; + } + else y = 10;// break; + } + y = -1; + name = "B"; + sjekkx = 0; + x = -1; + while (x < 50 && y == -1) + { + x++; + std::string string = name + std::to_string(x) + "X"; + sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (sjekkx != 0) + { + test = true; + inipoint.x = sjekkx; + + string = name + std::to_string(x) + "Y"; + inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + + string = name + std::to_string(x) + "Z"; + scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (scalemethod != 0) + inipoint = GetStaticFactor(inipoint, scalemethod, true); + ScanThread::staticPointB[x + ScanThread::numphotoBbmps].y = inipoint.y; + ScanThread::staticPointB[x + ScanThread::numphotoBbmps].x = inipoint.x; + } + + else y = 10;// break; + } + y = -1; + name = "X"; + sjekkx = 0; + x = -1; + while (x < 50 && y == -1) + { + x++; + std::string string = name.c_str() + std::to_string(x) + "X"; + //MessageBoxA(NULL, "no bmps", "aaahaAAAHAA", MB_OK); + sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (sjekkx != 0) + { + test = true; + inipoint.x = sjekkx; + + string = name + std::to_string(x) + "Y"; + inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + + string = name + std::to_string(x) + "Z"; + scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (scalemethod != 0) + inipoint = GetStaticFactor(inipoint, scalemethod, true); + ScanThread::staticPointX[x + ScanThread::numphotoXbmps].y = inipoint.y; + ScanThread::staticPointX[x + ScanThread::numphotoXbmps].x = inipoint.x; + + } + + else y = 10;// break; + } + y = -1; + name = "Y"; + sjekkx = 0; + x = -1; + while (x < 50 && y == -1) + { + x++; + std::string string = name.c_str() + std::to_string(x) + "X"; + sjekkx = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (sjekkx != 0) + { + test = true; + inipoint.x = sjekkx; + + string = name + std::to_string(x) + "Y"; + inipoint.y = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + + string = name + std::to_string(x) + "Z"; + scalemethod = GetPrivateProfileIntA(iniSettings.c_str(), string.c_str(), 0, iniPath.c_str()); + if (scalemethod != 0) + inipoint = GetStaticFactor(inipoint, scalemethod, true); + ScanThread::staticPointY[x + ScanThread::numphotoYbmps].y = inipoint.y; + ScanThread::staticPointY[x + ScanThread::numphotoYbmps].x = inipoint.x; + } + else y = 10; // break; + } + if (test == true) + return true; + else return false; //no points + } + + bool ScanThread::enumeratebmps() + { + std::wstring path = WGetExecutableFolder() + L"\\A"; + ScanThread::numphotoA = HowManyBmps(path, true); + ScanThread::numphotoAbmps = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\B"; + ScanThread::numphotoB = HowManyBmps(path, true); + ScanThread::numphotoBbmps = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\X"; + ScanThread::numphotoX = HowManyBmps(path, true); + ScanThread::numphotoXbmps = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\Y"; + ScanThread::numphotoY = HowManyBmps(path, true); + ScanThread::numphotoYbmps = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\C"; + ScanThread::numphotoC = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\D"; + ScanThread::numphotoD = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\E"; + ScanThread::numphotoE = HowManyBmps(path, false); + path = WGetExecutableFolder() + L"\\F"; + ScanThread::numphotoF = HowManyBmps(path, false); + + if (ScanThread::numphotoA < 0 && ScanThread::numphotoB < 0 && ScanThread::numphotoX < 0 && ScanThread::numphotoY < 0) + { + return false; + } + return true; + } + bool ButtonScanAction(const char key[3], int mode, int serchnum, int startsearch, bool onlysearch, POINT currentpoint, int checkarray) + { + bool found = false; + POINT pt = { 0,0 }; + POINT noeder = { 0,0 }; + int numbmp = 0; + if (ModeScanThread != 2) + { + int numphoto = 0; + if (checkarray == 1) + { //always check static first? + noeder = CheckStatics(key, startsearch); + if (noeder.x != 0) + { + Bmpfound(key, noeder.x, noeder.y, startsearch, onlysearch, true, checkarray); //or not found + found = true; + return true; + } + } + if (!found) + { + for (int i = startsearch; i < serchnum; i++) + { + if (checkarray == 1) + { + noeder = CheckStatics(key, i); + if (noeder.x != 0) + { + Bmpfound(key, noeder.x, noeder.y, i, onlysearch, true, checkarray); //or not found + found = true; + return true; + } + } + std::string path = UGetExecutableFolder() + key + std::to_string(i) + ".bmp"; + std::wstring wpath(path.begin(), path.end()); + // HDC soke; + if (LoadBMP24Bit(wpath.c_str(), smallPixels, smallW, smallH, strideSmall) && !found) + { + if (CaptureWindow24Bit(hwndhandle, screenSize, largePixels, strideLarge, false, ScanThread::resize)) + { + if (onlysearch) + { + if (FindSubImage24(largePixels.data(), screenSize.cx, screenSize.cy, strideLarge, smallPixels.data(), smallW, smallH, strideSmall, pt, currentpoint.x, currentpoint.y)) + { + numphoto = i; + found = true; + break; + } + } + if (found == false) + { + if (FindSubImage24(largePixels.data(), screenSize.cx, screenSize.cy, strideLarge, smallPixels.data(), smallW, smallH, strideSmall, pt, 0, 0)) + { + found = true; + numphoto = i; + break; + } + }//found + } //hbmdessktop + }//loadbmp + } + } + if (!found) + { + for (int i = 0; i < serchnum; i++) + { + if (checkarray == 1) + { + noeder = CheckStatics(key, i); + if (noeder.x != 0) + { + Bmpfound(key, noeder.x, noeder.y, i, onlysearch, true, checkarray); //or not found + found = true; + return true; + } + } + std::string path = UGetExecutableFolder() + key + std::to_string(i) + ".bmp"; + std::wstring wpath(path.begin(), path.end()); + if (LoadBMP24Bit(wpath.c_str(), smallPixels, smallW, smallH, strideSmall) && !found) + { + //ShowMemoryUsageMessageBox(); + if (CaptureWindow24Bit(hwndhandle, screenSize, largePixels, strideLarge, false, ScanThread::resize)) + + {// MessageBox(NULL, "some kind of error", "captured desktop", MB_OK | MB_ICONINFORMATION); + if (FindSubImage24(largePixels.data(), screenSize.cx, screenSize.cy, strideLarge, smallPixels.data(), smallW, smallH, strideSmall, pt, 0, 0)) + { + // MessageBox(NULL, "some kind of error", "found spot", MB_OK | MB_ICONINFORMATION); + found = true; + numphoto = i; + break; + } + } //hbmdessktop + }//loadbmp + } + + } + Bmpfound(key, pt.x, pt.y, numphoto, onlysearch, found, checkarray); //or not found + if (found == true) + return true; + else return false; + } + + // if (mode == 2 && MainThread::showmessage == 0 && onlysearch == false) //mode 2 button mapping //showmessage var to make sure no double map or map while message + // { + // Sleep(100); //to make sure red flicker expired + // std::string path = UGetExecutableFolder() + key + std::to_string(serchnum) + ".bmp"; + // std::wstring wpath(path.begin(), path.end()); + // SaveWindow10x10BMP(hwndhandle, wpath.c_str(), Mouse::Xf, Mouse::Yf); + // // MainThread::showmessage = 10; //signal is saving + // return true; + // } + // else if (MainThread::showmessage != 0) + // MainThread::showmessage = 11;//wait for mesage expire + return true; + } + + DWORD WINAPI ScanThreadMain(LPVOID, int Aisstatic, int Bisstatic, int Xisstatic, int Yisstatic) + { + int scantick = 0; + Sleep(3000); + Astatic = Aisstatic; + Bstatic = Bisstatic; + Xstatic = Xisstatic; + Ystatic = Yisstatic; + //scanrunning = true; + ScanThread::scanloop = true; + while (ScanThread::scanloop) + { + EnterCriticalSection(&ScanThread::critical); + POINT Apos = { ScanThread::PointA.x, ScanThread::PointA.y }; + POINT Bpos = { ScanThread::PointB.x, ScanThread::PointB.y }; + POINT Xpos = { ScanThread::PointX.x, ScanThread::PointX.y }; + POINT Ypos = { ScanThread::PointY.x, ScanThread::PointY.y }; + int startsearchAW = ScanThread::startsearchA; + int startsearchBW = ScanThread::startsearchB; + int startsearchXW = ScanThread::startsearchX; + int startsearchYW = ScanThread::startsearchY; + POINT PointAW = ScanThread::PointA; + POINT PointBW = ScanThread::PointB; + POINT PointXW = ScanThread::PointX; + POINT PointYW = ScanThread::PointY; + ModeScanThread = TranslateXtoMKB::mode; + showmessageScanThread = TranslateXtoMKB::showmessage; + hwndhandle = (HWND)Proto::HwndSelector::GetSelectedHwnd(); + LeaveCriticalSection(&ScanThread::critical); + + if (scantick < 3) + scantick++; + else scantick = 0; + if (PreScanningEnabled) + { + if (scantick == 0 && ScanThread::numphotoA > 0) + { + if (Astatic == 1) + { + if (ScanThread::staticPointA[startsearchAW].x == 0 && ScanThread::staticPointA[startsearchAW].y == 0) + ButtonScanAction("\\A", 1, ScanThread::numphotoA, startsearchAW, true, PointAW, Astatic); + else + Bmpfound("\\A", ScanThread::staticPointA[startsearchAW].x, ScanThread::staticPointA[startsearchAW].y, startsearchAW, true, true, Astatic); + } + else ButtonScanAction("\\A", 1, ScanThread::numphotoA, startsearchAW, true, PointAW, Astatic); + } + + if (scantick == 1 && ScanThread::numphotoB > 0) + { + if (Bstatic == 1) + { + if (ScanThread::staticPointB[startsearchBW].x == 0 && ScanThread::staticPointB[startsearchBW].y == 0) + //MessageBoxA(NULL, "heisann", "A", MB_OK); + ButtonScanAction("\\B", 1, ScanThread::numphotoB, startsearchBW, true, PointAW, Bstatic); + else + Bmpfound("\\B", ScanThread::staticPointB[startsearchBW].x, ScanThread::staticPointB[startsearchBW].y, startsearchBW, true, true, Bstatic); + } + else ButtonScanAction("\\B", 1, ScanThread::numphotoB, startsearchBW, true, PointBW, Bstatic); + + } + if (scantick == 2 && ScanThread::numphotoX > 0) + { + if (Xstatic == 1) + { + if (ScanThread::staticPointX[startsearchXW].x == 0 && ScanThread::staticPointX[startsearchXW].y == 0) + ButtonScanAction("\\X", 1, ScanThread::numphotoX, startsearchXW, true, PointXW, Xstatic); + else Bmpfound("\\X", ScanThread::staticPointX[startsearchXW].x, ScanThread::staticPointX[startsearchXW].y, startsearchXW, true, true, Xstatic); + } + else ButtonScanAction("\\X", 1, ScanThread::numphotoX, startsearchXW, true, PointXW, Xstatic); + + } + if (scantick == 3 && ScanThread::numphotoY > 0) + { + if (Ystatic == 1) + { + if (ScanThread::staticPointY[startsearchYW].x == 0 && ScanThread::staticPointY[startsearchYW].y == 0) + //MessageBoxA(NULL, "heisann", "A", MB_OK); + ButtonScanAction("\\Y", 1, ScanThread::numphotoY, startsearchYW, true, PointYW, Ystatic); + else + Bmpfound("\\Y", ScanThread::staticPointY[startsearchYW].x, ScanThread::staticPointY[startsearchYW].y, startsearchYW, true, true, Ystatic); + } + ButtonScanAction("\\Y", 1, ScanThread::numphotoY, startsearchYW, true, PointYW, Ystatic); + } + Sleep(10); + } + //else Sleep(1000); + } + return 0; + } + + bool ScanThread::ButtonPressed(UINT buttonFlagg) + { + bool returnedvalue = false; + if (buttonFlagg == 0) + { + if (!PreScanningEnabled) { + returnedvalue = ButtonScanAction("\\A", ModeScanThread, ScanThread::numphotoA, ScanThread::startsearchA, false, { 0,0 }, Astatic);//buttonacton will be occupied by scanthread + } + else + { + EnterCriticalSection(&ScanThread::critical); + POINT Cpoint; + Cpoint.x = ScanThread::PointA.x; + Cpoint.y = ScanThread::PointA.y; + if (Cpoint.x != 0 && Cpoint.y != 0) + { + if (ScanThread::ShoulderNextBMP == 0) + { + if (ScanThread::startsearchA < ScanThread::numphotoA - 1) + ScanThread::startsearchA++; //dont want it to update before input done + else ScanThread::startsearchA = 0; + ScanThread::PointA.x = 0; + ScanThread::PointA.y = 0; + } + BmpInputAction(Cpoint.x, Cpoint.y, scanAtype); + returnedvalue = true; + + } + LeaveCriticalSection(&ScanThread::critical); + } + if (ModeScanThread == 2 && showmessageScanThread != 11) + { + ScanThread::numphotoA++; + Sleep(500); + } + } + if (buttonFlagg == 1) + { + if (!PreScanningEnabled) { + returnedvalue = ButtonScanAction("\\B", ModeScanThread, ScanThread::numphotoB, ScanThread::startsearchB, false, { 0,0 }, Bstatic);//buttonacton will be occupied by scanthread + } + else + { + EnterCriticalSection(&ScanThread::critical); + POINT Cpoint; + Cpoint.x = ScanThread::PointB.x; + Cpoint.y = ScanThread::PointB.y; + if (Cpoint.x != 0 && Cpoint.y != 0) + { + if (ScanThread::ShoulderNextBMP == 0) + { + if (ScanThread::startsearchB < ScanThread::numphotoB - 1) + ScanThread::startsearchB++; //dont want it to update before input done + else ScanThread::startsearchB = 0; + ScanThread::PointA.x = 0; + ScanThread::PointA.y = 0; + } + BmpInputAction(Cpoint.x, Cpoint.y, ScanThread::scanBtype); + returnedvalue = true; + } + LeaveCriticalSection(&ScanThread::critical); + } + if (ModeScanThread == 2 && showmessageScanThread != 11) + { + ScanThread::numphotoB++; + Sleep(500); + } + } + if (buttonFlagg == 2) + { + if (!PreScanningEnabled) { + returnedvalue = ButtonScanAction("\\X", ModeScanThread, ScanThread::numphotoX, ScanThread::startsearchX, false, { 0,0 }, Xstatic);//buttonacton will be occupied by scanthread + } + else + { + EnterCriticalSection(&ScanThread::critical); + POINT Cpoint; + Cpoint.x = ScanThread::PointX.x; + Cpoint.y = ScanThread::PointX.y; + + if (Cpoint.x != 0 && Cpoint.y != 0) + { + if (ScanThread::ShoulderNextBMP == 0) + { + if (ScanThread::startsearchX < ScanThread::numphotoX - 1) + ScanThread::startsearchX++; //dont want it to update before input done + else ScanThread::startsearchX = 0; + ScanThread::PointX.x = 0; + ScanThread::PointX.y = 0; + } + BmpInputAction(Cpoint.x, Cpoint.y, ScanThread::scanXtype); + returnedvalue = true; + + } + LeaveCriticalSection(&ScanThread::critical); + } + if (ModeScanThread == 2 && showmessageScanThread != 11) + { + ScanThread::numphotoX++; + Sleep(500); + } + } + if (buttonFlagg == 3) + { + if (!PreScanningEnabled) { + returnedvalue = ButtonScanAction("\\Y", ModeScanThread, ScanThread::numphotoY, ScanThread::startsearchY, false, { 0,0 }, Ystatic);//buttonacton will be occupied by scanthread + } + else + { + EnterCriticalSection(&ScanThread::critical); + POINT Cpoint; + Cpoint.x = ScanThread::PointY.x; + Cpoint.y = ScanThread::PointY.y; + + //LeaveCriticalSection(&critical); + if (Cpoint.x != 0 && Cpoint.y != 0) + { + if (ScanThread::ShoulderNextBMP == 0) + { + if (ScanThread::startsearchY < ScanThread::numphotoY - 1) + ScanThread::startsearchY++; //dont want it to update before input done + else ScanThread::startsearchY = 0; + PointY.x = 0; + PointY.y = 0; + } + BmpInputAction(Cpoint.x, Cpoint.y, ScanThread::scanYtype); + returnedvalue = true; + + } + LeaveCriticalSection(&critical); + } + if (ModeScanThread == 2 && showmessageScanThread != 11) + { + ScanThread::numphotoY++; + Sleep(500); + } + } + if (buttonFlagg == 4) //C + { + if (!PreScanningEnabled) + { + EnterCriticalSection(&ScanThread::critical); + returnedvalue = ButtonScanAction("\\C", ModeScanThread, ScanThread::numphotoC, ScanThread::startsearchC, false, { 0,0 }, false); //2 save bmps + LeaveCriticalSection(&ScanThread::critical); + } + else if (ScanThread::ShoulderNextBMP == 1) + { + EnterCriticalSection(&ScanThread::critical); + if (ScanThread::startsearchA < ScanThread::numphotoA - 1) + ScanThread::startsearchA++; //dont want it to update before input done + else ScanThread::startsearchA = 0; + if (ScanThread::startsearchB < ScanThread::numphotoB - 1) + ScanThread::startsearchB++; //dont want it to update before input done + else ScanThread::startsearchB = 0; + if (ScanThread::startsearchX < ScanThread::numphotoX - 1) + ScanThread::startsearchX++; //dont want it to update before input done + else ScanThread::startsearchX = 0; + LeaveCriticalSection(&ScanThread::critical); + } + if (ModeScanThread == 2 && showmessageScanThread != 11) + { + ScanThread::numphotoC++; + Sleep(500); + } + + } + if (buttonFlagg == 5) //D + { + if (!PreScanningEnabled) + { + EnterCriticalSection(&ScanThread::critical); + returnedvalue = ButtonScanAction("\\D", ModeScanThread, ScanThread::numphotoD, ScanThread::startsearchD, false, { 0,0 }, false); //2 save bmps + LeaveCriticalSection(&ScanThread::critical); + } + else if (ScanThread::ShoulderNextBMP == 1) + { + + EnterCriticalSection(&ScanThread::critical); + if (ScanThread::startsearchA > 0) + ScanThread::startsearchA--; + else ScanThread::startsearchA = ScanThread::numphotoA - 1; + if (ScanThread::startsearchB > 0) + ScanThread::startsearchB--; + else ScanThread::startsearchB = ScanThread::numphotoB - 1; + if (ScanThread::startsearchX > 0) + ScanThread::startsearchX--; + else ScanThread::startsearchX = ScanThread::numphotoX - 1; + if (ScanThread::startsearchY > 0) + ScanThread::startsearchY--; + else ScanThread::startsearchY = ScanThread::numphotoY - 1; + LeaveCriticalSection(&ScanThread::critical); + } + //else MessageBoxA(NULL, "heisann2", "A", MB_OK); + if (ModeScanThread == 2 && showmessageScanThread != 11) + { + ScanThread::numphotoD++; + Sleep(500); + } + + } + if (buttonFlagg == 6) //E + { + // MessageBoxA(NULL, "heisann", "RSB", MB_OK); + if (!PreScanningEnabled) + { + EnterCriticalSection(&critical); + returnedvalue = ButtonScanAction("\\E", ModeScanThread, ScanThread::numphotoD, ScanThread::startsearchD, false, { 0,0 }, false); //2 save bmps + LeaveCriticalSection(&critical); + } + if (ModeScanThread == 2 && showmessageScanThread != 11) + { + ScanThread::numphotoE++; + Sleep(500); + } + } + if (buttonFlagg == 7) //F + { + //MessageBoxA(NULL, "heisann", "LSB", MB_OK); + if (!PreScanningEnabled) + { + EnterCriticalSection(&critical); + returnedvalue = ButtonScanAction("\\F", ModeScanThread, ScanThread::numphotoF, ScanThread::startsearchF, false, { 0,0 }, false); //2 save bmps + LeaveCriticalSection(&critical); + } + if (ModeScanThread == 2 && showmessageScanThread != 11) + { + ScanThread::numphotoF++; + Sleep(500); + } + } + return returnedvalue; + + } + + + void ScanThread::StartScanThread(HMODULE hmodule, int Astatic, int Bstatic, int Xstatic, int Ystatic, bool prescan) { + PreScanningEnabled = prescan; + std::thread tree(ScanThreadMain, hmodule, Astatic, Bstatic, Xstatic, Ystatic); + tree.detach(); + } + + +}; \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/ScanThread.h b/src/ProtoInput/ProtoInputHooks/ScanThread.h new file mode 100644 index 0000000..c3f07d1 --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/ScanThread.h @@ -0,0 +1,28 @@ +#pragma once +//#include "HandleMainWindow.h" + + +namespace ScreenshotInput { + + class ScanThread { + public: + static CRITICAL_SECTION critical; //window thread + static int scanAtype, scanBtype, scanXtype, scanYtype, Ctype, Dtype, Etype, Ftype; + static int numphotoA, numphotoB, numphotoX, numphotoY, numphotoC, numphotoD, numphotoE, numphotoF; + static int numphotoAbmps, numphotoBbmps, numphotoXbmps, numphotoYbmps; + static int Aisstatic, Bisstatic, Xisstatic, Yisstatic; + static POINT PointA, PointB, PointX, PointY; + static int startsearchA, startsearchB, startsearchX, startsearchY, startsearchC, startsearchD, startsearchE, startsearchF; + static std::vector staticPointA, staticPointB, staticPointX, staticPointY; + static bool scanloop; + static int scanoption; + static int ShoulderNextBMP; + static int resize; + static int ignorerect; + static void StartScanThread(HMODULE hmodule, int Astatic, int Bstatic, int Xstatic, int Ystatic, bool prescan); + + static bool enumeratebmps(); //false if no bmps found + static bool initovector(); + static bool ButtonPressed(UINT buttonFlag); + }; +} \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp index 51f5041..63d7881 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -25,9 +25,10 @@ #include #include "HwndSelector.h" #include "FakeCursor.h" +#include "Gui.h" #include "GtoMnK_RawInput.h" #include "FakeMouseKeyboard.h" -//#include "RawInput.h" +#include "ScanThread.h" //#include #pragma comment(lib, "dwmapi.lib") #include @@ -64,9 +65,10 @@ namespace ScreenshotInput int TranslateXtoMKB::optionmapping; int TranslateXtoMKB::startmapping; bool TranslateXtoMKB::lefthanded; + int TranslateXtoMKB::mode = 1; int updatewindowtick = 300; - int mode = 1; + int AxisLeftsens; int AxisRightsens; int AxisUpsens; @@ -86,16 +88,16 @@ namespace ScreenshotInput bool rightPressedold = false; HMODULE g_hModule = nullptr; - - CRITICAL_SECTION critical; //window thread - bool loop = true; - int showmessage = 0; //0 = no message, 1 = initializing, 2 = bmp mode, 3 = bmp and cursor mode, 4 = edit mode + //CRITICAL_SECTION critical; //window thread + int TranslateXtoMKB::showmessage = 0; //0 = no message, 1 = initializing, 2 = bmp mode, 3 = bmp and cursor mode, 4 = edit mode + int counter = 0; + bool oldhome = false; //toggle lock input with home key - - //syncronization control - HANDLE hMutex; + //copy of criticals + int showmessageMT; + int modeMT; POINT delta; //hooks @@ -125,11 +127,25 @@ namespace ScreenshotInput bool oldup = false; bool oldleft = false; bool oldright = false; + bool oldoptions = false; + bool oldstart = false; + bool oldstartoptions = false; + bool oldscrolldown = false; + bool oldscrollleft = false; + bool oldscrollright = false; + bool oldscrollup = false; // Add a fake key event to the array - - bool SendMouseClick(int x, int y, int z) { + USHORT lastVKkey = 0; + bool IsKeyPressed(int Vkey) + { + SHORT hmm = GetKeyState(Vkey); + if (hmm > 0) + return true; + else return false; + } + void TranslateXtoMKB::SendMouseClick(int x, int y, int z) { // Create a named mutex RAWMOUSE muusjn = { 0 }; POINT heer; @@ -140,8 +156,8 @@ namespace ScreenshotInput if (z == 3) { muusjn.usButtonFlags |= RI_MOUSE_LEFT_BUTTON_DOWN; - Proto::FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_LBUTTON, true); RawInput::GenerateRawMouseButton(-1, true); + Proto::FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_LBUTTON, true); //last originally } if (z == 4) { @@ -171,7 +187,6 @@ namespace ScreenshotInput } Proto::RawInput::SendInputMessages(muusjn); - return true; } void ButtonStateImpulse(int vk, bool state) @@ -209,7 +224,7 @@ namespace ScreenshotInput RawInput::GenerateRawKey(vk, state, false); } - std::string UGetExecutableFolder() { + std::string UGetExeFolder() { char path[MAX_PATH]; GetModuleFileNameA(NULL, path, MAX_PATH); @@ -220,7 +235,7 @@ namespace ScreenshotInput } - std::wstring WGetExecutableFolder() { + std::wstring WGetExeFolder() { wchar_t path[MAX_PATH]; GetModuleFileNameW(NULL, path, MAX_PATH); std::wstring exePath(path); @@ -320,7 +335,7 @@ namespace ScreenshotInput char buffer[16]; //or only 4 maybe // settings reporting - std::string iniPath = UGetExecutableFolder() + "\\Xinput.ini"; + std::string iniPath = UGetExeFolder() + "\\Xinput.ini"; std::string iniSettings = "Settings"; return true; @@ -328,14 +343,47 @@ namespace ScreenshotInput void ThreadFunction(HMODULE hModule) { Proto::AddThreadToACL(GetCurrentThreadId()); - Sleep(2000); if (readsettings() == false) { //messagebox? settings not read } + + InitializeCriticalSection(&ScanThread::critical); + ScanThread::scanoption = 1; + if (!ScanThread::enumeratebmps()) //false means no bmps found. also counts statics + { + // LOG("BMPs enumerated but not found: 0x%p", hwnd); + if (ScanThread::scanoption == 1) + { + ScanThread::scanoption = 0; + // LOG("Error. Nothing to scan for. Disabling scanoption: 0x%p", hwnd); + } + } + else { + // LOG("BMPs found: 0x%p", hwnd); + ScanThread::staticPointA.assign(ScanThread::numphotoA + 1, POINT{ 0, 0 }); + ScanThread::staticPointB.assign(ScanThread::numphotoB + 1, POINT{ 0, 0 }); + ScanThread::staticPointX.assign(ScanThread::numphotoX + 1, POINT{ 0, 0 }); + ScanThread::staticPointY.assign(ScanThread::numphotoY + 1, POINT{ 0, 0 }); + } + ScanThread::initovector(); + if (ScanThread::scanoption == 1) + { //starting bmp continous scanner + ScanThread::StartScanThread(g_hModule, ScanThread::Aisstatic, ScanThread::Bisstatic, ScanThread::Xisstatic, ScanThread::Yisstatic, ScanThread::scanoption); + // LOG("BMP scanner started: 0x%p", hwnd); + } + while (loop == true) { + //copy criticals + EnterCriticalSection(&ScanThread::critical); + showmessageMT = TranslateXtoMKB::showmessage; + modeMT = TranslateXtoMKB::mode; + + + + LeaveCriticalSection(&ScanThread::critical); movedmouse = false; //reset XINPUT_STATE state; ZeroMemory(&state, sizeof(XINPUT_STATE)); @@ -345,7 +393,7 @@ namespace ScreenshotInput { WORD buttons = state.Gamepad.wButtons; - if (mode > 0) + if (modeMT > 0) { //fake cursor poll int Xaxis = 0; @@ -371,7 +419,6 @@ namespace ScreenshotInput scrollYaxis = state.Gamepad.sThumbRY; } - delta = CalculateUltimateCursorMove( Xaxis, Yaxis, radial_deadzone, axial_deadzone, max_threshold, @@ -386,7 +433,7 @@ namespace ScreenshotInput if (movedmouse == true) //fake cursor move message { - SendMouseClick(delta.x, delta.y, 8); + TranslateXtoMKB::SendMouseClick(delta.x, delta.y, 8); Proto::FakeCursor::NotifyUpdatedCursorPosition(); } @@ -396,7 +443,7 @@ namespace ScreenshotInput if (!leftPressed) { - SendMouseClick(Xf, Yf, 6); //double click + TranslateXtoMKB::SendMouseClick(Xf, Yf, 6); //double click leftPressedold = false; } } @@ -404,7 +451,7 @@ namespace ScreenshotInput { if (leftPressedold == false) { - SendMouseClick(Xf, Yf, 5); //4 skal vere 3 + TranslateXtoMKB::SendMouseClick(Xf, Yf, 5); //4 skal vere 3 leftPressedold = true; } } @@ -413,7 +460,7 @@ namespace ScreenshotInput { if (!rightPressed) { - SendMouseClick(Xf, Yf, 4); + TranslateXtoMKB::SendMouseClick(Xf, Yf, 4); rightPressedold = false; } } //if rightpress @@ -421,13 +468,78 @@ namespace ScreenshotInput { if (rightPressedold == false) { - SendMouseClick(Xf, Yf, 3); + TranslateXtoMKB::SendMouseClick(Xf, Yf, 3); rightPressedold = true; } } //buttons + if (oldscrollleft) + { + if (scrollXaxis < AxisLeftsens) //left + { + } + else { + oldscrollleft = false; + ButtonStateImpulse(TranslateXtoMKB::stickleftmapping, false);//down + } + } + else if (scrollXaxis < AxisLeftsens) //left + { + oldscrollleft = true; + + ButtonStateImpulse(TranslateXtoMKB::stickleftmapping, true);//down + } + + if (oldscrollright) + { + if (scrollXaxis > AxisRightsens) //left + { + } + else { + oldscrollright = false; + ButtonStateImpulse(TranslateXtoMKB::stickrightmapping, false);//down + } + } + else if (scrollXaxis > AxisRightsens) //left + { + oldscrollright = true; + ButtonStateImpulse(TranslateXtoMKB::stickrightmapping, true);//down + } + + if (oldscrollup) + { + if (scrollXaxis > AxisUpsens) //left + { + } + else { + oldscrollup = false; + ButtonStateImpulse(TranslateXtoMKB::stickupmapping, false);//down + } + } + else if (scrollXaxis > AxisUpsens) //left + { + oldscrollup = true; + ButtonStateImpulse(TranslateXtoMKB::stickupmapping, true);//down + } + + if (oldscrolldown) + { + if (scrollXaxis < AxisDownsens) //left + { + } + else { + oldscrolldown = false; + ButtonStateImpulse(TranslateXtoMKB::stickdownmapping, false);//down + } + } + else if (scrollXaxis < AxisDownsens) //left + { + oldscrolldown = true; + ButtonStateImpulse(TranslateXtoMKB::stickdownmapping, true);//down + } + if (oldA) { if (buttons & XINPUT_GAMEPAD_A) @@ -435,13 +547,16 @@ namespace ScreenshotInput } else{ oldA = false; + ButtonStateImpulse(TranslateXtoMKB::Amapping, false);//release } } else if (buttons & XINPUT_GAMEPAD_A) { oldA = true; - ButtonStateImpulse(TranslateXtoMKB::Amapping, true);//down + bool found = ScanThread::ButtonPressed(0); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::Amapping, true);//down } @@ -458,7 +573,9 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_B) { oldB = true; - ButtonStateImpulse(TranslateXtoMKB::Bmapping, true);//down + bool found = ScanThread::ButtonPressed(1); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::Bmapping, true);//down } @@ -475,7 +592,9 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_X) { oldX = true; - ButtonStateImpulse(TranslateXtoMKB::Xmapping, true);//down + bool found = ScanThread::ButtonPressed(2); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::Xmapping, true);//down } @@ -492,7 +611,9 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_Y) { oldY = true; - ButtonStateImpulse(TranslateXtoMKB::Ymapping, true);//down + bool found = ScanThread::ButtonPressed(3); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::Ymapping, true);//down } @@ -509,7 +630,9 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) { oldC = true; - ButtonStateImpulse(TranslateXtoMKB::RSmapping, true); //down + bool found = ScanThread::ButtonPressed(4); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::RSmapping, true); //down } @@ -526,7 +649,9 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) { oldD = true; - ButtonStateImpulse(TranslateXtoMKB::LSmapping, true);//down + bool found = ScanThread::ButtonPressed(5); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::LSmapping, true);//down } @@ -597,30 +722,87 @@ namespace ScreenshotInput ButtonStateImpulse(TranslateXtoMKB::downmapping, true);//down } + if (oldstartoptions) + { + if (oldstart && oldoptions) + { + } + else oldstartoptions = false; + } + else if (oldstart && oldoptions)//gui + { + Proto::ToggleWindow(); + oldstartoptions = true; + // oldstart = false; + // oldoptions = false; + } + if (oldstart) + { + if (buttons & XINPUT_GAMEPAD_START) + { + } + else { + oldstart = false; + ButtonStateImpulse(TranslateXtoMKB::startmapping, false);//release + } + } + else if (buttons & XINPUT_GAMEPAD_START) + { + oldstart = true; + ButtonStateImpulse(TranslateXtoMKB::startmapping, true);//down + } + + if (oldoptions) + { + if (buttons & XINPUT_GAMEPAD_BACK) + { + } + else { + oldoptions = false; + ButtonStateImpulse(TranslateXtoMKB::optionmapping, false);//release + } + } + else if (buttons & XINPUT_GAMEPAD_BACK) + { + oldoptions = true; + ButtonStateImpulse(TranslateXtoMKB::optionmapping, true);//down + } + } //if mode above 0 } //if controller - else { - showmessage = 12; - } - - if (TranslateXtoMKB::rawinputhook == 1) - { - + else { //no controller + showmessageMT = 12; + EnterCriticalSection(&ScanThread::critical); + TranslateXtoMKB::showmessage = 12; + LeaveCriticalSection(&ScanThread::critical); } if (tick < updatewindowtick) tick++; - else { + else { //need to update hwnd and bounds periodically Proto::HwndSelector::UpdateMainHwnd(false); Proto::HwndSelector::UpdateWindowBounds(); tick = 0; } - - if (mode == 0) + EnterCriticalSection(&ScanThread::critical); + if (showmessageMT != 0) { //drawing messages or something + if (counter < 400) { //showmessage is critical + counter++; + } + else { + showmessageMT = 0; + EnterCriticalSection(&ScanThread::critical); + TranslateXtoMKB::showmessage = 0; + LeaveCriticalSection(&ScanThread::critical); + counter = 0; + } + } + LeaveCriticalSection(&ScanThread::critical); + if (modeMT == 0) Sleep(10); - if (mode > 0) { + if (modeMT > 0) { Sleep(1); } - if (showmessage == 99) + if (showmessageMT == 99) Sleep(15); } //loop end but endless return; @@ -630,7 +812,7 @@ namespace ScreenshotInput { RawInput::Initialize(); g_hModule = hModule; - InitializeCriticalSection(&critical); + std::thread one(ThreadFunction, g_hModule); one.detach(); return; diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h index 59de6ca..fbc94a0 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h @@ -12,10 +12,12 @@ namespace ScreenshotInput public: static void Initialize(HMODULE g_hModule); + static void SendMouseClick(int x, int y, int z); static int controllerID; static bool rawinputhook; static bool registerrawinputhook; - + static int showmessage; + static int mode; static int Amapping; static int Bmapping; static int Xmapping; diff --git a/src/ProtoInput/ProtoInputHost/Gui.cpp b/src/ProtoInput/ProtoInputHost/Gui.cpp index 8c20a67..7f86b98 100644 --- a/src/ProtoInput/ProtoInputHost/Gui.cpp +++ b/src/ProtoInput/ProtoInputHost/Gui.cpp @@ -11,7 +11,6 @@ #include "RawInput.h" #include "protoloader.h" #include "Profiles.h" -#include "RawInput.h" #include "MessageList.h" namespace ProtoHost @@ -52,6 +51,10 @@ StartupInjectionType selectedStartupInjectionType = StartupInjectionType::EASYHO std::vector trackedInstanceHandles{}; static bool isInputCurrentlyLocked = false; + +//TranslateXtoMKB +float Sensitivitymultiplier = 3.5f; +float Sensitivity = 15.0f; std::string VkToKeyName(int vk) { @@ -717,9 +720,6 @@ void SelectedInstanceWindow() ImGui::Spacing(); ImGui::TextWrapped("Controller index"); ImGui::Separator(); - ImGui::Spacing(); - ImGui::Checkbox("Use OpenXinput", ¤tProfile.useOpenXinput); // - ImGui::Separator(); ImGui::TextWrapped("If Translate X to MKB is selected, then it will emulate mouse and keyboard from selected ControllerIndex." "Option will automatically deactivate if a keyboard or mouse is selected for the instance. " "Also you should make sure ControllerIndex is not zero, as zero still implies no controller" @@ -1202,6 +1202,13 @@ void SelectedInstanceWindow() ImGui::Separator(); ImGui::Checkbox("Lefthanded Stick. moves mouse with left stick and button map on right stick. or opposite if disabled", ¤tProfile.XinputtoMKBstickinvert); // ImGui::Separator(); + ImGui::Separator(); + ImGui::TextWrapped("Sensitivity"); + ImGui::SliderFloat("Slider", &Sensitivity, 0.0f, 40.0f); + ImGui::Separator(); + ImGui::TextWrapped("Sensitivity Multiplier"); + ImGui::SliderFloat("Slider", &Sensitivitymultiplier, 1.0f, 20.0f); + ImGui::Separator(); ImGui::PopID(); } @@ -1394,6 +1401,7 @@ void OptionsMenu() ImGui::Checkbox(hook.uiLabel.c_str(), &hook.enabled); } } + ImGui::Checkbox("Use OpenXinput", ¤tProfile.useOpenXinput); ImGui::Checkbox("Dinput to Xinput redirection", ¤tProfile.dinputToXinputRedirection); diff --git a/src/ProtoInput/ProtoInputHost/Profiles.h b/src/ProtoInput/ProtoInputHost/Profiles.h index 17327ea..881cd94 100644 --- a/src/ProtoInput/ProtoInputHost/Profiles.h +++ b/src/ProtoInput/ProtoInputHost/Profiles.h @@ -98,7 +98,7 @@ struct Profile bool showCursorWhenImageUpdated = false; - bool putMouseInsideWindow = false; + bool putMouseInsideWindow = true; bool drawFakeMouseCursor = true; bool drawFakeCursorFix = false; diff --git a/src/ProtoInput/ProtoInputHost/RawInput.cpp b/src/ProtoInput/ProtoInputHost/RawInput.cpp index 34f8285..ef14636 100644 --- a/src/ProtoInput/ProtoInputHost/RawInput.cpp +++ b/src/ProtoInput/ProtoInputHost/RawInput.cpp @@ -49,19 +49,6 @@ void ProcessRawInput(HRAWINPUT rawInputHandle) (rawinput.data.keyboard.Flags & RI_KEY_BREAK) == 0) // key down { USHORT vkey = rawinput.data.keyboard.VKey; - //if (vkey == VK_LEFT) - // MessageBoxA(nullptr, "E0 key detected", "Info", MB_OK); - // If VKey is missing or invalid, reconstruct it - //if (vkey == 0 || vkey == 255) - //{ - // if ((rawinput.data.keyboard.Flags & RI_KEY_E0) != 0) - // { - // vkey = MapVirtualKey(rawinput.data.keyboard.MakeCode, MAPVK_VSC_TO_VK_EX); - - // } - // else - // vkey = MapVirtualKey(rawinput.data.keyboard.MakeCode, MAPVK_VSC_TO_VK); - //} lastVKcode = vkey; lastKeypressKeyboardHandle = (intptr_t)rawinput.header.hDevice; } From 876b31b8d62c05b225e5028d0526364d0f4f0d53 Mon Sep 17 00:00:00 2001 From: messenils Date: Mon, 9 Feb 2026 22:24:44 +0100 Subject: [PATCH 07/20] important. reverted something in inputlock i shouldnt touch --- src/ProtoInput/ProtoInputUtil/InputLocker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ProtoInput/ProtoInputUtil/InputLocker.cpp b/src/ProtoInput/ProtoInputUtil/InputLocker.cpp index 006a393..f6356bb 100644 --- a/src/ProtoInput/ProtoInputUtil/InputLocker.cpp +++ b/src/ProtoInput/ProtoInputUtil/InputLocker.cpp @@ -13,7 +13,7 @@ LRESULT CALLBACK LowLevelMouseProc( ) { //TODO: change wparam/lparam instead of blocking - return CallNextHookEx(nullptr, nCode, wParam, lParam);// isLocked ? 1 : + return isLocked ? 1 : CallNextHookEx(nullptr, nCode, wParam, lParam); } LRESULT CALLBACK LowLevelKeyboardProc( @@ -75,7 +75,7 @@ extern "C" __declspec(dllexport) unsigned int LockInput(bool lock) if (lock && !installedHooks) { installedHooks = true; - //SetWindowsHookExW(WH_MOUSE_LL, LowLevelMouseProc, GetModuleHandle(0), 0); + SetWindowsHookExW(WH_MOUSE_LL, LowLevelMouseProc, GetModuleHandle(0), 0); SetWindowsHookExW(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(0), 0); } From 7d4fef163bef0d3d00462408c309e246fb0091c0 Mon Sep 17 00:00:00 2001 From: messenils Date: Tue, 10 Feb 2026 08:35:14 +0100 Subject: [PATCH 08/20] fixed coordinate redraw on window move. added some of the scanning options to GUI --- src/ProtoInput/ProtoInputHooks/FakeCursor.cpp | 19 ++-- src/ProtoInput/ProtoInputHooks/Gui.cpp | 6 +- .../ProtoInputHooks/PipeCommunication.cpp | 69 ++++++++------ src/ProtoInput/ProtoInputHooks/ScanThread.cpp | 15 ++-- src/ProtoInput/ProtoInputHooks/ScanThread.h | 7 +- .../ProtoInputHooks/TranslateXtoMKB.cpp | 16 ++-- .../ProtoInputHooks/pipeinclude/pipeinclude.h | 59 +++++++----- src/ProtoInput/ProtoInputHost/Gui.cpp | 42 ++++++--- src/ProtoInput/ProtoInputHost/Profiles.h | 9 +- src/ProtoInput/ProtoInputLoader/Inject.cpp | 89 ++++++++++++------- .../ProtoInputLoader/include/protoloader.h | 8 +- 11 files changed, 212 insertions(+), 127 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp index 3f4e693..cf480d2 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp @@ -114,29 +114,37 @@ void DrawPinkSquare(HDC hdc, int x, int y) SelectObject(hdc, hOldPen); DeleteObject(hPen); } +POINT OldTestpos = { 0,0 }; void DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, POINT spotY, HBRUSH Brush) { - + bool windowmoved = false; bool erased = false; - if (OldspotA.x != spotA.x || OldspotA.y != spotA.y) + //detect window change pos + POINT testpos; + ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &testpos); + if (testpos.x < OldTestpos.x || testpos.y < OldTestpos.y || testpos.x > OldTestpos.x || testpos.y > OldTestpos.y) + { + windowmoved = true; + } + if (OldspotA.x != spotA.x || OldspotA.y != spotA.y || windowmoved) { RECT fill{ OldspotA.x - 20, OldspotA.y - 20, OldspotA.x + 20, OldspotA.y + 20 }; FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! erased = true; } - if (OldspotB.x != spotB.x || OldspotB.y != spotB.y) + if (OldspotB.x != spotB.x || OldspotB.y != spotB.y || windowmoved) { RECT fill{ OldspotB.x - 20, OldspotB.y - 20, OldspotB.x + 20, OldspotB.y + 20 }; FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! erased = true; } - if (OldspotX.x != spotX.x || OldspotX.y != spotX.y) + if (OldspotX.x != spotX.x || OldspotX.y != spotX.y || windowmoved) { RECT fill{ OldspotX.x - 20, OldspotX.y - 20, OldspotX.x + 20, OldspotX.y + 20 }; FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! erased = true; } - if (OldspotY.x != spotY.x || OldspotY.y != spotY.y) + if (OldspotY.x != spotY.x || OldspotY.y != spotY.y || windowmoved) { RECT fill{ OldspotY.x - 20, OldspotY.y - 20, OldspotY.x + 20, OldspotY.y + 20 }; FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! @@ -167,6 +175,7 @@ void DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, POINT spotY, OldspotB = spotB; OldspotX = spotX; OldspotY = spotY; + OldTestpos = testpos; } void FakeCursor::DrawCursor() { diff --git a/src/ProtoInput/ProtoInputHooks/Gui.cpp b/src/ProtoInput/ProtoInputHooks/Gui.cpp index 95cb275..c6173ab 100644 --- a/src/ProtoInput/ProtoInputHooks/Gui.cpp +++ b/src/ProtoInput/ProtoInputHooks/Gui.cpp @@ -14,6 +14,7 @@ #include "StateInfo.h" #include "FakeCursor.h" #include "TranslateXtoMKB.h" +#include "ScanThread.h" #include "GtoMnK_RawInput.h" namespace Proto @@ -663,6 +664,9 @@ void XTranslateMenu() ImGui::Separator(); //no idea if this may crash. suppose it is not safe ImGui::Checkbox("Lefthanded Stick. moves mouse with left stick and button map on right stick. or opposite if disabled", &ScreenshotInput::TranslateXtoMKB::lefthanded); // ImGui::Separator(); + ImGui::Separator(); + ImGui::Checkbox("Shoulder Swap BMPs", &ScreenshotInput::ScanThread::ShoulderNextBMP); // + ImGui::Separator(); } void HooksMenu() { @@ -821,7 +825,7 @@ void RawInputMenu() } void ControlsMenu() -{ +{ if (ImGui::Button("Hide GUI")) { SetWindowVisible(false); diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index 3c82b37..f9b78db 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -27,6 +27,7 @@ #include "AdjustWindowRectHook.h" #include "RemoveBorderHook.h" #include "TranslateXtoMKB.h" +#include "ScanThread.h" namespace Proto { @@ -164,35 +165,7 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) else printf("TranslateXtoMKB is set to false"); break; } - case ProtoPipe::PipeMessageType::SetXinputtoMKBkeys: - { - const auto body = reinterpret_cast(messageBuffer); - printf("Received TranslateXtoMKB Mapping"); - ScreenshotInput::TranslateXtoMKB::Amapping = body->XinputtoMKBAkey; - ScreenshotInput::TranslateXtoMKB::Bmapping = body->XinputtoMKBBkey; - ScreenshotInput::TranslateXtoMKB::Xmapping = body->XinputtoMKBXkey; - ScreenshotInput::TranslateXtoMKB::Ymapping = body->XinputtoMKBYkey; - ScreenshotInput::TranslateXtoMKB::RSmapping = body->XinputtoMKBRSkey; - ScreenshotInput::TranslateXtoMKB::LSmapping = body->XinputtoMKBLSkey; - ScreenshotInput::TranslateXtoMKB::RSmapping = body->XinputtoMKBRSkey; - - ScreenshotInput::TranslateXtoMKB::rightmapping = body->XinputtoMKBrightkey; - ScreenshotInput::TranslateXtoMKB::leftmapping = body->XinputtoMKBleftkey; - ScreenshotInput::TranslateXtoMKB::upmapping = body->XinputtoMKBupkey; - ScreenshotInput::TranslateXtoMKB::downmapping = body->XinputtoMKBdownkey; - - ScreenshotInput::TranslateXtoMKB::stickRpressmapping = body->XinputtoMKBstickR; - ScreenshotInput::TranslateXtoMKB::stickLpressmapping = body->XinputtoMKBstickL; - ScreenshotInput::TranslateXtoMKB::stickrightmapping = body->XinputtoMKBstickright; - ScreenshotInput::TranslateXtoMKB::stickleftmapping = body->XinputtoMKBstickleft; - ScreenshotInput::TranslateXtoMKB::stickupmapping = body->XinputtoMKBstickup; - ScreenshotInput::TranslateXtoMKB::stickdownmapping = body->XinputtoMKBstickdown; - ScreenshotInput::TranslateXtoMKB::optionmapping = body->XinputtoMKBoption; - ScreenshotInput::TranslateXtoMKB::startmapping = body->XinputtoMKBstart; - ScreenshotInput::TranslateXtoMKB::lefthanded = body->XinputtoMKBstickinvert; - break; - } case ProtoPipe::PipeMessageType::SetupHook: { const auto body = reinterpret_cast(messageBuffer); @@ -634,6 +607,46 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) break; } + case ProtoPipe::PipeMessageType::SetXinputtoMKBkeys: + { + const auto body = reinterpret_cast(messageBuffer); + printf("Received TranslateXtoMKB Mapping"); + ScreenshotInput::TranslateXtoMKB::Amapping = body->XinputtoMKBAkey; + ScreenshotInput::TranslateXtoMKB::Bmapping = body->XinputtoMKBBkey; + ScreenshotInput::TranslateXtoMKB::Xmapping = body->XinputtoMKBXkey; + ScreenshotInput::TranslateXtoMKB::Ymapping = body->XinputtoMKBYkey; + ScreenshotInput::TranslateXtoMKB::RSmapping = body->XinputtoMKBRSkey; + ScreenshotInput::TranslateXtoMKB::LSmapping = body->XinputtoMKBLSkey; + ScreenshotInput::TranslateXtoMKB::RSmapping = body->XinputtoMKBRSkey; + + ScreenshotInput::TranslateXtoMKB::rightmapping = body->XinputtoMKBrightkey; + ScreenshotInput::TranslateXtoMKB::leftmapping = body->XinputtoMKBleftkey; + ScreenshotInput::TranslateXtoMKB::upmapping = body->XinputtoMKBupkey; + ScreenshotInput::TranslateXtoMKB::downmapping = body->XinputtoMKBdownkey; + + ScreenshotInput::TranslateXtoMKB::stickRpressmapping = body->XinputtoMKBstickR; + ScreenshotInput::TranslateXtoMKB::stickLpressmapping = body->XinputtoMKBstickL; + ScreenshotInput::TranslateXtoMKB::stickrightmapping = body->XinputtoMKBstickright; + ScreenshotInput::TranslateXtoMKB::stickleftmapping = body->XinputtoMKBstickleft; + ScreenshotInput::TranslateXtoMKB::stickupmapping = body->XinputtoMKBstickup; + ScreenshotInput::TranslateXtoMKB::stickdownmapping = body->XinputtoMKBstickdown; + + ScreenshotInput::TranslateXtoMKB::optionmapping = body->XinputtoMKBoption; + ScreenshotInput::TranslateXtoMKB::startmapping = body->XinputtoMKBstart; + break; + } //PipeMessageSetXinputtoMKBCFG + case ProtoPipe::PipeMessageType::SetXinputtoMKBCFG: + { + const auto body = reinterpret_cast(messageBuffer); + ScreenshotInput::TranslateXtoMKB::lefthanded = body->stickinvert; + ScreenshotInput::ScanThread::scanoption = body->scanoption; + ScreenshotInput::ScanThread::ShoulderNextBMP = body->shoulderswap; + ScreenshotInput::ScanThread::Aisstatic = body->astsatic; + ScreenshotInput::ScanThread::Bisstatic = body->bstsatic; + ScreenshotInput::ScanThread::Xisstatic = body->xstsatic; + ScreenshotInput::ScanThread::Yisstatic = body->ystsatic; + break; + } default: { fprintf(stderr, "Unrecongnised message type, exiting pipe\n"); diff --git a/src/ProtoInput/ProtoInputHooks/ScanThread.cpp b/src/ProtoInput/ProtoInputHooks/ScanThread.cpp index c7a3a0e..01f02f9 100644 --- a/src/ProtoInput/ProtoInputHooks/ScanThread.cpp +++ b/src/ProtoInput/ProtoInputHooks/ScanThread.cpp @@ -48,8 +48,7 @@ namespace ScreenshotInput { int ScanThread::Ctype, ScanThread::Dtype, ScanThread::Etype, ScanThread::Ftype; bool ScanThread::scanloop = true; int ScanThread::scanoption; - int ScanThread::ignorerect; - int ScanThread::ShoulderNextBMP; + bool ScanThread::ShoulderNextBMP; int ScanThread::resize = 1; //support scaling HWND hwndhandle; POINT hwndres{ 0,0 }; @@ -1044,7 +1043,7 @@ namespace ScreenshotInput { Cpoint.y = ScanThread::PointA.y; if (Cpoint.x != 0 && Cpoint.y != 0) { - if (ScanThread::ShoulderNextBMP == 0) + if (!ScanThread::ShoulderNextBMP) { if (ScanThread::startsearchA < ScanThread::numphotoA - 1) ScanThread::startsearchA++; //dont want it to update before input done @@ -1077,7 +1076,7 @@ namespace ScreenshotInput { Cpoint.y = ScanThread::PointB.y; if (Cpoint.x != 0 && Cpoint.y != 0) { - if (ScanThread::ShoulderNextBMP == 0) + if (!ScanThread::ShoulderNextBMP) { if (ScanThread::startsearchB < ScanThread::numphotoB - 1) ScanThread::startsearchB++; //dont want it to update before input done @@ -1110,7 +1109,7 @@ namespace ScreenshotInput { if (Cpoint.x != 0 && Cpoint.y != 0) { - if (ScanThread::ShoulderNextBMP == 0) + if (!ScanThread::ShoulderNextBMP) { if (ScanThread::startsearchX < ScanThread::numphotoX - 1) ScanThread::startsearchX++; //dont want it to update before input done @@ -1145,7 +1144,7 @@ namespace ScreenshotInput { //LeaveCriticalSection(&critical); if (Cpoint.x != 0 && Cpoint.y != 0) { - if (ScanThread::ShoulderNextBMP == 0) + if (!ScanThread::ShoulderNextBMP) { if (ScanThread::startsearchY < ScanThread::numphotoY - 1) ScanThread::startsearchY++; //dont want it to update before input done @@ -1173,7 +1172,7 @@ namespace ScreenshotInput { returnedvalue = ButtonScanAction("\\C", ModeScanThread, ScanThread::numphotoC, ScanThread::startsearchC, false, { 0,0 }, false); //2 save bmps LeaveCriticalSection(&ScanThread::critical); } - else if (ScanThread::ShoulderNextBMP == 1) + else if (ScanThread::ShoulderNextBMP) { EnterCriticalSection(&ScanThread::critical); if (ScanThread::startsearchA < ScanThread::numphotoA - 1) @@ -1202,7 +1201,7 @@ namespace ScreenshotInput { returnedvalue = ButtonScanAction("\\D", ModeScanThread, ScanThread::numphotoD, ScanThread::startsearchD, false, { 0,0 }, false); //2 save bmps LeaveCriticalSection(&ScanThread::critical); } - else if (ScanThread::ShoulderNextBMP == 1) + else if (ScanThread::ShoulderNextBMP) { EnterCriticalSection(&ScanThread::critical); diff --git a/src/ProtoInput/ProtoInputHooks/ScanThread.h b/src/ProtoInput/ProtoInputHooks/ScanThread.h index c3f07d1..8d92ac2 100644 --- a/src/ProtoInput/ProtoInputHooks/ScanThread.h +++ b/src/ProtoInput/ProtoInputHooks/ScanThread.h @@ -10,13 +10,16 @@ namespace ScreenshotInput { static int scanAtype, scanBtype, scanXtype, scanYtype, Ctype, Dtype, Etype, Ftype; static int numphotoA, numphotoB, numphotoX, numphotoY, numphotoC, numphotoD, numphotoE, numphotoF; static int numphotoAbmps, numphotoBbmps, numphotoXbmps, numphotoYbmps; - static int Aisstatic, Bisstatic, Xisstatic, Yisstatic; + static POINT PointA, PointB, PointX, PointY; static int startsearchA, startsearchB, startsearchX, startsearchY, startsearchC, startsearchD, startsearchE, startsearchF; static std::vector staticPointA, staticPointB, staticPointX, staticPointY; static bool scanloop; + //tunell + static int Aisstatic, Bisstatic, Xisstatic, Yisstatic; static int scanoption; - static int ShoulderNextBMP; + static bool ShoulderNextBMP; + static int resize; static int ignorerect; static void StartScanThread(HMODULE hmodule, int Astatic, int Bstatic, int Xstatic, int Ystatic, bool prescan); diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp index 63d7881..71a752b 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -350,7 +350,6 @@ namespace ScreenshotInput } InitializeCriticalSection(&ScanThread::critical); - ScanThread::scanoption = 1; if (!ScanThread::enumeratebmps()) //false means no bmps found. also counts statics { // LOG("BMPs enumerated but not found: 0x%p", hwnd); @@ -380,10 +379,8 @@ namespace ScreenshotInput EnterCriticalSection(&ScanThread::critical); showmessageMT = TranslateXtoMKB::showmessage; modeMT = TranslateXtoMKB::mode; - - - LeaveCriticalSection(&ScanThread::critical); + movedmouse = false; //reset XINPUT_STATE state; ZeroMemory(&state, sizeof(XINPUT_STATE)); @@ -727,11 +724,16 @@ namespace ScreenshotInput if (oldstart && oldoptions) { } - else oldstartoptions = false; + else + { + oldstartoptions = false; + ButtonStateImpulse(VK_HOME, false);//down} + } } - else if (oldstart && oldoptions)//gui + else if (oldstart && oldoptions)//gui or fake cursor toggle { - Proto::ToggleWindow(); + //Proto::ToggleWindow(); + ButtonStateImpulse(VK_HOME, true);//down oldstartoptions = true; // oldstart = false; // oldoptions = false; diff --git a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h index 5668f44..291b0fd 100644 --- a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h +++ b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h @@ -9,7 +9,6 @@ enum class PipeMessageType { AddSelectedMouseOrKeyboard, SetTranslateXinputtoMKB, - SetXinputtoMKBkeys, SetupHook, WakeUpProcess, SetupMessageFilter, @@ -44,7 +43,9 @@ enum class PipeMessageType SetMoveWindowDontResize, SetMoveWindowDontReposition, SetAdjustWindowRectSettings, - SetDontWaitWindowBorder + SetDontWaitWindowBorder, + SetXinputtoMKBkeys, + SetXinputtoMKBCFG }; struct PipeMessageHeader @@ -62,28 +63,7 @@ struct PipeMessageSetTranslateXinputtoMKB { bool TranslateXinputtoMKB; }; -struct PipeMessageSetXinputtoMKBkeys -{ - int XinputtoMKBAkey; - int XinputtoMKBBkey; - int XinputtoMKBXkey; - int XinputtoMKBYkey; - int XinputtoMKBRSkey; - int XinputtoMKBLSkey; - int XinputtoMKBrightkey; - int XinputtoMKBleftkey; - int XinputtoMKBupkey; - int XinputtoMKBdownkey; - int XinputtoMKBstickR; - int XinputtoMKBstickL; - int XinputtoMKBstickright; -int XinputtoMKBstickleft; - int XinputtoMKBstickup; - int XinputtoMKBstickdown; - int XinputtoMKBoption; - int XinputtoMKBstart; - bool XinputtoMKBstickinvert; -}; + struct PipeMessageSetupHook { @@ -286,4 +266,35 @@ struct PipeMessageSetDontWaitWindowBorder bool DontWaitWindowBorder; }; +struct PipeMessageSetXinputtoMKBkeys +{ + int XinputtoMKBAkey; + int XinputtoMKBBkey; + int XinputtoMKBXkey; + int XinputtoMKBYkey; + int XinputtoMKBRSkey; + int XinputtoMKBLSkey; + int XinputtoMKBrightkey; + int XinputtoMKBleftkey; + int XinputtoMKBupkey; + int XinputtoMKBdownkey; + int XinputtoMKBstickR; + int XinputtoMKBstickL; + int XinputtoMKBstickright; + int XinputtoMKBstickleft; + int XinputtoMKBstickup; + int XinputtoMKBstickdown; + int XinputtoMKBoption; + int XinputtoMKBstart; +}; +struct PipeMessageSetXinputtoMKBCFG +{ + bool stickinvert; + bool scanoption; + bool shoulderswap; + bool astsatic; + bool bstsatic; + bool xstsatic; + bool ystsatic; +}; } \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHost/Gui.cpp b/src/ProtoInput/ProtoInputHost/Gui.cpp index 7f86b98..d27f38e 100644 --- a/src/ProtoInput/ProtoInputHost/Gui.cpp +++ b/src/ProtoInput/ProtoInputHost/Gui.cpp @@ -176,10 +176,7 @@ bool Launch() if (instance.keyboardHandle != -1) AddSelectedKeyboardHandle(instanceHandle, instance.keyboardHandle); SetTranslateXinputtoMKB(instanceHandle, currentProfile.TranslateXinputtoMKB); - //keys - SetXinputtoMKBkeys(instanceHandle, currentProfile.XinputtoMKBAkey, currentProfile.XinputtoMKBBkey, currentProfile.XinputtoMKBXkey, currentProfile.XinputtoMKBYkey, currentProfile.XinputtoMKBRSkey, currentProfile.XinputtoMKBLSkey, currentProfile.XinputtoMKBrightkey, currentProfile.XinputtoMKBleftkey, currentProfile.XinputtoMKBupkey, currentProfile.XinputtoMKBdownkey, - currentProfile.XinputtoMKBstickR, currentProfile.XinputtoMKBstickL, currentProfile.XinputtoMKBstickright, currentProfile.XinputtoMKBstickleft, currentProfile.XinputtoMKBstickup, currentProfile.XinputtoMKBstickdown, - currentProfile.XinputtoMKBoption, currentProfile.XinputtoMKBstart, currentProfile.XinputtoMKBstickinvert); + if (hookEnabled(RegisterRawInputHookID)) InstallHook(instanceHandle, RegisterRawInputHookID); if (hookEnabled(GetRawInputDataHookID)) InstallHook(instanceHandle, GetRawInputDataHookID); @@ -260,6 +257,12 @@ bool Launch() SetExternalFreezeFakeInput(instanceHandle, !isInputCurrentlyLocked && freezeGameInputWhileInputNotLocked); + //Xinput translate settings + SetXinputtoMKBkeys(instanceHandle, currentProfile.XinputtoMKBAkey, currentProfile.XinputtoMKBBkey, currentProfile.XinputtoMKBXkey, currentProfile.XinputtoMKBYkey, currentProfile.XinputtoMKBRSkey, currentProfile.XinputtoMKBLSkey, currentProfile.XinputtoMKBrightkey, currentProfile.XinputtoMKBleftkey, currentProfile.XinputtoMKBupkey, currentProfile.XinputtoMKBdownkey, + currentProfile.XinputtoMKBstickR, currentProfile.XinputtoMKBstickL, currentProfile.XinputtoMKBstickright, currentProfile.XinputtoMKBstickleft, currentProfile.XinputtoMKBstickup, currentProfile.XinputtoMKBstickdown, + currentProfile.XinputtoMKBoption, currentProfile.XinputtoMKBstart, currentProfile.XinputtoMKBstickinvert); + SetXinputtoMKBCFG(instanceHandle, currentProfile.XinputtoMKBstickinvert, currentProfile.ScanOption, currentProfile.Shoulderswappoints, currentProfile.XAstatic, currentProfile.XBstatic, currentProfile.XXstatic, currentProfile.XYstatic); + if (!instance.runtime) WakeUpProcess(instanceHandle); @@ -715,11 +718,11 @@ void SelectedInstanceWindow() ImGui::PushID(128794); ImGui::Spacing(); ImGui::Separator(); + ImGui::TextWrapped("Controller index"); ImGui::SliderInt("", (int*)&instance.controllerIndex, 0, 16, "%d", ImGuiSliderFlags_AlwaysClamp); - ImGui::Separator(); ImGui::Spacing(); - ImGui::TextWrapped("Controller index"); ImGui::Separator(); + ImGui::Spacing(); ImGui::TextWrapped("If Translate X to MKB is selected, then it will emulate mouse and keyboard from selected ControllerIndex." "Option will automatically deactivate if a keyboard or mouse is selected for the instance. " "Also you should make sure ControllerIndex is not zero, as zero still implies no controller" @@ -728,9 +731,26 @@ void SelectedInstanceWindow() ImGui::Checkbox("Translate X to MKB", ¤tProfile.TranslateXinputtoMKB); // ImGui::Separator(); ImGui::Spacing(); + ImGui::TextWrapped("Scanoption Will prescan and render coordinates if any BMPs or static points are loaded" + ""); + ImGui::Checkbox("Scanoption", ¤tProfile.ScanOption); // + ImGui::Separator(); ImGui::Spacing(); - ImGui::TextWrapped("Options and mappings for Xinput controller if Translate X to MKB is enabled." - "Option will automatically deactivate if a keyboard or mouse is selected for the instance. " + ImGui::TextWrapped("Uses shoulder buttons for point next or previous point if enabled" + ""); + ImGui::Checkbox("ShoulderScroll", ¤tProfile.Shoulderswappoints); // + ImGui::Separator(); + ImGui::Spacing(); + ImGui::TextWrapped("Any button set as static will not forget coordinates found" + ""); + + ImGui::Spacing(); + ImGui::Checkbox("A static", ¤tProfile.XAstatic); // + ImGui::Checkbox("B static", ¤tProfile.XBstatic); // + ImGui::Checkbox("X static", ¤tProfile.XXstatic); // + ImGui::Checkbox("Y static", ¤tProfile.XYstatic); // + ImGui::Separator(); + ImGui::TextWrapped("Mappings:" ""); // A key { @@ -1203,12 +1223,6 @@ void SelectedInstanceWindow() ImGui::Checkbox("Lefthanded Stick. moves mouse with left stick and button map on right stick. or opposite if disabled", ¤tProfile.XinputtoMKBstickinvert); // ImGui::Separator(); ImGui::Separator(); - ImGui::TextWrapped("Sensitivity"); - ImGui::SliderFloat("Slider", &Sensitivity, 0.0f, 40.0f); - ImGui::Separator(); - ImGui::TextWrapped("Sensitivity Multiplier"); - ImGui::SliderFloat("Slider", &Sensitivitymultiplier, 1.0f, 20.0f); - ImGui::Separator(); ImGui::PopID(); } diff --git a/src/ProtoInput/ProtoInputHost/Profiles.h b/src/ProtoInput/ProtoInputHost/Profiles.h index 881cd94..2d6f758 100644 --- a/src/ProtoInput/ProtoInputHost/Profiles.h +++ b/src/ProtoInput/ProtoInputHost/Profiles.h @@ -74,6 +74,13 @@ struct Profile bool useOpenXinput = false; bool TranslateXinputtoMKB = false; + bool XinputtoMKBstickinvert = false; + bool ScanOption = false; + bool Shoulderswappoints = false; + bool XAstatic = false; + bool XBstatic = false; + bool XXstatic = false; + bool XYstatic = false; int XinputtoMKBAkey = 0x52; //R int XinputtoMKBBkey = 0x47; //G int XinputtoMKBXkey = 0x45; //E @@ -92,7 +99,7 @@ struct Profile int XinputtoMKBstickdown = 0x53; //S int XinputtoMKBoption = 0x1B; // int XinputtoMKBstart = 0x0D; - bool XinputtoMKBstickinvert = false; + bool useFakeClipCursor = true; diff --git a/src/ProtoInput/ProtoInputLoader/Inject.cpp b/src/ProtoInput/ProtoInputLoader/Inject.cpp index def9a88..f2294ac 100644 --- a/src/ProtoInput/ProtoInputLoader/Inject.cpp +++ b/src/ProtoInput/ProtoInputLoader/Inject.cpp @@ -88,41 +88,7 @@ void SetTranslateXinputtoMKB(ProtoInstanceHandle instanceHandle, bool TranslateX ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetTranslateXinputtoMKB, &message); } } -void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright,int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, bool XinputtoMKBstickinvert) -{ - if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) - { - auto& instance = find->second; - - WaitClientConnect(instance); - - ProtoPipe::PipeMessageSetXinputtoMKBkeys message - { - XinputtoMKBAkey, - XinputtoMKBBkey, - XinputtoMKBXkey, - XinputtoMKBYkey, - XinputtoMKBRSkey, - XinputtoMKBLSkey, - XinputtoMKBrightkey, - XinputtoMKBleftkey, - XinputtoMKBupkey, - XinputtoMKBdownkey, - XinputtoMKBstickR, - XinputtoMKBstickL, - XinputtoMKBstickright, - XinputtoMKBstickleft, - XinputtoMKBstickup, - XinputtoMKBstickdown, - XinputtoMKBoption, - XinputtoMKBstart, - XinputtoMKBstickinvert - }; - - ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetXinputtoMKBkeys, &message); - } -} extern "C" __declspec(dllexport) void StartFocusMessageLoop(ProtoInstanceHandle instanceHandle, int milliseconds, @@ -730,4 +696,59 @@ void SetDontWaitWindowBorder(ProtoInstanceHandle instanceHandle, bool enabled) ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetDontWaitWindowBorder, &message); } +} +void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright, int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, bool XinputtoMKBstickinvert) +{ + if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) + { + auto& instance = find->second; + + WaitClientConnect(instance); + + ProtoPipe::PipeMessageSetXinputtoMKBkeys message + { + XinputtoMKBAkey, + XinputtoMKBBkey, + XinputtoMKBXkey, + XinputtoMKBYkey, + XinputtoMKBRSkey, + XinputtoMKBLSkey, + XinputtoMKBrightkey, + XinputtoMKBleftkey, + XinputtoMKBupkey, + XinputtoMKBdownkey, + XinputtoMKBstickR, + XinputtoMKBstickL, + XinputtoMKBstickright, + XinputtoMKBstickleft, + XinputtoMKBstickup, + XinputtoMKBstickdown, + XinputtoMKBoption, + XinputtoMKBstart, + }; + + ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetXinputtoMKBkeys, &message); + } +} +void SetXinputtoMKBCFG(ProtoInstanceHandle instanceHandle, bool stickinvert, bool scanoption, bool shoulderswap, bool astatic, bool bstatic, bool xstatic, bool ystatic) +{ + if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) + { + auto& instance = find->second; + + WaitClientConnect(instance); + + ProtoPipe::PipeMessageSetXinputtoMKBCFG message + { + stickinvert, + scanoption, + shoulderswap, + astatic, + bstatic, + xstatic, + ystatic, + }; + + ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetXinputtoMKBCFG, &message); + } } \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputLoader/include/protoloader.h b/src/ProtoInput/ProtoInputLoader/include/protoloader.h index 833f936..226ad17 100644 --- a/src/ProtoInput/ProtoInputLoader/include/protoloader.h +++ b/src/ProtoInput/ProtoInputLoader/include/protoloader.h @@ -60,8 +60,6 @@ extern "C" __declspec(dllexport) void AddSelectedMouseHandle(ProtoInstanceHandle extern "C" __declspec(dllexport) void AddSelectedKeyboardHandle(ProtoInstanceHandle instanceHandle, unsigned int keyboardHandle); extern "C" __declspec(dllexport) void SetTranslateXinputtoMKB(ProtoInstanceHandle instanceHandle, bool TranslateXinputtoMKB); -extern "C" __declspec(dllexport) void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright, int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, bool XinputtoMKBstickinvert); - extern "C" __declspec(dllexport) void InstallHook(ProtoInstanceHandle instanceHandle, ProtoHookIDs hookID); extern "C" __declspec(dllexport) void UninstallHook(ProtoInstanceHandle instanceHandle, ProtoHookIDs hookID); @@ -152,4 +150,8 @@ extern "C" __declspec(dllexport) void SetMoveWindowDontReposition(ProtoInstanceH extern "C" __declspec(dllexport) void SetAdjustWindowRectSettings(ProtoInstanceHandle instanceHandle, int posx, int posy, int width, int height); -extern "C" __declspec(dllexport) void SetDontWaitWindowBorder(ProtoInstanceHandle instanceHandle, bool enabled); \ No newline at end of file +extern "C" __declspec(dllexport) void SetDontWaitWindowBorder(ProtoInstanceHandle instanceHandle, bool enabled); + +extern "C" __declspec(dllexport) void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright, int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, bool XinputtoMKBstickinvert); + +extern "C" __declspec(dllexport) void SetXinputtoMKBCFG(ProtoInstanceHandle instanceHandle, bool stickinvert, bool scanoption, bool shoulderswap, bool astatic, bool bstatic, bool xstatic, bool ystatic); \ No newline at end of file From b7dcfebccbfc9f587ba5a81c79765b9b82942a92 Mon Sep 17 00:00:00 2001 From: messenils Date: Tue, 10 Feb 2026 21:07:22 +0100 Subject: [PATCH 09/20] disabled coordinate search completely when scanoption is disabled --- src/ProtoInput/ProtoInputHooks/FakeCursor.cpp | 47 +++++-- src/ProtoInput/ProtoInputHooks/Gui.cpp | 5 +- src/ProtoInput/ProtoInputHooks/ScanThread.cpp | 6 +- .../ProtoInputHooks/TranslateXtoMKB.cpp | 115 ++++++++++++------ src/ProtoInput/ProtoInputHooks/dllmain.cpp | 3 + 5 files changed, 125 insertions(+), 51 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp index cf480d2..d6002a8 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp @@ -15,7 +15,9 @@ FakeCursor FakeCursor::state{}; //TranslateXtoMKB POINT OldspotA, OldspotB, OldspotX, OldspotY; int showmessage = 0; -bool erasemessage = false; +int oldmessage = 0; +bool messageshown = false; +HWND selectorhwnd = nullptr; //copy of variable in TranslateXtoMKB to avoid accessing it multiple times with critical section in DrawCursor LRESULT WINAPI FakeCursorWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -115,13 +117,36 @@ void DrawPinkSquare(HDC hdc, int x, int y) DeleteObject(hPen); } POINT OldTestpos = { 0,0 }; -void DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, POINT spotY, HBRUSH Brush) + +void DrawMessage(HDC hdc, HWND window, HBRUSH Brush) +{ + POINT here = { 0,0 }; + ClientToScreen(window, &here); + + if (oldmessage != showmessage) + { + RECT fill{ 50, 50, 100, 100 }; + FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! + messageshown = false; + } + if (!messageshown) + { + if (showmessage == 12){ + DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + TextOutW(hdc, here.x + 20, here.y + 20, TEXT("DISCONNECTED!"), 14); //14 + messageshown = true; + } + } + oldmessage = showmessage; + +} +void DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, POINT spotY,HWND window, HBRUSH Brush) { bool windowmoved = false; bool erased = false; //detect window change pos POINT testpos; - ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &testpos); + ClientToScreen(window, &testpos); if (testpos.x < OldTestpos.x || testpos.y < OldTestpos.y || testpos.x > OldTestpos.x || testpos.y > OldTestpos.y) { windowmoved = true; @@ -152,22 +177,22 @@ void DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, POINT spotY, } if (spotA.x != 0 && spotA.y != 0 && erased == true) { - ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &spotA); + ClientToScreen(window, &spotA); DrawRedX(hdc, spotA.x, spotA.y); } if (spotB.x != 0 && spotB.y != 0 && erased == true) { - ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &spotB); + ClientToScreen(window, &spotB); DrawBlueCircle(hdc, spotB.x, spotB.y); } if (spotX.x != 0 && spotX.y != 0 && erased == true) { - ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &spotX); + ClientToScreen(window, &spotX); DrawGreenTriangle(hdc, spotX.x, spotX.y); } if (spotY.x != 0 && spotY.y != 0 && erased == true) { - ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &spotY); + ClientToScreen(window, &spotY); DrawPinkSquare(hdc, spotY.x, spotY.y); } @@ -186,19 +211,21 @@ void FakeCursor::DrawCursor() FillRect(hdc, &fill, transparencyBrush); // Note: window, not screen coordinates! } + if (ScreenshotInput::ScanThread::scanoption == 1) { EnterCriticalSection(&ScreenshotInput::ScanThread::critical); + selectorhwnd = (HWND)HwndSelector::GetSelectedHwnd(); showmessage = ScreenshotInput::TranslateXtoMKB::showmessage; POINT Apos = { ScreenshotInput::ScanThread::PointA.x, ScreenshotInput::ScanThread::PointA.y }; POINT Bpos = { ScreenshotInput::ScanThread::PointB.x, ScreenshotInput::ScanThread::PointB.y }; POINT Xpos = { ScreenshotInput::ScanThread::PointX.x, ScreenshotInput::ScanThread::PointX.y }; POINT Ypos = { ScreenshotInput::ScanThread::PointY.x, ScreenshotInput::ScanThread::PointY.y }; + DrawFoundSpots(hdc, Apos, Bpos, Xpos, Ypos, selectorhwnd, transparencyBrush); + //DrawMessage(hdc, selectorhwnd, transparencyBrush); LeaveCriticalSection(&ScreenshotInput::ScanThread::critical); - - DrawFoundSpots(hdc, Apos, Bpos, Xpos, Ypos, transparencyBrush); - } + oldHadShowCursor = showCursor; POINT pos = { FakeMouseKeyboard::GetMouseState().x,FakeMouseKeyboard::GetMouseState().y }; diff --git a/src/ProtoInput/ProtoInputHooks/Gui.cpp b/src/ProtoInput/ProtoInputHooks/Gui.cpp index c6173ab..98b5f8c 100644 --- a/src/ProtoInput/ProtoInputHooks/Gui.cpp +++ b/src/ProtoInput/ProtoInputHooks/Gui.cpp @@ -19,7 +19,7 @@ namespace Proto { - + bool TranslateXisenabled = false; intptr_t ConsoleHwnd; static void HelpMarker(const char* desc) @@ -795,8 +795,9 @@ void RawInputMenu() - if (RawInput::TranslateXinputtoMKB) + if (RawInput::TranslateXinputtoMKB) //TranslateXisenabled { + ImGui::TextWrapped("XinputtoMKB ControllerID"); ImGui::TextWrapped("0 is first controller"); ImGui::SliderInt("XinputtoMKB ControllerID", (int*)&ScreenshotInput::TranslateXtoMKB::controllerID, 0, 16, "%d", ImGuiSliderFlags_AlwaysClamp); diff --git a/src/ProtoInput/ProtoInputHooks/ScanThread.cpp b/src/ProtoInput/ProtoInputHooks/ScanThread.cpp index 01f02f9..22e2a8f 100644 --- a/src/ProtoInput/ProtoInputHooks/ScanThread.cpp +++ b/src/ProtoInput/ProtoInputHooks/ScanThread.cpp @@ -934,7 +934,7 @@ namespace ScreenshotInput { // } // else if (MainThread::showmessage != 0) // MainThread::showmessage = 11;//wait for mesage expire - return true; + return false; } DWORD WINAPI ScanThreadMain(LPVOID, int Aisstatic, int Bisstatic, int Xisstatic, int Yisstatic) @@ -1022,7 +1022,7 @@ namespace ScreenshotInput { } Sleep(10); } - //else Sleep(1000); + else Sleep(100); } return 0; } @@ -1140,8 +1140,6 @@ namespace ScreenshotInput { POINT Cpoint; Cpoint.x = ScanThread::PointY.x; Cpoint.y = ScanThread::PointY.y; - - //LeaveCriticalSection(&critical); if (Cpoint.x != 0 && Cpoint.y != 0) { if (!ScanThread::ShoulderNextBMP) diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp index 71a752b..ca8245b 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -29,6 +29,7 @@ #include "GtoMnK_RawInput.h" #include "FakeMouseKeyboard.h" #include "ScanThread.h" +#include "StateInfo.h" //#include #pragma comment(lib, "dwmapi.lib") #include @@ -41,6 +42,8 @@ namespace ScreenshotInput { + int InstanceID = 0; //InstanceID copy from stateinfo.h + //from tunnell int TranslateXtoMKB::controllerID; bool TranslateXtoMKB::rawinputhook; //registerrawinputhook @@ -134,16 +137,15 @@ namespace ScreenshotInput bool oldscrollleft = false; bool oldscrollright = false; bool oldscrollup = false; + bool oldGUIkey = false; // Add a fake key event to the array USHORT lastVKkey = 0; bool IsKeyPressed(int Vkey) { - SHORT hmm = GetKeyState(Vkey); - if (hmm > 0) - return true; - else return false; + return (GetAsyncKeyState(Vkey) & 0x8000) != 0; + } void TranslateXtoMKB::SendMouseClick(int x, int y, int z) { // Create a named mutex @@ -342,6 +344,7 @@ namespace ScreenshotInput } void ThreadFunction(HMODULE hModule) { + Proto::AddThreadToACL(GetCurrentThreadId()); Sleep(2000); if (readsettings() == false) @@ -349,18 +352,18 @@ namespace ScreenshotInput //messagebox? settings not read } - InitializeCriticalSection(&ScanThread::critical); + // InitializeCriticalSection(&ScanThread::critical); if (!ScanThread::enumeratebmps()) //false means no bmps found. also counts statics { - // LOG("BMPs enumerated but not found: 0x%p", hwnd); + // printf("BMPs enumerated but not found"); if (ScanThread::scanoption == 1) { ScanThread::scanoption = 0; - // LOG("Error. Nothing to scan for. Disabling scanoption: 0x%p", hwnd); + // printf("Error. Nothing to scan for. Disabling scanoption"); } } else { - // LOG("BMPs found: 0x%p", hwnd); + // printf("BMPs found"); ScanThread::staticPointA.assign(ScanThread::numphotoA + 1, POINT{ 0, 0 }); ScanThread::staticPointB.assign(ScanThread::numphotoB + 1, POINT{ 0, 0 }); ScanThread::staticPointX.assign(ScanThread::numphotoX + 1, POINT{ 0, 0 }); @@ -370,17 +373,37 @@ namespace ScreenshotInput if (ScanThread::scanoption == 1) { //starting bmp continous scanner ScanThread::StartScanThread(g_hModule, ScanThread::Aisstatic, ScanThread::Bisstatic, ScanThread::Xisstatic, ScanThread::Yisstatic, ScanThread::scanoption); - // LOG("BMP scanner started: 0x%p", hwnd); + // printf("BMP scanner started"); } while (loop == true) { + //if render. sleep while rendering instead of at the end + bool alreadyslept = false; //copy criticals EnterCriticalSection(&ScanThread::critical); showmessageMT = TranslateXtoMKB::showmessage; modeMT = TranslateXtoMKB::mode; LeaveCriticalSection(&ScanThread::critical); + //GUI + if (oldGUIkey) + { + if (IsKeyPressed(VK_RCONTROL) && IsKeyPressed(VK_RMENU) && IsKeyPressed(0x30 + InstanceID)) + { + } + else + { + oldGUIkey = false; + ButtonStateImpulse(VK_HOME, false);//down} + } + } + else if (IsKeyPressed(VK_RCONTROL) && IsKeyPressed(VK_RMENU) && IsKeyPressed(0x30 + InstanceID))//gui or fake cursor toggle + { + Proto::ToggleWindow(); + oldGUIkey = true; + } + movedmouse = false; //reset XINPUT_STATE state; ZeroMemory(&state, sizeof(XINPUT_STATE)); @@ -427,12 +450,12 @@ namespace ScreenshotInput Yf += delta.y; movedmouse = true; } - if (movedmouse == true) //fake cursor move message { TranslateXtoMKB::SendMouseClick(delta.x, delta.y, 8); - + Proto::FakeCursor::NotifyUpdatedCursorPosition(); + } if (leftPressedold) @@ -551,9 +574,13 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_A) { oldA = true; + if (ScanThread::scanoption == 1) + { bool found = ScanThread::ButtonPressed(0); if (!found) ButtonStateImpulse(TranslateXtoMKB::Amapping, true);//down + } + else ButtonStateImpulse(TranslateXtoMKB::Amapping, true); } @@ -570,9 +597,13 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_B) { oldB = true; - bool found = ScanThread::ButtonPressed(1); - if (!found) - ButtonStateImpulse(TranslateXtoMKB::Bmapping, true);//down + if (ScanThread::scanoption == 1) + { + bool found = ScanThread::ButtonPressed(1); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::Bmapping, true);//down + } + else ButtonStateImpulse(TranslateXtoMKB::Bmapping, true);//down } @@ -589,9 +620,13 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_X) { oldX = true; - bool found = ScanThread::ButtonPressed(2); - if (!found) - ButtonStateImpulse(TranslateXtoMKB::Xmapping, true);//down + if (ScanThread::scanoption == 1) + { + bool found = ScanThread::ButtonPressed(2); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::Xmapping, true);//down + } + else ButtonStateImpulse(TranslateXtoMKB::Xmapping, true);//down } @@ -608,9 +643,13 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_Y) { oldY = true; - bool found = ScanThread::ButtonPressed(3); - if (!found) - ButtonStateImpulse(TranslateXtoMKB::Ymapping, true);//down + if (ScanThread::scanoption == 1) + { + bool found = ScanThread::ButtonPressed(3); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::Ymapping, true);//down + } + else ButtonStateImpulse(TranslateXtoMKB::Ymapping, true);//down } @@ -627,9 +666,13 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) { oldC = true; - bool found = ScanThread::ButtonPressed(4); - if (!found) - ButtonStateImpulse(TranslateXtoMKB::RSmapping, true); //down + if (ScanThread::scanoption == 1) + { + bool found = ScanThread::ButtonPressed(4); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::RSmapping, true); //down + } + else ButtonStateImpulse(TranslateXtoMKB::RSmapping, true); //down } @@ -646,9 +689,13 @@ namespace ScreenshotInput else if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) { oldD = true; - bool found = ScanThread::ButtonPressed(5); - if (!found) - ButtonStateImpulse(TranslateXtoMKB::LSmapping, true);//down + if (ScanThread::scanoption == 1) + { + bool found = ScanThread::ButtonPressed(5); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::LSmapping, true);//down + } + else ButtonStateImpulse(TranslateXtoMKB::LSmapping, true);//down } @@ -732,11 +779,8 @@ namespace ScreenshotInput } else if (oldstart && oldoptions)//gui or fake cursor toggle { - //Proto::ToggleWindow(); ButtonStateImpulse(VK_HOME, true);//down oldstartoptions = true; - // oldstart = false; - // oldoptions = false; } if (oldstart) { @@ -781,10 +825,13 @@ namespace ScreenshotInput if (tick < updatewindowtick) tick++; else { //need to update hwnd and bounds periodically + // EnterCriticalSection(&ScanThread::critical); Proto::HwndSelector::UpdateMainHwnd(false); Proto::HwndSelector::UpdateWindowBounds(); + // LeaveCriticalSection(&ScanThread::critical); tick = 0; } + EnterCriticalSection(&ScanThread::critical); if (showmessageMT != 0) { //drawing messages or something if (counter < 400) { //showmessage is critical @@ -792,20 +839,18 @@ namespace ScreenshotInput } else { showmessageMT = 0; - EnterCriticalSection(&ScanThread::critical); TranslateXtoMKB::showmessage = 0; - LeaveCriticalSection(&ScanThread::critical); counter = 0; } } LeaveCriticalSection(&ScanThread::critical); - if (modeMT == 0) - Sleep(10); + if (modeMT > 0) { Sleep(1); } + else Sleep(1); if (showmessageMT == 99) - Sleep(15); + Sleep(1); } //loop end but endless return; } @@ -814,7 +859,7 @@ namespace ScreenshotInput { RawInput::Initialize(); g_hModule = hModule; - + InstanceID = Proto::StateInfo::info.instanceIndex; std::thread one(ThreadFunction, g_hModule); one.detach(); return; diff --git a/src/ProtoInput/ProtoInputHooks/dllmain.cpp b/src/ProtoInput/ProtoInputHooks/dllmain.cpp index 6c67a4c..07170fe 100644 --- a/src/ProtoInput/ProtoInputHooks/dllmain.cpp +++ b/src/ProtoInput/ProtoInputHooks/dllmain.cpp @@ -17,6 +17,7 @@ #include "Gui.h" #include "FakeCursor.h" #include "TranslateXtoMKB.h" +#include "ScanThread.h" HMODULE dll_hModule; @@ -60,6 +61,8 @@ DWORD WINAPI StartThread(LPVOID lpParameter) if (Proto::RawInput::TranslateXinputtoMKB) ScreenshotInput::TranslateXtoMKB::Initialize(dll_hModule); + InitializeCriticalSection(&ScreenshotInput::ScanThread::critical); + HANDLE hGuiThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)GuiThread, dll_hModule, CREATE_SUSPENDED, &Proto::GuiThreadID); From aa42036cdd36989d3c6ea2041952fdd18daeb6b7 Mon Sep 17 00:00:00 2001 From: messenils Date: Wed, 11 Feb 2026 08:33:34 +0100 Subject: [PATCH 10/20] repaired stick axis buttons, added GetCursorInfoHook --- .../ProtoInputHooks/GetCursorInfoHook.cpp | 64 +++++++++++++++++++ .../ProtoInputHooks/GetCursorInfoHook.h | 22 +++++++ src/ProtoInput/ProtoInputHooks/Gui.cpp | 8 +-- .../ProtoInputHooks/HookManager.cpp | 10 +-- .../ProtoInputHooks/ProtoInputHooks.vcxproj | 5 ++ .../ProtoInputHooks.vcxproj.filters | 6 ++ .../ProtoInputHooks.vcxproj.user | 4 +- .../ProtoInputHooks/TranslateXtoMKB.cpp | 41 +++++++----- src/ProtoInput/ProtoInputHost/Gui.cpp | 1 + src/ProtoInput/ProtoInputHost/Profiles.h | 3 +- .../ProtoInputHost/ProtoInputHost.cpp | 1 + .../ProtoInputLoader/include/protoloader.h | 3 +- 12 files changed, 136 insertions(+), 32 deletions(-) create mode 100644 src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp create mode 100644 src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.h diff --git a/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp b/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp new file mode 100644 index 0000000..04f787a --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp @@ -0,0 +1,64 @@ +#include "GetCursorInfoHook.h" +#include "FakeMouseKeyboard.h" +#include "HwndSelector.h" + +namespace Proto +{ + + BOOL WINAPI Hook_GetCursorInfo(PCURSORINFO pci) + { + if (pci) + { + const auto& state = FakeMouseKeyboard::GetMouseState(); + POINT clientPos = pci->ptScreenPos; + ScreenToClient((HWND)HwndSelector::GetSelectedHwnd(), &clientPos); + clientPos.x = state.x; + clientPos.y = state.y; + + clientPos.x = state.x; + clientPos.y = state.y; + + + if (FakeMouseKeyboard::PutMouseInsideWindow) + { + int clientWidth = HwndSelector::windowWidth; + int clientHeight = HwndSelector::windowHeight; + if (!FakeMouseKeyboard::DefaultTopLeftMouseBounds) + { + if (clientPos.y < 1) + clientPos.y = 0; // Top edge + if (clientPos.x < 1) + clientPos.x = 0; // Left edge + } + if (!FakeMouseKeyboard::DefaultBottomRightMouseBounds) + { + if (clientPos.y > clientHeight - 1) + clientPos.y = clientHeight - 1; // Bottom edge + if (clientPos.x > clientWidth - 1) + clientPos.x = clientWidth - 1; // Right edge + } + } + ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &clientPos); + pci->ptScreenPos.x = clientPos.x; + pci->ptScreenPos.y = clientPos.y; + } + + return true; + } + + void GetCursorInfoHook::ShowGuiStatus() + { + + } + + void GetCursorInfoHook::InstallImpl() + { + hookInfo = std::get<1>(InstallNamedHook(L"user32", "GetCursorInfo", Hook_GetCursorInfo)); + } + + void GetCursorInfoHook::UninstallImpl() + { + UninstallHook(&hookInfo); + } + +} diff --git a/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.h b/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.h new file mode 100644 index 0000000..0e1a016 --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.h @@ -0,0 +1,22 @@ +#pragma once +#include "Hook.h" +#include "InstallHooks.h" + +namespace Proto +{ + + class GetCursorInfoHook final : public Hook + { + private: + HookInfo hookInfo{}; + + public: + const char* GetHookName() const override { return "Get Cursor Position with GetCursorInfo"; } + const char* GetHookDescription() const override { return "Hooks the GetCursorInfo function to return our 'fake' position"; } + bool HasGuiStatus() const override { return false; } + void ShowGuiStatus() override; + void InstallImpl() override; + void UninstallImpl() override; + }; + +} diff --git a/src/ProtoInput/ProtoInputHooks/Gui.cpp b/src/ProtoInput/ProtoInputHooks/Gui.cpp index 98b5f8c..512d3ac 100644 --- a/src/ProtoInput/ProtoInputHooks/Gui.cpp +++ b/src/ProtoInput/ProtoInputHooks/Gui.cpp @@ -169,7 +169,7 @@ void XTranslatefreshmapping(bool read) { X_stickdown = ScreenshotInput::TranslateXtoMKB::stickdownmapping; X_option = ScreenshotInput::TranslateXtoMKB::optionmapping; - X_start = ScreenshotInput::TranslateXtoMKB::optionmapping; + X_start = ScreenshotInput::TranslateXtoMKB::startmapping; X_stickdown = ScreenshotInput::TranslateXtoMKB::stickdownmapping; }//ImGui::SliderFloat("Slider", &sliderValue, 0.0f, 1.0f); @@ -586,7 +586,7 @@ void XTranslateMenu() ImGui::Separator(); { const auto XstickdownString = VkToKeyName(X_stickdown); - ImGui::TextWrapped("Stick up axis is mapped to: %s", (XstickdownString.c_str())); + ImGui::TextWrapped("Stick down axis is mapped to: %s", (XstickdownString.c_str())); static bool waitingKeyPressstickdown = false; if (waitingKeyPressstickdown) @@ -612,7 +612,7 @@ void XTranslateMenu() ImGui::Separator(); { const auto XoptionString = VkToKeyName(X_option); - ImGui::TextWrapped("Stick Options button is mapped to: %s", (XoptionString.c_str())); + ImGui::TextWrapped("Options button is mapped to: %s", (XoptionString.c_str())); static bool waitingKeyPressoption = false; if (waitingKeyPressoption) @@ -638,7 +638,7 @@ void XTranslateMenu() ImGui::Separator(); { const auto XstartString = VkToKeyName(X_start); - ImGui::TextWrapped("Stick Start button is mapped to: %s", (XstartString.c_str())); + ImGui::TextWrapped("Start button is mapped to: %s", (XstartString.c_str())); static bool waitingKeyPressstart = false; if (waitingKeyPressstart) diff --git a/src/ProtoInput/ProtoInputHooks/HookManager.cpp b/src/ProtoInput/ProtoInputHooks/HookManager.cpp index 5a454b9..bceffba 100644 --- a/src/ProtoInput/ProtoInputHooks/HookManager.cpp +++ b/src/ProtoInput/ProtoInputHooks/HookManager.cpp @@ -21,6 +21,7 @@ #include "MoveWindowHook.h" #include "AdjustWindowRectHook.h" #include "RemoveBorderHook.h" +#include "GetCursorInfoHook.h" #include "RawInput.h" #include "TranslateXtoMKB.h" @@ -54,6 +55,7 @@ HookManager::HookManager() AddHook(ProtoHookIDs::MoveWindowHookID);//19 AddHook(ProtoHookIDs::AdjustWindowRectHookID);//20 AddHook(ProtoHookIDs::RemoveBorderHookID);//21 + AddHook(ProtoHookIDs::GetCursorInfoHookID);//22 } void HookManager::InstallHook(ProtoHookIDs hookID) @@ -118,14 +120,6 @@ bool HookManager::IsInstalled(ProtoHookIDs hookID) } else { - if(RawInput::TranslateXinputtoMKB) - { - if (hookID == 0) return hookManagerInstance.hooks[hookID]->IsInstalled(); - if (hookID == 1) return hookManagerInstance.hooks[hookID]->IsInstalled(); - if (hookID == 2) return hookManagerInstance.hooks[hookID]->IsInstalled(); - else return hookManagerInstance.hooks[hookID]->IsInstalled(); - } - else return hookManagerInstance.hooks[hookID]->IsInstalled(); } } diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj index 3e8f536..82f36fe 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj @@ -87,6 +87,9 @@ $(SolutionDir)$(Configuration)\ $(PlatformShortName)\$(Configuration)\ $(ProjectName)$(PlatformArchitecture) + CppCoreCheckConcurrencyRules.ruleset + true + false false @@ -205,6 +208,7 @@ + @@ -269,6 +273,7 @@ + diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters index 3923cbd..1886ce6 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters @@ -195,6 +195,9 @@ Source Files\Hooks\TranslateXtoMKB + + Source Files\Hooks + @@ -350,5 +353,8 @@ Source Files\Hooks\TranslateXtoMKB + + Source Files\Hooks + \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.user b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.user index 0f14913..dc63f8a 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.user +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.user @@ -1,4 +1,6 @@  - + + false + \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp index ca8245b..029ae58 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -72,10 +72,10 @@ namespace ScreenshotInput int updatewindowtick = 300; - int AxisLeftsens; - int AxisRightsens; - int AxisUpsens; - int AxisDownsens; + int AxisLeftsens = -15000; + int AxisRightsens = 15000; + int AxisUpsens = 15000; + int AxisDownsens = -15000; int scrollspeed3; float radial_deadzone = 0.10f; // Circular/Radial Deadzone (0.0 to 0.3) float axial_deadzone = 0.00f; // Square/Axial Deadzone (0.0 to 0.3) @@ -334,11 +334,19 @@ namespace ScreenshotInput return std::wstring(s.begin(), s.end()); } bool readsettings() { - char buffer[16]; //or only 4 maybe + char buffer[64]; //or only 4 maybe // settings reporting std::string iniPath = UGetExeFolder() + "\\Xinput.ini"; std::string iniSettings = "Settings"; + GetPrivateProfileStringA(iniSettings.c_str(), "Axial_Deadzone", "0.0", buffer, sizeof(buffer), iniPath.c_str()); + axial_deadzone = std::stof(buffer); //sensitivity + + GetPrivateProfileStringA(iniSettings.c_str(), "Sensitivity", "12.0", buffer, sizeof(buffer), iniPath.c_str()); + sensitivity = std::stof(buffer); //sensitivity //accel_multiplier + + GetPrivateProfileStringA(iniSettings.c_str(), "Accel_Multiplier", "2.5", buffer, sizeof(buffer), iniPath.c_str()); + accel_multiplier = std::stof(buffer); return true; } @@ -502,14 +510,14 @@ namespace ScreenshotInput } else { oldscrollleft = false; - ButtonStateImpulse(TranslateXtoMKB::stickleftmapping, false);//down + ButtonStateImpulse(TranslateXtoMKB::stickrightmapping, false);//down } } else if (scrollXaxis < AxisLeftsens) //left { oldscrollleft = true; - ButtonStateImpulse(TranslateXtoMKB::stickleftmapping, true);//down + ButtonStateImpulse(TranslateXtoMKB::stickrightmapping, true);//down } if (oldscrollright) @@ -519,18 +527,18 @@ namespace ScreenshotInput } else { oldscrollright = false; - ButtonStateImpulse(TranslateXtoMKB::stickrightmapping, false);//down + ButtonStateImpulse(TranslateXtoMKB::stickleftmapping, false);//down } } else if (scrollXaxis > AxisRightsens) //left { oldscrollright = true; - ButtonStateImpulse(TranslateXtoMKB::stickrightmapping, true);//down + ButtonStateImpulse(TranslateXtoMKB::stickleftmapping, true);//down } if (oldscrollup) { - if (scrollXaxis > AxisUpsens) //left + if (scrollYaxis > AxisUpsens) //left { } else { @@ -538,7 +546,7 @@ namespace ScreenshotInput ButtonStateImpulse(TranslateXtoMKB::stickupmapping, false);//down } } - else if (scrollXaxis > AxisUpsens) //left + else if (scrollYaxis > AxisUpsens) //left { oldscrollup = true; ButtonStateImpulse(TranslateXtoMKB::stickupmapping, true);//down @@ -546,7 +554,7 @@ namespace ScreenshotInput if (oldscrolldown) { - if (scrollXaxis < AxisDownsens) //left + if (scrollYaxis < AxisDownsens) //left { } else { @@ -554,7 +562,7 @@ namespace ScreenshotInput ButtonStateImpulse(TranslateXtoMKB::stickdownmapping, false);//down } } - else if (scrollXaxis < AxisDownsens) //left + else if (scrollYaxis < AxisDownsens) //left { oldscrolldown = true; ButtonStateImpulse(TranslateXtoMKB::stickdownmapping, true);//down @@ -766,7 +774,7 @@ namespace ScreenshotInput ButtonStateImpulse(TranslateXtoMKB::downmapping, true);//down } - if (oldstartoptions) + if (oldstartoptions) //toggle fake cursor { if (oldstart && oldoptions) { @@ -774,12 +782,11 @@ namespace ScreenshotInput else { oldstartoptions = false; - ButtonStateImpulse(VK_HOME, false);//down} } } - else if (oldstart && oldoptions)//gui or fake cursor toggle + else if (oldstart && oldoptions)//fake cursor toggle { - ButtonStateImpulse(VK_HOME, true);//down + Proto::FakeCursor::SetCursorVisibility(!Proto::FakeCursor::GetCursorVisibility()); oldstartoptions = true; } if (oldstart) diff --git a/src/ProtoInput/ProtoInputHost/Gui.cpp b/src/ProtoInput/ProtoInputHost/Gui.cpp index d27f38e..4490a77 100644 --- a/src/ProtoInput/ProtoInputHost/Gui.cpp +++ b/src/ProtoInput/ProtoInputHost/Gui.cpp @@ -206,6 +206,7 @@ bool Launch() if (hookEnabled(XinputHookID)) InstallHook(instanceHandle, XinputHookID); if (hookEnabled(DinputOrderHookID)) InstallHook(instanceHandle, DinputOrderHookID); + if (hookEnabled(GetCursorInfoHookID)) InstallHook(instanceHandle, GetCursorInfoHookID); if (filterEnabled(RawInputFilterID)) EnableMessageFilter(instanceHandle, RawInputFilterID); if (filterEnabled(MouseMoveFilterID)) EnableMessageFilter(instanceHandle, MouseMoveFilterID); diff --git a/src/ProtoInput/ProtoInputHost/Profiles.h b/src/ProtoInput/ProtoInputHost/Profiles.h index 2d6f758..d2b0ba3 100644 --- a/src/ProtoInput/ProtoInputHost/Profiles.h +++ b/src/ProtoInput/ProtoInputHost/Profiles.h @@ -55,7 +55,8 @@ struct Profile { "Rename Handles", true, "Rename Handles", ProtoHookIDs::RenameHandlesHookID }, { "Block Raw Input", false, "Block Raw Input", ProtoHookIDs::BlockRawInputHookID }, { "Dinput Order", false, "Dinput Order", ProtoHookIDs::DinputOrderHookID }, - { "Xinput", false, "Xinput", ProtoHookIDs::XinputHookID } + { "Xinput", false, "Xinput", ProtoHookIDs::XinputHookID }, + { "GetCursorInfo", false, "GetCursorInfo", ProtoHookIDs::GetCursorInfoHookID } }; std::vector messageFilters diff --git a/src/ProtoInput/ProtoInputHost/ProtoInputHost.cpp b/src/ProtoInput/ProtoInputHost/ProtoInputHost.cpp index ea783a0..efd6e87 100644 --- a/src/ProtoInput/ProtoInputHost/ProtoInputHost.cpp +++ b/src/ProtoInput/ProtoInputHost/ProtoInputHost.cpp @@ -124,6 +124,7 @@ int main() InstallHook(instanceHandle, ClipCursorHookID); InstallHook(instanceHandle, FocusHooksHookID); InstallHook(instanceHandle, RenameHandlesHookID); + InstallHook(instanceHandle, GetCursorInfoHookID); EnableMessageFilter(instanceHandle, RawInputFilterID); EnableMessageFilter(instanceHandle, MouseMoveFilterID); diff --git a/src/ProtoInput/ProtoInputLoader/include/protoloader.h b/src/ProtoInput/ProtoInputLoader/include/protoloader.h index 226ad17..e8c9642 100644 --- a/src/ProtoInput/ProtoInputLoader/include/protoloader.h +++ b/src/ProtoInput/ProtoInputLoader/include/protoloader.h @@ -27,7 +27,8 @@ enum ProtoHookIDs : unsigned int WindowStyleHookID, MoveWindowHookID, AdjustWindowRectHookID, - RemoveBorderHookID + RemoveBorderHookID, + GetCursorInfoHookID }; enum ProtoMessageFilterIDs : unsigned int From b2bd6bf816158c4add91fd3ff0a05c61882490d7 Mon Sep 17 00:00:00 2001 From: messenils Date: Sun, 15 Feb 2026 00:09:31 +0100 Subject: [PATCH 11/20] near complete. just some render problem. already fixed for pointA --- .../ProtoInputHooks/BlockXinputHook.cpp | 85 ++ .../ProtoInputHooks/BlockXinputHook.h | 29 + src/ProtoInput/ProtoInputHooks/FakeCursor.cpp | 174 ++- src/ProtoInput/ProtoInputHooks/FakeCursor.h | 5 +- .../ProtoInputHooks/GetCursorInfoHook.cpp | 17 +- src/ProtoInput/ProtoInputHooks/Gui.cpp | 19 + .../ProtoInputHooks/HookManager.cpp | 36 +- .../ProtoInputHooks/PipeCommunication.cpp | 36 + .../ProtoInputHooks.vcxproj.filters | 18 +- src/ProtoInput/ProtoInputHooks/RawInput.cpp | 2 + src/ProtoInput/ProtoInputHooks/ScanThread.cpp | 114 +- src/ProtoInput/ProtoInputHooks/ScanThread.h | 5 +- .../ProtoInputHooks/TranslateXtoMKB.cpp | 1014 +++++++++-------- .../ProtoInputHooks/TranslateXtoMKB.h | 7 +- src/ProtoInput/ProtoInputHooks/dllmain.cpp | 6 +- .../ProtoInputHooks/pipeinclude/pipeinclude.h | 10 + src/ProtoInput/ProtoInputHost/Gui.cpp | 39 +- src/ProtoInput/ProtoInputHost/Profiles.h | 51 + src/ProtoInput/ProtoInputLoader/Inject.cpp | 14 +- .../ProtoInputLoader/include/protoloader.h | 4 +- 20 files changed, 1034 insertions(+), 651 deletions(-) create mode 100644 src/ProtoInput/ProtoInputHooks/BlockXinputHook.cpp create mode 100644 src/ProtoInput/ProtoInputHooks/BlockXinputHook.h diff --git a/src/ProtoInput/ProtoInputHooks/BlockXinputHook.cpp b/src/ProtoInput/ProtoInputHooks/BlockXinputHook.cpp new file mode 100644 index 0000000..ea6df2e --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/BlockXinputHook.cpp @@ -0,0 +1,85 @@ +#include "BlockXinputHook.h" +#include +#include + +namespace Proto +{ + + DWORD WINAPI Hook_XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState) + { + return ERROR_SUCCESS; + } + DWORD WINAPI Hook_XInputGetStateEx(DWORD dwUserIndex, XINPUT_STATE* pState) + { + return ERROR_SUCCESS; + } + + DWORD WINAPI Hook_XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration) + { + return ERROR_SUCCESS; + } + + + void BlockXinputHook::ShowGuiStatus() + { + + ImGui::Separator(); + ImGui::Text("This hook blocks Xinput Controllers from being discovered by game."); + } + + void BlockXinputHook::InstallImpl() + { + // Some games (e.g. Terraria) haven't loaded the dlls when we inject hooks. So load all XInput dlls. + const wchar_t* xinputNames[] = { + L"xinput1_3.dll", L"xinput1_4.dll", L"xinput1_2.dll", L"xinput1_1.dll", L"xinput9_1_0.dll" + }; + for (const auto xinputName : xinputNames) + { + if (LoadLibraryW(xinputName) == nullptr) + { + fprintf(stderr, "Not hooking %ws as failed to load dll\n", xinputName); + continue; + } + + if (GetModuleHandleW(xinputName) == nullptr) + { + fprintf(stderr, "Not hooking %ws as failed get module\n", xinputName); + continue; + } + + hookInfos.push_back(std::get<1>(InstallNamedHook(xinputName, "XInputGetState", Hook_XInputGetState))); + hookInfos.push_back(std::get<1>(InstallNamedHook(xinputName, "XInputSetState", Hook_XInputSetState))); + } + //XinputGetStateEx (hidden call, ordinal 100). Only present in xinput1_4.dll and xinput1_3.dll. Used by EtG and DoS2 + //DWORD as 1st param and similar structure pointer for 2nd param (with an extra DWORD at the end). Can be treated as a normal XINPUT_STATE. + if (nullptr != LoadLibraryW(L"xinput1_4.dll")) + { + hookInfos.push_back(std::get<1>(InstallNamedHook(L"xinput1_4.dll", (LPCSTR)(100), Hook_XInputGetStateEx, true))); + } + if (nullptr != LoadLibraryW(L"xinput1_3.dll")) + { + hookInfos.push_back(std::get<1>(InstallNamedHook(L"xinput1_3.dll", (LPCSTR)(100), Hook_XInputGetStateEx, true))); + + XInputGetStateExPtr = t_XInputGetStateEx(GetProcAddress(GetModuleHandleW(L"xinput1_3.dll"), (LPCSTR)(100))); + XInputGetStatePtr = t_XInputGetState(GetProcAddress(GetModuleHandleW(L"xinput1_3.dll"), "XInputGetState")); + XInputSetStatePtr = t_XInputSetState(GetProcAddress(GetModuleHandleW(L"xinput1_3.dll"), "XInputSetState")); + + if (XInputGetStateExPtr == nullptr) + MessageBoxA(NULL, "XInputGetStateExPtr is null", "Error", MB_OK); + + if (XInputGetStatePtr == nullptr) + MessageBoxA(NULL, "XInputGetStatePtr is null", "Error", MB_OK); + + if (XInputSetStatePtr == nullptr) + MessageBoxA(NULL, "XInputSetStatePtr is null", "Error", MB_OK); + + if (XInputGetCapabilitiesPtr == nullptr) + MessageBoxA(NULL, "XInputGetCapabilitiesPtr is null", "Error", MB_OK); + } + + void BlockXinputHook::UninstallImpl() + { + UninstallHook(&hookInfoBlockXinput); + } + +} diff --git a/src/ProtoInput/ProtoInputHooks/BlockXinputHook.h b/src/ProtoInput/ProtoInputHooks/BlockXinputHook.h new file mode 100644 index 0000000..b8f786b --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/BlockXinputHook.h @@ -0,0 +1,29 @@ +#pragma once +#include "Hook.h" +#include "InstallHooks.h" + +namespace Proto +{ + + + class BlockXinputHook final : public Hook + { + private: + std::vector hookInfos{}; + + public: + const char* GetHookName() const override { return "Cursor Visibility"; } + const char* GetHookDescription() const override + { + return "Whenever the game calls for the cursor to be shown/hidden, the 'fake' cursor is shown/hidden instead. " + "Also detects when the game tries to set a custom cursor image, so the fake cursor can copy it. "; + } + bool HasGuiStatus() const override { return true; } + void ShowGuiStatus() override; + void InstallImpl() override; + void UninstallImpl() override; + + static bool ShowCursorWhenImageUpdated; + }; + +} \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp index d6002a8..f9fc492 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp @@ -5,6 +5,7 @@ #include "HwndSelector.h" #include "ScanThread.h" #include "TranslateXtoMKB.h" +#include "RawInput.h" #include namespace Proto @@ -14,7 +15,7 @@ FakeCursor FakeCursor::state{}; //TranslateXtoMKB POINT OldspotA, OldspotB, OldspotX, OldspotY; -int showmessage = 0; +int FakeCursor::Showmessage = 0; int oldmessage = 0; bool messageshown = false; HWND selectorhwnd = nullptr; //copy of variable in TranslateXtoMKB to avoid accessing it multiple times with critical section in DrawCursor @@ -118,88 +119,152 @@ void DrawPinkSquare(HDC hdc, int x, int y) } POINT OldTestpos = { 0,0 }; -void DrawMessage(HDC hdc, HWND window, HBRUSH Brush) +void FakeCursor::DrawMessage(HDC hdc, HWND window, HBRUSH Brush, int message) { POINT here = { 0,0 }; ClientToScreen(window, &here); - if (oldmessage != showmessage) + if (oldmessage != message) { - RECT fill{ 50, 50, 100, 100 }; - FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! - messageshown = false; + // RECT fill{ here.x + 20, here.y + 20, 500, 500 }; + // FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! + RECT wholewindow; + GetClientRect(pointerWindow, &wholewindow); + + FillRect(hdc, &wholewindow, Brush); + // MessageBoxA(NULL, "Message Erased!", "Debug", MB_OK); + /// messageshown = false; } if (!messageshown) { - if (showmessage == 12){ - DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + if (message == 1){ + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); TextOutW(hdc, here.x + 20, here.y + 20, TEXT("DISCONNECTED!"), 14); //14 messageshown = true; } + if (message == 2) { + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + TextOutW(hdc, here.x + 20, here.y + 20, TEXT("GUI TOGGLE!"), 11); //14 + messageshown = true; + } + if (message == 3) { + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + TextOutW(hdc, here.x + 20, here.y + 20, TEXT("SHOWCURSOR TOGGLE!"), 18); //14 + messageshown = true; + } + if (message == 4) { + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + TextOutW(hdc, here.x + 20, here.y + 20, TEXT("LOCK TOGGLED!"), 13); //14 + messageshown = true; + } + if (ScreenshotInput::TranslateXtoMKB::SaveBmps) { + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + TextOutW(hdc, here.x + 20, here.y + 0, TEXT("BMP SAVE MODE!"), 14); //14 + messageshown = true; + } + if (message == 10) { + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + TextOutW(hdc, here.x + 20, here.y + 25, TEXT("A MAPPED TO SPOT!"), 17); //14 + messageshown = true; + } + if (message == 11) { + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + TextOutW(hdc, here.x + 20, here.y + 25, TEXT("B MAPPED TO SPOT!"), 17); //14 + messageshown = true; + } + if (message == 12) { + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + TextOutW(hdc, here.x + 20, here.y + 25, TEXT("X MAPPED TO SPOT!"), 17); //14 + messageshown = true; + } + if (message == 13) { + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + TextOutW(hdc, here.x + 20, here.y + 25, TEXT("Y MAPPED TO SPOT!"), 17); //14 + messageshown = true; + } } - oldmessage = showmessage; + oldmessage = message; } -void DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, POINT spotY,HWND window, HBRUSH Brush) +void FakeCursor::DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, POINT spotY,HWND window, HBRUSH Brush) { bool windowmoved = false; - bool erased = false; + bool erasedA = false; + bool erasedB = false; + bool erasedX = false; + bool erasedY = false; //detect window change pos POINT testpos; ClientToScreen(window, &testpos); if (testpos.x < OldTestpos.x || testpos.y < OldTestpos.y || testpos.x > OldTestpos.x || testpos.y > OldTestpos.y) { windowmoved = true; + //MessageBoxA(NULL, "Window moved!", "Debug", MB_OK); } - if (OldspotA.x != spotA.x || OldspotA.y != spotA.y || windowmoved) + if (OldspotA.x != spotA.x) { - RECT fill{ OldspotA.x - 20, OldspotA.y - 20, OldspotA.x + 20, OldspotA.y + 20 }; - FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! - erased = true; + RECT wholewindow; + GetClientRect(pointerWindow, &wholewindow); + + FillRect(hdc, &wholewindow, Brush); + erasedA = true; + // std::string text = "OldSpot:\nA = " + std::to_string(OldspotA.x) + + // "\nNewspot = " + std::to_string(spotA.x); + // MessageBoxA(NULL, text.c_str(), "Two Integers", MB_OK); } - if (OldspotB.x != spotB.x || OldspotB.y != spotB.y || windowmoved) + + if (OldspotB.x != spotB.x || OldspotB.y != spotB.y) //|| windowmoved) { RECT fill{ OldspotB.x - 20, OldspotB.y - 20, OldspotB.x + 20, OldspotB.y + 20 }; FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! - erased = true; + erasedB = true; } - if (OldspotX.x != spotX.x || OldspotX.y != spotX.y || windowmoved) + if (OldspotX.x != spotX.x || OldspotX.y != spotX.y) //|| windowmoved) { RECT fill{ OldspotX.x - 20, OldspotX.y - 20, OldspotX.x + 20, OldspotX.y + 20 }; FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! - erased = true; + erasedX = true; } - if (OldspotY.x != spotY.x || OldspotY.y != spotY.y || windowmoved) + if (OldspotY.x != spotY.x || OldspotY.y != spotY.y) //|| windowmoved) { RECT fill{ OldspotY.x - 20, OldspotY.y - 20, OldspotY.x + 20, OldspotY.y + 20 }; FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! - erased = true; + erasedY = true; } - if (spotA.x != 0 && spotA.y != 0 && erased == true) + + OldspotA.x = spotA.x; + OldspotB = spotB; + OldspotX = spotX; + OldspotY = spotY; + + + + + if (spotA.x != 0 && spotA.y != 0 && erasedA == true) { ClientToScreen(window, &spotA); DrawRedX(hdc, spotA.x, spotA.y); + //MessageBoxA(NULL, "Spot A drawn!", "Debug", MB_OK); + erasedA = false; } - if (spotB.x != 0 && spotB.y != 0 && erased == true) + if (spotB.x != 0 && spotB.y != 0 && erasedB == true) { ClientToScreen(window, &spotB); DrawBlueCircle(hdc, spotB.x, spotB.y); } - if (spotX.x != 0 && spotX.y != 0 && erased == true) + if (spotX.x != 0 && spotX.y != 0 && erasedX == true) { ClientToScreen(window, &spotX); DrawGreenTriangle(hdc, spotX.x, spotX.y); } - if (spotY.x != 0 && spotY.y != 0 && erased == true) + if (spotY.x != 0 && spotY.y != 0 && erasedY == true) { ClientToScreen(window, &spotY); DrawPinkSquare(hdc, spotY.x, spotY.y); } - OldspotA = spotA; - OldspotB = spotB; - OldspotX = spotX; - OldspotY = spotY; + + OldTestpos = testpos; } void FakeCursor::DrawCursor() @@ -212,19 +277,21 @@ void FakeCursor::DrawCursor() } - if (ScreenshotInput::ScanThread::scanoption == 1) + if (ScreenshotInput::ScanThread::scanoption) { EnterCriticalSection(&ScreenshotInput::ScanThread::critical); selectorhwnd = (HWND)HwndSelector::GetSelectedHwnd(); - showmessage = ScreenshotInput::TranslateXtoMKB::showmessage; + // FakeCursor::Showmessage = ScreenshotInput::TranslateXtoMKB::showmessage; POINT Apos = { ScreenshotInput::ScanThread::PointA.x, ScreenshotInput::ScanThread::PointA.y }; - POINT Bpos = { ScreenshotInput::ScanThread::PointB.x, ScreenshotInput::ScanThread::PointB.y }; + POINT Bpos = { ScreenshotInput::ScanThread::PointB.x, ScreenshotInput::ScanThread::PointB.y }; POINT Xpos = { ScreenshotInput::ScanThread::PointX.x, ScreenshotInput::ScanThread::PointX.y }; POINT Ypos = { ScreenshotInput::ScanThread::PointY.x, ScreenshotInput::ScanThread::PointY.y }; - DrawFoundSpots(hdc, Apos, Bpos, Xpos, Ypos, selectorhwnd, transparencyBrush); - //DrawMessage(hdc, selectorhwnd, transparencyBrush); + FakeCursor::DrawFoundSpots(hdc, Apos, Bpos, Xpos, Ypos, selectorhwnd, transparencyBrush); + FakeCursor::DrawMessage(hdc, selectorhwnd, transparencyBrush, FakeCursor::Showmessage); LeaveCriticalSection(&ScreenshotInput::ScanThread::critical); } + else if (RawInput::TranslateXinputtoMKB) + DrawMessage(hdc, (HWND)HwndSelector::GetSelectedHwnd(), transparencyBrush, FakeCursor::Showmessage); oldHadShowCursor = showCursor; @@ -358,21 +425,38 @@ void FakeCursor::StartDrawLoopInternal() { int tick = 0; + if (Proto::RawInput::TranslateXinputtoMKB) + ScreenshotInput::TranslateXtoMKB::Initialize(GetModuleHandle(NULL)); + while (true) { - std::unique_lock lock(mutex); - conditionvar.wait(lock); - - DrawCursor(); - - //TODO: is this ok? (might eat cpu) - Sleep(drawingEnabled ? 12 : 500); - + if (!Proto::RawInput::TranslateXinputtoMKB) + { + std::unique_lock lock(mutex); + conditionvar.wait(lock); + + DrawCursor(); + + //TODO: is this ok? (might eat cpu) + Sleep(drawingEnabled ? 12 : 500); + } + else { + ScreenshotInput::TranslateXtoMKB::ThreadFunction(); + if (ScreenshotInput::TranslateXtoMKB::RefreshWindow > 0) + { + DrawCursor(); + ScreenshotInput::TranslateXtoMKB::RefreshWindow--; + } + } tick = (tick + 1) % 200; - if (tick == 0) + if (tick == 0 && pointerWindow != GetForegroundWindow()) + { // Nucleus can put the game window above the pointer without this SetWindowPos(pointerWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE); + } + + } } @@ -465,10 +549,10 @@ void FakeCursor::EnableDisableFakeCursor(bool enable) UpdateWindow(state.pointerWindow); } -void FakeCursor::Initialise() +void FakeCursor::Initialise(HMODULE module) { const auto threadHandle = CreateThread(nullptr, 0, - (LPTHREAD_START_ROUTINE)FakeCursorThreadStart, GetModuleHandle(0), 0, 0); + (LPTHREAD_START_ROUTINE)FakeCursorThreadStart, module, 0, 0); if (threadHandle != nullptr) CloseHandle(threadHandle); diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.h b/src/ProtoInput/ProtoInputHooks/FakeCursor.h index 564874d..0a2cbbd 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.h +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.h @@ -40,6 +40,8 @@ namespace Proto unsigned int toggleVisibilityVkey = VK_HOME; void DrawCursor(); + void DrawMessage(HDC hdc, HWND window, HBRUSH Brush, int message); + void DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, POINT spotY, HWND window, HBRUSH Brush); public: static FakeCursor state; @@ -47,6 +49,7 @@ namespace Proto void StartInternal(); void StartDrawLoopInternal(); + static int Showmessage; static bool& GetToggleVisilbityShorcutEnabled() { return state.toggleVisilbityShorcutEnabled; @@ -90,7 +93,7 @@ namespace Proto static void EnableDisableFakeCursor(bool enable); - static void Initialise(); + static void Initialise(HMODULE module); }; } diff --git a/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp b/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp index 04f787a..95baa9f 100644 --- a/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp @@ -7,18 +7,11 @@ namespace Proto BOOL WINAPI Hook_GetCursorInfo(PCURSORINFO pci) { - if (pci) + if (GetCursorInfo(pci)) { + const auto& state = FakeMouseKeyboard::GetMouseState(); - POINT clientPos = pci->ptScreenPos; - ScreenToClient((HWND)HwndSelector::GetSelectedHwnd(), &clientPos); - clientPos.x = state.x; - clientPos.y = state.y; - - clientPos.x = state.x; - clientPos.y = state.y; - - + POINT clientPos = { state.x, state.y }; if (FakeMouseKeyboard::PutMouseInsideWindow) { int clientWidth = HwndSelector::windowWidth; @@ -41,9 +34,11 @@ namespace Proto ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &clientPos); pci->ptScreenPos.x = clientPos.x; pci->ptScreenPos.y = clientPos.y; + } - return true; + + } void GetCursorInfoHook::ShowGuiStatus() diff --git a/src/ProtoInput/ProtoInputHooks/Gui.cpp b/src/ProtoInput/ProtoInputHooks/Gui.cpp index 512d3ac..da826a1 100644 --- a/src/ProtoInput/ProtoInputHooks/Gui.cpp +++ b/src/ProtoInput/ProtoInputHooks/Gui.cpp @@ -192,6 +192,11 @@ void XTranslateMenu() { if (!mappingrefreshed) XTranslatefreshmapping(true); + + ImGui::SliderInt("Sensitivity flat", (int*)&ScreenshotInput::TranslateXtoMKB::Sens, 1, 40, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::Separator(); + ImGui::SliderInt("Sensitivity exponential", (int*)&ScreenshotInput::TranslateXtoMKB::Sensmult, 1, 20, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::Separator(); { const auto XAString = VkToKeyName(X_A); ImGui::TextWrapped("A is mapped to: %s", (XAString.c_str())); @@ -667,6 +672,20 @@ void XTranslateMenu() ImGui::Separator(); ImGui::Checkbox("Shoulder Swap BMPs", &ScreenshotInput::ScanThread::ShoulderNextBMP); // ImGui::Separator(); + ImGui::Text("Input actions for Scanoption. 0 is move+click. 1 is only move. 2 is only click"); + ImGui::SliderInt("A coordinate", (int*)&ScreenshotInput::ScanThread::scanAtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::SliderInt("B coordinate", (int*)&ScreenshotInput::ScanThread::scanBtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::SliderInt("X coordinate", (int*)&ScreenshotInput::ScanThread::scanXtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::SliderInt("Y coordinate", (int*)&ScreenshotInput::ScanThread::scanYtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::Separator(); + ImGui::Text("Save BMP mode. buttons XYAB will save a bmp on press at fake cursor coordinate when enabled. This option also force ScanOption to deactivate"); + ImGui::Checkbox("Save BMP mode:", &ScreenshotInput::TranslateXtoMKB::SaveBmps); // + ImGui::Separator(); + ImGui::Text("Scanoption will need a restart to discover new bmps."); + ImGui::Checkbox("ScanOption:", &ScreenshotInput::ScanThread::scanoption); // + ImGui::Separator(); + if (!ScreenshotInput::ScanThread::scanoption) + ScreenshotInput::ScanThread::scanloop = false; } void HooksMenu() { diff --git a/src/ProtoInput/ProtoInputHooks/HookManager.cpp b/src/ProtoInput/ProtoInputHooks/HookManager.cpp index bceffba..ba63279 100644 --- a/src/ProtoInput/ProtoInputHooks/HookManager.cpp +++ b/src/ProtoInput/ProtoInputHooks/HookManager.cpp @@ -65,25 +65,7 @@ void HookManager::InstallHook(ProtoHookIDs hookID) std::cerr << "Trying to install hook ID " << hookID << " which is out of range" << std::endl; else { - if (!RawInput::TranslateXinputtoMKB) - hookManagerInstance.hooks[hookID]->Install(); - else // skipping original protoinput hooks on experimental Xinput to MKB translation mode - { - if (hookID == 0) hookManagerInstance.hooks[hookID]->Install(); - if (hookID == 1) hookManagerInstance.hooks[hookID]->Install(); - if (hookID == 2) hookManagerInstance.hooks[hookID]->Install(); - if (hookID == 3) hookManagerInstance.hooks[hookID]->Install(); - if (hookID == 4) hookManagerInstance.hooks[hookID]->Install(); - if (hookID == 5) hookManagerInstance.hooks[hookID]->Install(); - if (hookID == 6) hookManagerInstance.hooks[hookID]->Install(); - if (hookID == 7) hookManagerInstance.hooks[hookID]->Install(); - if (hookID == 8) hookManagerInstance.hooks[hookID]->Install(); - if (hookID == 9) hookManagerInstance.hooks[hookID]->Install(); - if (hookID > 9 && hookID != 15) //15 is block rawinput dont want that. - hookManagerInstance.hooks[hookID]->Install(); - - } - + hookManagerInstance.hooks[hookID]->Install(); } } @@ -93,21 +75,7 @@ void HookManager::UninstallHook(ProtoHookIDs hookID) std::cerr << "Trying to uninstall hook ID " << hookID << " which is out of range" << std::endl; else { - if (!RawInput::TranslateXinputtoMKB) - hookManagerInstance.hooks[hookID]->Uninstall(); - else - if (hookID == 0) hookManagerInstance.hooks[hookID]->Uninstall(); - if (hookID == 1) hookManagerInstance.hooks[hookID]->Uninstall(); - if (hookID == 2) hookManagerInstance.hooks[hookID]->Uninstall(); - if (hookID == 3) hookManagerInstance.hooks[hookID]->Uninstall(); - if (hookID == 4) hookManagerInstance.hooks[hookID]->Uninstall(); - if (hookID == 5) hookManagerInstance.hooks[hookID]->Uninstall(); - if (hookID == 6) hookManagerInstance.hooks[hookID]->Uninstall(); - if (hookID == 7) hookManagerInstance.hooks[hookID]->Uninstall(); - if (hookID == 8) hookManagerInstance.hooks[hookID]->Uninstall(); - if (hookID == 9) hookManagerInstance.hooks[hookID]->Uninstall(); - if (hookID > 9 && hookID != 15) //15 is block rawinput dont want that. - hookManagerInstance.hooks[hookID]->Uninstall(); + hookManagerInstance.hooks[hookID]->Uninstall(); } } diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index f9b78db..9926cc0 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -379,6 +379,11 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) if (RawInput::TranslateXinputtoMKB == true) { ScreenshotInput::TranslateXtoMKB::controllerID = XinputHook::controllerIndex - 1; + //Xinput hook can block controller making TranslateXtoMKB work on games with Xinput support + XinputHook::controllerIndex = 0; + XinputHook::controllerIndex2 = 0; + XinputHook::controllerIndex3 = 0; + XinputHook::controllerIndex4 = 0; } break; } @@ -633,6 +638,8 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) ScreenshotInput::TranslateXtoMKB::optionmapping = body->XinputtoMKBoption; ScreenshotInput::TranslateXtoMKB::startmapping = body->XinputtoMKBstart; + ScreenshotInput::TranslateXtoMKB::Sens = body->XinputtoMKBsens; + ScreenshotInput::TranslateXtoMKB::Sensmult = body->XinputtoMKBsensmult; break; } //PipeMessageSetXinputtoMKBCFG case ProtoPipe::PipeMessageType::SetXinputtoMKBCFG: @@ -645,6 +652,35 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) ScreenshotInput::ScanThread::Bisstatic = body->bstsatic; ScreenshotInput::ScanThread::Xisstatic = body->xstsatic; ScreenshotInput::ScanThread::Yisstatic = body->ystsatic; + + if (body->amove && body->aclick) + ScreenshotInput::ScanThread::scanAtype = 0; + else if (body->amove) + ScreenshotInput::ScanThread::scanAtype = 1; + else if (body->aclick) + ScreenshotInput::ScanThread::scanAtype = 2; + + if (body->bmove && body->bclick) + ScreenshotInput::ScanThread::scanBtype = 0; + else if (body->bmove) + ScreenshotInput::ScanThread::scanBtype = 1; + else if (body->bclick) + ScreenshotInput::ScanThread::scanBtype = 2; + + if (body->xmove && body->xclick) + ScreenshotInput::ScanThread::scanXtype = 0; + else if (body->xmove) + ScreenshotInput::ScanThread::scanXtype = 1; + else if (body->xclick) + ScreenshotInput::ScanThread::scanXtype = 2; + + if (body->ymove && body->yclick) + ScreenshotInput::ScanThread::scanYtype = 0; + else if (body->ymove) + ScreenshotInput::ScanThread::scanYtype = 1; + else if (body->yclick) + ScreenshotInput::ScanThread::scanYtype = 2; + break; } default: diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters index 1886ce6..7d5bbf3 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters @@ -28,7 +28,7 @@ {14e41680-f011-4d2c-b31b-3fd2d6ae9a52} - + {a0d1a945-2bce-40dd-88b8-54724cf1b678} @@ -184,16 +184,16 @@ Source Files\Hooks - Source Files\Hooks\TranslateXtoMKB + Source Files\TranslateXtoMKB - Source Files\Hooks\TranslateXtoMKB + Source Files\TranslateXtoMKB - Source Files\Hooks\TranslateXtoMKB + Source Files\TranslateXtoMKB - Source Files\Hooks\TranslateXtoMKB + Source Files\TranslateXtoMKB Source Files\Hooks @@ -342,16 +342,16 @@ Source Files\Hooks - Source Files\Hooks\TranslateXtoMKB + Source Files\TranslateXtoMKB - Source Files\Hooks\TranslateXtoMKB + Source Files\TranslateXtoMKB - Source Files\Hooks\TranslateXtoMKB + Source Files\TranslateXtoMKB - Source Files\Hooks\TranslateXtoMKB + Source Files\TranslateXtoMKB Source Files\Hooks diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.cpp b/src/ProtoInput/ProtoInputHooks/RawInput.cpp index 7ca80b3..69c5a6d 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.cpp +++ b/src/ProtoInput/ProtoInputHooks/RawInput.cpp @@ -329,6 +329,7 @@ void RawInput::ProcessRawInput(HRAWINPUT rawInputHandle, bool inForeground, cons if ((GetAsyncKeyState(VK_RCONTROL) & ~1) != 0 && (GetAsyncKeyState(VK_RMENU) & ~1) != 0) // if ((GetAsyncKeyState(VK_LCONTROL) & ~1) != 0 && (GetAsyncKeyState(VK_LMENU) & ~1) != 0) { + //FakeCursor::Showmessage = 2; Proto::ToggleWindow(); } } @@ -355,6 +356,7 @@ void RawInput::ProcessRawInput(HRAWINPUT rawInputHandle, bool inForeground, cons { printf(locked ? "Locking input\n" : "Unlocking input\n"); RawInput::ToggleLockInput(); + //FakeCursor::Showmessage = 3; } diff --git a/src/ProtoInput/ProtoInputHooks/ScanThread.cpp b/src/ProtoInput/ProtoInputHooks/ScanThread.cpp index 22e2a8f..942995a 100644 --- a/src/ProtoInput/ProtoInputHooks/ScanThread.cpp +++ b/src/ProtoInput/ProtoInputHooks/ScanThread.cpp @@ -35,7 +35,7 @@ namespace ScreenshotInput { //public // extern int drawfakecursor; int ScanThread::Aisstatic, ScanThread::Bisstatic, ScanThread::Xisstatic, ScanThread::Yisstatic; - + bool ScanThread::UpdateWindow; int ScanThread::numphotoA, ScanThread::numphotoB, ScanThread::numphotoX, ScanThread::numphotoY; int ScanThread::numphotoC, ScanThread::numphotoD, ScanThread::numphotoE, ScanThread::numphotoF; int ScanThread::numphotoAbmps, ScanThread::numphotoBbmps, ScanThread::numphotoXbmps, ScanThread::numphotoYbmps; @@ -46,10 +46,11 @@ namespace ScreenshotInput { std::vector ScanThread::staticPointA, ScanThread::staticPointB, ScanThread::staticPointX, ScanThread::staticPointY; int ScanThread::scanAtype, ScanThread::scanBtype, ScanThread::scanXtype, ScanThread::scanYtype; int ScanThread::Ctype, ScanThread::Dtype, ScanThread::Etype, ScanThread::Ftype; - bool ScanThread::scanloop = true; - int ScanThread::scanoption; + bool ScanThread::scanloop = false; + bool ScanThread::scanoption; bool ScanThread::ShoulderNextBMP; int ScanThread::resize = 1; //support scaling + HWND hwndhandle; POINT hwndres{ 0,0 }; //private @@ -159,21 +160,20 @@ namespace ScreenshotInput { Sleep(5); TranslateXtoMKB::SendMouseClick(X, Y, 4); Sleep(5); - TranslateXtoMKB::SendMouseClick(Xhold, Yhold, 8); + TranslateXtoMKB::SendMouseClick(-X, -Y, 8); } } - + POINT Aprevious{ 0,0 }, Bprevious{ 0,0 }, Xprevious{ 0,0 }, Yprevious{ 0,0 }; + int Awas; int Bwas; int Xwas; int Ywas; void Bmpfound(const char key[3], int X, int Y, int i, bool onlysearch, bool found, int store) { int input = 0; + //wait event + if (strcmp(key, "\\A") == 0) { if (found) { - - EnterCriticalSection(&ScanThread::critical); - Proto::FakeCursor::NotifyUpdatedCursorPosition(); - LeaveCriticalSection(&ScanThread::critical); if (onlysearch) { EnterCriticalSection(&ScanThread::critical); @@ -183,6 +183,9 @@ namespace ScreenshotInput { ScanThread::staticPointA[i].y = Y; ScanThread::PointA.x = X; ScanThread::PointA.y = Y; + if (Awas != ScanThread::startsearchA) + ScanThread::UpdateWindow = true; + Awas = ScanThread::startsearchA; LeaveCriticalSection(&ScanThread::critical); } else @@ -206,6 +209,10 @@ namespace ScreenshotInput { ScanThread::startsearchA = 0; ScanThread::PointA.x = 0; ScanThread::PointA.y = 0; + // if (Aprevious.x != X || Aprevious.y != Y) + // ScanThread::UpdateWindow = true; + // Aprevious.x = ScanThread::PointA.x; + // Aprevious.y = ScanThread::PointA.y; LeaveCriticalSection(&ScanThread::critical); } } @@ -225,6 +232,9 @@ namespace ScreenshotInput { ScanThread::staticPointB[i].x = X; ScanThread::staticPointB[i].y = Y; ScanThread::PointB.y = Y; + if (Bwas != i) + ScanThread::UpdateWindow = true; + Bwas = i; LeaveCriticalSection(&ScanThread::critical); } else @@ -247,6 +257,10 @@ namespace ScreenshotInput { ScanThread::startsearchB = 0; ScanThread::PointB.x = 0; ScanThread::PointB.y = 0; + // if (Bprevious.x != X || Bprevious.y != Y) + // ScanThread::UpdateWindow = true; + // Bprevious.x = ScanThread::PointB.x; + // Bprevious.y = ScanThread::PointB.y; LeaveCriticalSection(&ScanThread::critical); } } @@ -266,6 +280,9 @@ namespace ScreenshotInput { ScanThread::PointX.y = Y; ScanThread::staticPointX[i].x = X; ScanThread::staticPointX[i].y = Y; + if (Xwas != i) + ScanThread::UpdateWindow = true; + Xwas = i; LeaveCriticalSection(&ScanThread::critical); } else @@ -289,6 +306,10 @@ namespace ScreenshotInput { ScanThread::startsearchX = 0; ScanThread::PointX.x = 0; ScanThread::PointX.y = 0; + // if (Xprevious.x != X || Xprevious.y != Y) + // ScanThread::UpdateWindow = true; + // Xprevious.x = ScanThread::PointX.x; + // Xprevious.y = ScanThread::PointX.y; LeaveCriticalSection(&ScanThread::critical); } } @@ -308,6 +329,9 @@ namespace ScreenshotInput { ScanThread::staticPointY[i].y = Y; ScanThread::PointY.x = X; ScanThread::PointY.y = Y; + if (Ywas != i) + ScanThread::UpdateWindow = true; + Ywas = i; LeaveCriticalSection(&ScanThread::critical); } else @@ -332,6 +356,10 @@ namespace ScreenshotInput { //input = scanYtype; ScanThread::PointY.x = 0; ScanThread::PointY.y = 0; + // if (Yprevious.x != X || Yprevious.y != Y) + // ScanThread::UpdateWindow = true; + // Yprevious.x = ScanThread::PointY.x; + // Yprevious.y = ScanThread::PointY.y; LeaveCriticalSection(&ScanThread::critical); } } @@ -572,7 +600,7 @@ namespace ScreenshotInput { return true; } - bool SaveWindow10x10BMP(HWND hwnd, std::wstring filename, int x, int y) { + bool ScanThread::SaveWindow10x10BMP(HWND hwnd, std::wstring filename, int x, int y) { HDC hdcWindow = GetDC(hwnd); HDC hdcMem = CreateCompatibleDC(hdcWindow); @@ -794,6 +822,14 @@ namespace ScreenshotInput { bool ScanThread::enumeratebmps() { + ScanThread::numphotoA = 0; + ScanThread::startsearchA = 0; + ScanThread::numphotoB = 0; + ScanThread::startsearchB = 0; + ScanThread::numphotoX = 0; + ScanThread::startsearchX = 0; + ScanThread::numphotoY = 0; + ScanThread::startsearchY = 0; std::wstring path = WGetExecutableFolder() + L"\\A"; ScanThread::numphotoA = HowManyBmps(path, true); ScanThread::numphotoAbmps = HowManyBmps(path, false); @@ -827,9 +863,11 @@ namespace ScreenshotInput { POINT pt = { 0,0 }; POINT noeder = { 0,0 }; int numbmp = 0; - if (ModeScanThread != 2) - { + + // if (ModeScanThread != 2) + // { int numphoto = 0; + //MessageBoxA(NULL, "starting scan", "BMPs not found", MB_OK); if (checkarray == 1) { //always check static first? noeder = CheckStatics(key, startsearch); @@ -855,10 +893,13 @@ namespace ScreenshotInput { } } std::string path = UGetExecutableFolder() + key + std::to_string(i) + ".bmp"; + std::wstring wpath(path.begin(), path.end()); + // // HDC soke; if (LoadBMP24Bit(wpath.c_str(), smallPixels, smallW, smallH, strideSmall) && !found) { + // MessageBoxA(NULL, "loaded bmp.", "BMPs not found", MB_OK); if (CaptureWindow24Bit(hwndhandle, screenSize, largePixels, strideLarge, false, ScanThread::resize)) { if (onlysearch) @@ -921,7 +962,7 @@ namespace ScreenshotInput { if (found == true) return true; else return false; - } + // } // if (mode == 2 && MainThread::showmessage == 0 && onlysearch == false) //mode 2 button mapping //showmessage var to make sure no double map or map while message // { @@ -939,14 +980,15 @@ namespace ScreenshotInput { DWORD WINAPI ScanThreadMain(LPVOID, int Aisstatic, int Bisstatic, int Xisstatic, int Yisstatic) { + ScanThread::scanloop = true; int scantick = 0; Sleep(3000); Astatic = Aisstatic; Bstatic = Bisstatic; Xstatic = Xisstatic; Ystatic = Yisstatic; - //scanrunning = true; - ScanThread::scanloop = true; + // + while (ScanThread::scanloop) { EnterCriticalSection(&ScanThread::critical); @@ -963,7 +1005,7 @@ namespace ScreenshotInput { POINT PointXW = ScanThread::PointX; POINT PointYW = ScanThread::PointY; ModeScanThread = TranslateXtoMKB::mode; - showmessageScanThread = TranslateXtoMKB::showmessage; + //showmessageScanThread = TranslateXtoMKB::showmessage; hwndhandle = (HWND)Proto::HwndSelector::GetSelectedHwnd(); LeaveCriticalSection(&ScanThread::critical); @@ -972,6 +1014,7 @@ namespace ScreenshotInput { else scantick = 0; if (PreScanningEnabled) { + if (scantick == 0 && ScanThread::numphotoA > 0) { if (Astatic == 1) @@ -1057,11 +1100,6 @@ namespace ScreenshotInput { } LeaveCriticalSection(&ScanThread::critical); } - if (ModeScanThread == 2 && showmessageScanThread != 11) - { - ScanThread::numphotoA++; - Sleep(500); - } } if (buttonFlagg == 1) { @@ -1089,11 +1127,6 @@ namespace ScreenshotInput { } LeaveCriticalSection(&ScanThread::critical); } - if (ModeScanThread == 2 && showmessageScanThread != 11) - { - ScanThread::numphotoB++; - Sleep(500); - } } if (buttonFlagg == 2) { @@ -1123,11 +1156,6 @@ namespace ScreenshotInput { } LeaveCriticalSection(&ScanThread::critical); } - if (ModeScanThread == 2 && showmessageScanThread != 11) - { - ScanThread::numphotoX++; - Sleep(500); - } } if (buttonFlagg == 3) { @@ -1169,9 +1197,11 @@ namespace ScreenshotInput { EnterCriticalSection(&ScanThread::critical); returnedvalue = ButtonScanAction("\\C", ModeScanThread, ScanThread::numphotoC, ScanThread::startsearchC, false, { 0,0 }, false); //2 save bmps LeaveCriticalSection(&ScanThread::critical); + //MessageBoxA(NULL, "ooonei", "A", MB_OK); } else if (ScanThread::ShoulderNextBMP) { + //MessageBoxA(NULL, "heisann2", "A", MB_OK); EnterCriticalSection(&ScanThread::critical); if (ScanThread::startsearchA < ScanThread::numphotoA - 1) ScanThread::startsearchA++; //dont want it to update before input done @@ -1184,12 +1214,6 @@ namespace ScreenshotInput { else ScanThread::startsearchX = 0; LeaveCriticalSection(&ScanThread::critical); } - if (ModeScanThread == 2 && showmessageScanThread != 11) - { - ScanThread::numphotoC++; - Sleep(500); - } - } if (buttonFlagg == 5) //D { @@ -1217,12 +1241,6 @@ namespace ScreenshotInput { else ScanThread::startsearchY = ScanThread::numphotoY - 1; LeaveCriticalSection(&ScanThread::critical); } - //else MessageBoxA(NULL, "heisann2", "A", MB_OK); - if (ModeScanThread == 2 && showmessageScanThread != 11) - { - ScanThread::numphotoD++; - Sleep(500); - } } if (buttonFlagg == 6) //E @@ -1234,11 +1252,6 @@ namespace ScreenshotInput { returnedvalue = ButtonScanAction("\\E", ModeScanThread, ScanThread::numphotoD, ScanThread::startsearchD, false, { 0,0 }, false); //2 save bmps LeaveCriticalSection(&critical); } - if (ModeScanThread == 2 && showmessageScanThread != 11) - { - ScanThread::numphotoE++; - Sleep(500); - } } if (buttonFlagg == 7) //F { @@ -1249,11 +1262,6 @@ namespace ScreenshotInput { returnedvalue = ButtonScanAction("\\F", ModeScanThread, ScanThread::numphotoF, ScanThread::startsearchF, false, { 0,0 }, false); //2 save bmps LeaveCriticalSection(&critical); } - if (ModeScanThread == 2 && showmessageScanThread != 11) - { - ScanThread::numphotoF++; - Sleep(500); - } } return returnedvalue; diff --git a/src/ProtoInput/ProtoInputHooks/ScanThread.h b/src/ProtoInput/ProtoInputHooks/ScanThread.h index 8d92ac2..9803c74 100644 --- a/src/ProtoInput/ProtoInputHooks/ScanThread.h +++ b/src/ProtoInput/ProtoInputHooks/ScanThread.h @@ -10,20 +10,21 @@ namespace ScreenshotInput { static int scanAtype, scanBtype, scanXtype, scanYtype, Ctype, Dtype, Etype, Ftype; static int numphotoA, numphotoB, numphotoX, numphotoY, numphotoC, numphotoD, numphotoE, numphotoF; static int numphotoAbmps, numphotoBbmps, numphotoXbmps, numphotoYbmps; - + static bool UpdateWindow; static POINT PointA, PointB, PointX, PointY; static int startsearchA, startsearchB, startsearchX, startsearchY, startsearchC, startsearchD, startsearchE, startsearchF; static std::vector staticPointA, staticPointB, staticPointX, staticPointY; static bool scanloop; //tunell static int Aisstatic, Bisstatic, Xisstatic, Yisstatic; - static int scanoption; + static bool scanoption; static bool ShoulderNextBMP; static int resize; static int ignorerect; static void StartScanThread(HMODULE hmodule, int Astatic, int Bstatic, int Xstatic, int Ystatic, bool prescan); + static bool SaveWindow10x10BMP(HWND hwnd, std::wstring filename, int x, int y); static bool enumeratebmps(); //false if no bmps found static bool initovector(); static bool ButtonPressed(UINT buttonFlag); diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp index 029ae58..60e1fb8 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -44,6 +44,7 @@ namespace ScreenshotInput { int InstanceID = 0; //InstanceID copy from stateinfo.h + int TranslateXtoMKB::RefreshWindow; //from tunnell int TranslateXtoMKB::controllerID; bool TranslateXtoMKB::rawinputhook; //registerrawinputhook @@ -69,37 +70,39 @@ namespace ScreenshotInput int TranslateXtoMKB::startmapping; bool TranslateXtoMKB::lefthanded; int TranslateXtoMKB::mode = 1; + bool TranslateXtoMKB::SaveBmps; + int TranslateXtoMKB::Sens = 12; + int TranslateXtoMKB::Sensmult = 4; int updatewindowtick = 300; - - int AxisLeftsens = -15000; - int AxisRightsens = 15000; - int AxisUpsens = 15000; - int AxisDownsens = -15000; + + int AxisLeftsens = -9000; + int AxisRightsens = 9000; + int AxisUpsens = 9000; + int AxisDownsens = -9000; int scrollspeed3; float radial_deadzone = 0.10f; // Circular/Radial Deadzone (0.0 to 0.3) float axial_deadzone = 0.00f; // Square/Axial Deadzone (0.0 to 0.3) const float max_threshold = 0.03f; // Max Input Threshold, an "outer deadzone" (0.0 to 0.15) const float curve_slope = 0.16f; // The linear portion of the response curve (0.0 to 1.0) const float curve_exponent = 5.00f; // The exponential portion of the curve (1.0 to 10.0) - float sensitivity = 12.00f; // Base sensitivity / max speed (1.0 to 30.0) - float accel_multiplier = 1.90f; // Look Acceleration Multiplier (1.0 to 3.0) + //float sensitivity = 9.00f; // Base sensitivity / max speed (1.0 to 30.0) + //float accel_multiplier = 1.90f; // Look Acceleration Multiplier (1.0 to 3.0) ///////////////// - bool movedmouse; - bool leftPressedold = false; - bool rightPressedold = false; + + bool leftPressedold = false; + bool rightPressedold = false; HMODULE g_hModule = nullptr; bool loop = true; //CRITICAL_SECTION critical; //window thread - int TranslateXtoMKB::showmessage = 0; //0 = no message, 1 = initializing, 2 = bmp mode, 3 = bmp and cursor mode, 4 = edit mode - + //int TranslateXtoMKB::showmessage = 0; //0 = no message, 1 = initializing, 2 = bmp mode, 3 = bmp and cursor mode, 4 = edit mode + int counter = 0; - bool oldhome = false; //toggle lock input with home key + bool oldhome = false; //toggle lock input with home key //copy of criticals - int showmessageMT; int modeMT; POINT delta; @@ -116,10 +119,10 @@ namespace ScreenshotInput bool rawmouseWu = false; bool rawmouseWd = false; - bool oldA = false; - bool oldB = false; - bool oldX = false; - bool oldY = false; + bool oldA = false; + bool oldB = false; + bool oldX = false; + bool oldY = false; bool oldC = false; bool oldD = false; @@ -139,9 +142,40 @@ namespace ScreenshotInput bool oldscrollup = false; bool oldGUIkey = false; - // Add a fake key event to the array - USHORT lastVKkey = 0; + void StartScanner() { + ScanThread::numphotoA = 0; + ScanThread::numphotoB = 0; + ScanThread::numphotoX = 0; + ScanThread::numphotoY = 0; + // InitializeCriticalSection(&ScanThread::critical); + if (!ScanThread::enumeratebmps()) //false means no bmps found. also counts statics + { + // printf("BMPs enumerated but not found"); + if (ScanThread::scanoption) + { + ScanThread::scanoption = false; + // printf("Error. Nothing to scan for. Disabling scanoption"); + } + + } + else { + // printf("BMPs found"); + ScanThread::staticPointA.assign(ScanThread::numphotoA + 1, POINT{ 0, 0 }); + ScanThread::staticPointB.assign(ScanThread::numphotoB + 1, POINT{ 0, 0 }); + ScanThread::staticPointX.assign(ScanThread::numphotoX + 1, POINT{ 0, 0 }); + ScanThread::staticPointY.assign(ScanThread::numphotoY + 1, POINT{ 0, 0 }); + } + ScanThread::initovector(); + if (ScanThread::scanoption) + { //starting bmp continous scanner + ScanThread::StartScanThread(g_hModule, ScanThread::Aisstatic, ScanThread::Bisstatic, ScanThread::Xisstatic, ScanThread::Yisstatic, ScanThread::scanoption); + // printf("BMP scanner started"); + } + Sleep(20); //give time for ScanThread::scanloop toggle true + } + + USHORT lastVKkey = 0; bool IsKeyPressed(int Vkey) { return (GetAsyncKeyState(Vkey) & 0x8000) != 0; @@ -190,51 +224,94 @@ namespace ScreenshotInput } Proto::RawInput::SendInputMessages(muusjn); } + std::string UGetExeFolder() { + char path[MAX_PATH]; + GetModuleFileNameA(NULL, path, MAX_PATH); + + std::string exePath(path); - void ButtonStateImpulse(int vk, bool state) + size_t lastSlash = exePath.find_last_of("\\/"); + return exePath.substr(0, lastSlash); + } + void ButtonStateImpulse(int vk, bool state, int whocalled) + { + if (modeMT == 1) { RAWKEYBOARD data{}; data.MakeCode = MapVirtualKey(vk, MAPVK_VK_TO_VSC); data.VKey = vk; + // MessageBoxA(NULL, path.c_str(), "1", MB_OK); data.ExtraInformation = 0; - data.Flags = state ? 0 : RI_KEY_BREAK; data.Message = state ? WM_KEYDOWN : WM_KEYUP; - // Extended key? switch (vk) { - case VK_LEFT: - case VK_RIGHT: - case VK_UP: - case VK_DOWN: - case VK_INSERT: - case VK_DELETE: - case VK_HOME: - case VK_END: - case VK_PRIOR: - case VK_NEXT: - case VK_RCONTROL: - case VK_RMENU: - case VK_DIVIDE: - case VK_NUMLOCK: - data.Flags |= RI_KEY_E0; - break; + case VK_LEFT: + case VK_RIGHT: + case VK_UP: + case VK_DOWN: + case VK_INSERT: + case VK_DELETE: + case VK_HOME: + case VK_END: + case VK_PRIOR: + case VK_NEXT: + case VK_RCONTROL: + case VK_RMENU: + case VK_DIVIDE: + case VK_NUMLOCK: + data.Flags |= RI_KEY_E0; + break; } - Proto::FakeMouseKeyboard::ReceivedKeyPressOrRelease(vk, state); - Proto::RawInput::SendKeyMessage(data, state); - RawInput::GenerateRawKey(vk, state, false); - + Proto::FakeMouseKeyboard::ReceivedKeyPressOrRelease(vk, state); + Proto::RawInput::SendKeyMessage(data, state); + RawInput::GenerateRawKey(vk, state, false); + } + if (modeMT == 2) + { + if (Proto::FakeCursor::Showmessage == 0) + { + HWND hwndhere = (HWND)Proto::HwndSelector::GetSelectedHwnd(); + Proto::FakeMouseState muusjn = Proto::FakeMouseKeyboard::GetMouseState(); + int Xhold = muusjn.x; + int Yhold = muusjn.y; + std::string path; + if ( whocalled == 0) //A + { + path = UGetExeFolder() + "\\A" + std::to_string(ScanThread::numphotoA) + ".bmp"; + Proto::FakeCursor::Showmessage = 10; //signal is saving + ScanThread::numphotoA++; + } + if (whocalled == 1) //B + { + path = UGetExeFolder() + "\\B" + std::to_string(ScanThread::numphotoB) + ".bmp"; + Proto::FakeCursor::Showmessage = 11; //signal is saving + ScanThread::numphotoB++; + } + if (whocalled == 2) //X + { + path = UGetExeFolder() + "\\X" + std::to_string(ScanThread::numphotoX) + ".bmp"; + Proto::FakeCursor::Showmessage = 12; //signal is saving + ScanThread::numphotoX++; + } + if (whocalled == 3) //Y + { + path = UGetExeFolder() + "\\Y" + std::to_string(ScanThread::numphotoY) + ".bmp"; + Proto::FakeCursor::Showmessage = 13; //signal is saving + ScanThread::numphotoY++; + } + + std::wstring wpath(path.begin(), path.end()); + ScanThread::SaveWindow10x10BMP(hwndhere, wpath.c_str(), muusjn.x, muusjn.y); + // MessageBoxW(nullptr, wpath.c_str(), L"Path", MB_OK); + + TranslateXtoMKB::RefreshWindow ++; + counter = 0; + } + } } - std::string UGetExeFolder() { - char path[MAX_PATH]; - GetModuleFileNameA(NULL, path, MAX_PATH); - std::string exePath(path); - - size_t lastSlash = exePath.find_last_of("\\/"); - return exePath.substr(0, lastSlash); - } std::wstring WGetExeFolder() { @@ -328,547 +405,518 @@ namespace ScreenshotInput return { integerDeltaX, -integerDeltaY }; } - + std::wstring ToWString(const std::string& s) { return std::wstring(s.begin(), s.end()); } - bool readsettings() { - char buffer[64]; //or only 4 maybe - - // settings reporting - std::string iniPath = UGetExeFolder() + "\\Xinput.ini"; - std::string iniSettings = "Settings"; - GetPrivateProfileStringA(iniSettings.c_str(), "Axial_Deadzone", "0.0", buffer, sizeof(buffer), iniPath.c_str()); - axial_deadzone = std::stof(buffer); //sensitivity - - GetPrivateProfileStringA(iniSettings.c_str(), "Sensitivity", "12.0", buffer, sizeof(buffer), iniPath.c_str()); - sensitivity = std::stof(buffer); //sensitivity //accel_multiplier - - GetPrivateProfileStringA(iniSettings.c_str(), "Accel_Multiplier", "2.5", buffer, sizeof(buffer), iniPath.c_str()); - accel_multiplier = std::stof(buffer); - - return true; - } - void ThreadFunction(HMODULE hModule) + void TranslateXtoMKB::ThreadFunction() { - - Proto::AddThreadToACL(GetCurrentThreadId()); - Sleep(2000); - if (readsettings() == false) + if (ScanThread::scanoption && ScanThread::scanloop == false) { - //messagebox? settings not read + MessageBoxA(NULL, "Starting BMP scanner...", "Info", MB_OK); + StartScanner(); } - - // InitializeCriticalSection(&ScanThread::critical); - if (!ScanThread::enumeratebmps()) //false means no bmps found. also counts statics + float sensitivity = static_cast(TranslateXtoMKB::Sens); + float accel_multiplier = static_cast(TranslateXtoMKB::Sensmult) / 2.0f; + + EnterCriticalSection(&ScanThread::critical); + if (ScanThread::UpdateWindow) + TranslateXtoMKB::RefreshWindow = 1; + LeaveCriticalSection(&ScanThread::critical); + modeMT = 1; + if (TranslateXtoMKB::SaveBmps) { + modeMT = 2; + } + + //GUI + if (oldGUIkey) { - // printf("BMPs enumerated but not found"); - if (ScanThread::scanoption == 1) + if (IsKeyPressed(VK_RCONTROL) && IsKeyPressed(VK_RMENU) && IsKeyPressed(0x30 + InstanceID)) { - ScanThread::scanoption = 0; - // printf("Error. Nothing to scan for. Disabling scanoption"); + } + else + { + oldGUIkey = false; + ButtonStateImpulse(VK_HOME, false, 99);//down} } } - else { - // printf("BMPs found"); - ScanThread::staticPointA.assign(ScanThread::numphotoA + 1, POINT{ 0, 0 }); - ScanThread::staticPointB.assign(ScanThread::numphotoB + 1, POINT{ 0, 0 }); - ScanThread::staticPointX.assign(ScanThread::numphotoX + 1, POINT{ 0, 0 }); - ScanThread::staticPointY.assign(ScanThread::numphotoY + 1, POINT{ 0, 0 }); - } - ScanThread::initovector(); - if (ScanThread::scanoption == 1) - { //starting bmp continous scanner - ScanThread::StartScanThread(g_hModule, ScanThread::Aisstatic, ScanThread::Bisstatic, ScanThread::Xisstatic, ScanThread::Yisstatic, ScanThread::scanoption); - // printf("BMP scanner started"); + else if (IsKeyPressed(VK_RCONTROL) && IsKeyPressed(VK_RMENU) && IsKeyPressed(0x30 + InstanceID))//gui or fake cursor toggle + { + Proto::ToggleWindow(); + oldGUIkey = true; + Proto::FakeCursor::Showmessage = 2; + TranslateXtoMKB::RefreshWindow = 1; + tick = 0; + if (TranslateXtoMKB::mode == 1) //modechange + { + TranslateXtoMKB::mode = 2; + } + else TranslateXtoMKB::mode = 1; } - while (loop == true) + XINPUT_STATE state; + ZeroMemory(&state, sizeof(XINPUT_STATE)); + // Check controller 0 + DWORD dwResult = OpenXInputGetState(TranslateXtoMKB::controllerID, &state); + if (dwResult == ERROR_SUCCESS) { - //if render. sleep while rendering instead of at the end - bool alreadyslept = false; - //copy criticals - EnterCriticalSection(&ScanThread::critical); - showmessageMT = TranslateXtoMKB::showmessage; - modeMT = TranslateXtoMKB::mode; - LeaveCriticalSection(&ScanThread::critical); - - //GUI - if (oldGUIkey) + WORD buttons = state.Gamepad.wButtons; + if (Proto::FakeCursor::Showmessage == 1) + {//remove disconnected message + Proto::FakeCursor::Showmessage = 0; + TranslateXtoMKB::RefreshWindow = 1; + } + if (modeMT > 0) { - if (IsKeyPressed(VK_RCONTROL) && IsKeyPressed(VK_RMENU) && IsKeyPressed(0x30 + InstanceID)) - { + //fake cursor poll + int Xaxis = 0; + int Yaxis = 0; + int scrollXaxis = 0; + int scrollYaxis = 0; + int Yscroll = 0; + int Xscroll = 0; + bool leftPressed = IsTriggerPressed(state.Gamepad.bLeftTrigger); + bool rightPressed = IsTriggerPressed(state.Gamepad.bRightTrigger); + + if (TranslateXtoMKB::lefthanded == 1) { + Xaxis = state.Gamepad.sThumbRX; + Yaxis = state.Gamepad.sThumbRY; + scrollXaxis = state.Gamepad.sThumbLX; + scrollYaxis = state.Gamepad.sThumbLY; } else { - oldGUIkey = false; - ButtonStateImpulse(VK_HOME, false);//down} + Xaxis = state.Gamepad.sThumbLX; + Yaxis = state.Gamepad.sThumbLY; + scrollXaxis = state.Gamepad.sThumbRX; + scrollYaxis = state.Gamepad.sThumbRY; } - } - else if (IsKeyPressed(VK_RCONTROL) && IsKeyPressed(VK_RMENU) && IsKeyPressed(0x30 + InstanceID))//gui or fake cursor toggle - { - Proto::ToggleWindow(); - oldGUIkey = true; - } - - movedmouse = false; //reset - XINPUT_STATE state; - ZeroMemory(&state, sizeof(XINPUT_STATE)); - // Check controller 0 - DWORD dwResult = OpenXInputGetState(TranslateXtoMKB::controllerID, &state); - if (dwResult == ERROR_SUCCESS) - { - WORD buttons = state.Gamepad.wButtons; - - if (modeMT > 0) - { - //fake cursor poll - int Xaxis = 0; - int Yaxis = 0; - int scrollXaxis = 0; - int scrollYaxis = 0; - int Yscroll = 0; - int Xscroll = 0; - bool leftPressed = IsTriggerPressed(state.Gamepad.bLeftTrigger); - bool rightPressed = IsTriggerPressed(state.Gamepad.bRightTrigger); - - if (TranslateXtoMKB::lefthanded == 1) { - Xaxis = state.Gamepad.sThumbRX; - Yaxis = state.Gamepad.sThumbRY; - scrollXaxis = state.Gamepad.sThumbLX; - scrollYaxis = state.Gamepad.sThumbLY; - } - else - { - Xaxis = state.Gamepad.sThumbLX; - Yaxis = state.Gamepad.sThumbLY; - scrollXaxis = state.Gamepad.sThumbRX; - scrollYaxis = state.Gamepad.sThumbRY; - } - - delta = CalculateUltimateCursorMove( - Xaxis, Yaxis, - radial_deadzone, axial_deadzone, max_threshold, - curve_slope, curve_exponent, - sensitivity, accel_multiplier - ); - if (delta.x != 0 || delta.y != 0) { - Xf += delta.x; - Yf += delta.y; - movedmouse = true; - } - if (movedmouse == true) //fake cursor move message - { - TranslateXtoMKB::SendMouseClick(delta.x, delta.y, 8); - - Proto::FakeCursor::NotifyUpdatedCursorPosition(); - } + delta = CalculateUltimateCursorMove( + Xaxis, Yaxis, + radial_deadzone, axial_deadzone, max_threshold, + curve_slope, curve_exponent, + sensitivity, accel_multiplier + ); + if (delta.x != 0 || delta.y != 0) { + Xf += delta.x; + Yf += delta.y; + TranslateXtoMKB::RefreshWindow = 1; + TranslateXtoMKB::SendMouseClick(delta.x, delta.y, 8); + } - if (leftPressedold) + if (leftPressedold) + { + if (!leftPressed) { - if (!leftPressed) - { - TranslateXtoMKB::SendMouseClick(Xf, Yf, 6); //double click - leftPressedold = false; - } + TranslateXtoMKB::SendMouseClick(Xf, Yf, 6); //double click + leftPressedold = false; } - else if (leftPressed) + } + else if (leftPressed) + { + if (leftPressedold == false) { - if (leftPressedold == false) - { - TranslateXtoMKB::SendMouseClick(Xf, Yf, 5); //4 skal vere 3 - leftPressedold = true; - } + TranslateXtoMKB::SendMouseClick(Xf, Yf, 5); //4 skal vere 3 + leftPressedold = true; } + } - if (rightPressedold) + if (rightPressedold) + { + if (!rightPressed) { - if (!rightPressed) - { - TranslateXtoMKB::SendMouseClick(Xf, Yf, 4); - rightPressedold = false; - } - } //if rightpress - else if (rightPressed) + TranslateXtoMKB::SendMouseClick(Xf, Yf, 4); + rightPressedold = false; + } + } //if rightpress + else if (rightPressed) + { + if (rightPressedold == false) { - if (rightPressedold == false) - { - TranslateXtoMKB::SendMouseClick(Xf, Yf, 3); - rightPressedold = true; + TranslateXtoMKB::SendMouseClick(Xf, Yf, 3); + rightPressedold = true; - } } + } - //buttons - if (oldscrollleft) - { - if (scrollXaxis < AxisLeftsens) //left - { - } - else { - oldscrollleft = false; - ButtonStateImpulse(TranslateXtoMKB::stickrightmapping, false);//down - } - } - else if (scrollXaxis < AxisLeftsens) //left + //buttons + if (oldscrollleft) + { + if (scrollXaxis < AxisLeftsens) //left { - oldscrollleft = true; - - ButtonStateImpulse(TranslateXtoMKB::stickrightmapping, true);//down } + else { + oldscrollleft = false; + ButtonStateImpulse(TranslateXtoMKB::stickrightmapping, false, 99);//down + } + } + else if (scrollXaxis < AxisLeftsens) //left + { + oldscrollleft = true; - if (oldscrollright) - { - if (scrollXaxis > AxisRightsens) //left - { - } - else { - oldscrollright = false; - ButtonStateImpulse(TranslateXtoMKB::stickleftmapping, false);//down - } - } - else if (scrollXaxis > AxisRightsens) //left + ButtonStateImpulse(TranslateXtoMKB::stickrightmapping, true, 99);//down + } + + if (oldscrollright) + { + if (scrollXaxis > AxisRightsens) //left { - oldscrollright = true; - ButtonStateImpulse(TranslateXtoMKB::stickleftmapping, true);//down } + else { + oldscrollright = false; + ButtonStateImpulse(TranslateXtoMKB::stickleftmapping, false, 99);//down + } + } + else if (scrollXaxis > AxisRightsens) //left + { + oldscrollright = true; + ButtonStateImpulse(TranslateXtoMKB::stickleftmapping, true, 99);//down + } - if (oldscrollup) - { - if (scrollYaxis > AxisUpsens) //left - { - } - else { - oldscrollup = false; - ButtonStateImpulse(TranslateXtoMKB::stickupmapping, false);//down - } - } - else if (scrollYaxis > AxisUpsens) //left + if (oldscrollup) + { + if (scrollYaxis > AxisUpsens) //left { - oldscrollup = true; - ButtonStateImpulse(TranslateXtoMKB::stickupmapping, true);//down } + else { + oldscrollup = false; + ButtonStateImpulse(TranslateXtoMKB::stickupmapping, false, 99);//down + } + } + else if (scrollYaxis > AxisUpsens) //left + { + oldscrollup = true; + ButtonStateImpulse(TranslateXtoMKB::stickupmapping, true, 99);//down + } - if (oldscrolldown) - { - if (scrollYaxis < AxisDownsens) //left - { - } - else { - oldscrolldown = false; - ButtonStateImpulse(TranslateXtoMKB::stickdownmapping, false);//down - } - } - else if (scrollYaxis < AxisDownsens) //left + if (oldscrolldown) + { + if (scrollYaxis < AxisDownsens) //left { - oldscrolldown = true; - ButtonStateImpulse(TranslateXtoMKB::stickdownmapping, true);//down } + else { + oldscrolldown = false; + ButtonStateImpulse(TranslateXtoMKB::stickdownmapping, false, 99);//down + } + } + else if (scrollYaxis < AxisDownsens) //left + { + oldscrolldown = true; + ButtonStateImpulse(TranslateXtoMKB::stickdownmapping, true, 99);//down + } - if (oldA) + if (oldA) + { + if (buttons & XINPUT_GAMEPAD_A) { - if (buttons & XINPUT_GAMEPAD_A) - { - } - else{ - oldA = false; + } + else { + oldA = false; - ButtonStateImpulse(TranslateXtoMKB::Amapping, false);//release - } + ButtonStateImpulse(TranslateXtoMKB::Amapping, false, 0);//release } - else if (buttons & XINPUT_GAMEPAD_A) + + } + else if (buttons & XINPUT_GAMEPAD_A) + { + oldA = true; + if (ScanThread::scanoption) { - oldA = true; - if (ScanThread::scanoption == 1) - { bool found = ScanThread::ButtonPressed(0); if (!found) - ButtonStateImpulse(TranslateXtoMKB::Amapping, true);//down - } - else ButtonStateImpulse(TranslateXtoMKB::Amapping, true); + ButtonStateImpulse(TranslateXtoMKB::Amapping, true, 0);//down } + else ButtonStateImpulse(TranslateXtoMKB::Amapping, true, 0); + TranslateXtoMKB::RefreshWindow = 2; + } - if (oldB) + if (oldB) + { + if (buttons & XINPUT_GAMEPAD_B) { - if (buttons & XINPUT_GAMEPAD_B) - { - } - else { - oldB = false; - ButtonStateImpulse(TranslateXtoMKB::Bmapping, false);//release - } - } - else if (buttons & XINPUT_GAMEPAD_B) + } + else { + oldB = false; + ButtonStateImpulse(TranslateXtoMKB::Bmapping, false,1);//release + } + } + else if (buttons & XINPUT_GAMEPAD_B) + { + oldB = true; + if (ScanThread::scanoption && modeMT != 2) { - oldB = true; - if (ScanThread::scanoption == 1) - { - bool found = ScanThread::ButtonPressed(1); - if (!found) - ButtonStateImpulse(TranslateXtoMKB::Bmapping, true);//down - } - else ButtonStateImpulse(TranslateXtoMKB::Bmapping, true);//down + bool found = ScanThread::ButtonPressed(1); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::Bmapping, true, 1);//down } + else ButtonStateImpulse(TranslateXtoMKB::Bmapping, true, 1);//down + TranslateXtoMKB::RefreshWindow = 2; + } - if (oldX) + if (oldX) + { + if (buttons & XINPUT_GAMEPAD_X) { - if (buttons & XINPUT_GAMEPAD_X) - { - } - else { - oldX = false; - ButtonStateImpulse(TranslateXtoMKB::Xmapping, false);//release - } - } - else if (buttons & XINPUT_GAMEPAD_X) + } + else { + oldX = false; + ButtonStateImpulse(TranslateXtoMKB::Xmapping, false, 2);//release + } + } + else if (buttons & XINPUT_GAMEPAD_X) + { + oldX = true; + if (ScanThread::scanoption && modeMT != 2) { - oldX = true; - if (ScanThread::scanoption == 1) - { - bool found = ScanThread::ButtonPressed(2); - if (!found) - ButtonStateImpulse(TranslateXtoMKB::Xmapping, true);//down - } - else ButtonStateImpulse(TranslateXtoMKB::Xmapping, true);//down + bool found = ScanThread::ButtonPressed(2); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::Xmapping, true, 2);//down } + else ButtonStateImpulse(TranslateXtoMKB::Xmapping, true, 2);//down + TranslateXtoMKB::RefreshWindow = 2; + } - if (oldY) + if (oldY) + { + if (buttons & XINPUT_GAMEPAD_Y) { - if (buttons & XINPUT_GAMEPAD_Y) - { - } - else { - oldY = false; - ButtonStateImpulse(TranslateXtoMKB::Ymapping, false);//release - } - } - else if (buttons & XINPUT_GAMEPAD_Y) + } + else { + oldY = false; + ButtonStateImpulse(TranslateXtoMKB::Ymapping, false, 3);//release + } + } + else if (buttons & XINPUT_GAMEPAD_Y) + { + oldY = true; + if (ScanThread::scanoption && modeMT != 2) { - oldY = true; - if (ScanThread::scanoption == 1) - { - bool found = ScanThread::ButtonPressed(3); - if (!found) - ButtonStateImpulse(TranslateXtoMKB::Ymapping, true);//down - } - else ButtonStateImpulse(TranslateXtoMKB::Ymapping, true);//down + bool found = ScanThread::ButtonPressed(3); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::Ymapping, true, 3);//down } + else ButtonStateImpulse(TranslateXtoMKB::Ymapping, true, 3);//down + TranslateXtoMKB::RefreshWindow = 2; + } - if (oldC) + if (oldC) + { + if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) { - if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) - { - } - else { - oldC = false; - ButtonStateImpulse(TranslateXtoMKB::RSmapping, false); //release - } - } - else if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) + } + else { + oldC = false; + ButtonStateImpulse(TranslateXtoMKB::RSmapping, false, 99); //release + } + } + else if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) + { + oldC = true; + if (ScanThread::scanoption) { - oldC = true; - if (ScanThread::scanoption == 1) - { - bool found = ScanThread::ButtonPressed(4); - if (!found) - ButtonStateImpulse(TranslateXtoMKB::RSmapping, true); //down - } - else ButtonStateImpulse(TranslateXtoMKB::RSmapping, true); //down + bool found = ScanThread::ButtonPressed(4); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::RSmapping, true, 99); //down } + else ButtonStateImpulse(TranslateXtoMKB::RSmapping, true, 99); //down + TranslateXtoMKB::RefreshWindow = 10; + } - if (oldD) + if (oldD) + { + if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) { - if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) - { - } - else { - oldD = false; - ButtonStateImpulse(TranslateXtoMKB::LSmapping, false);//release - } - } - else if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) + } + else { + oldD = false; + ButtonStateImpulse(TranslateXtoMKB::LSmapping, false, 99);//release + } + } + else if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) + { + oldD = true; + if (ScanThread::scanoption) { - oldD = true; - if (ScanThread::scanoption == 1) - { - bool found = ScanThread::ButtonPressed(5); - if (!found) - ButtonStateImpulse(TranslateXtoMKB::LSmapping, true);//down - } - else ButtonStateImpulse(TranslateXtoMKB::LSmapping, true);//down + bool found = ScanThread::ButtonPressed(5); + if (!found) + ButtonStateImpulse(TranslateXtoMKB::LSmapping, true, 99);//down } + else ButtonStateImpulse(TranslateXtoMKB::LSmapping, true, 99);//down + TranslateXtoMKB::RefreshWindow = 10; + } - if (oldleft) - { - if (buttons & XINPUT_GAMEPAD_DPAD_LEFT) - { - } - else { - oldleft = false; - ButtonStateImpulse(TranslateXtoMKB::leftmapping, false); //release - } - } - else if (buttons & XINPUT_GAMEPAD_DPAD_LEFT) + if (oldleft) + { + if (buttons & XINPUT_GAMEPAD_DPAD_LEFT) { - oldleft = true; - ButtonStateImpulse(TranslateXtoMKB::leftmapping, true);//down } + else { + oldleft = false; + ButtonStateImpulse(TranslateXtoMKB::leftmapping, false, 99); //release + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_LEFT) + { + oldleft = true; + ButtonStateImpulse(TranslateXtoMKB::leftmapping, true, 99);//down + } - if (oldright) - { - if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) - { - } - else { - oldright = false; - ButtonStateImpulse(TranslateXtoMKB::rightmapping, false);//release - } - } - else if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) + if (oldright) + { + if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) { - oldright = true; - ButtonStateImpulse(TranslateXtoMKB::rightmapping, true);//down } + else { + oldright = false; + ButtonStateImpulse(TranslateXtoMKB::rightmapping, false, 99);//release + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) + { + oldright = true; + ButtonStateImpulse(TranslateXtoMKB::rightmapping, true, 99);//down + } - if (oldup) - { - if (buttons & XINPUT_GAMEPAD_DPAD_UP) - { - } - else { - oldup = false; - ButtonStateImpulse(TranslateXtoMKB::upmapping, false);//release - } - } - else if (buttons & XINPUT_GAMEPAD_DPAD_UP) + if (oldup) + { + if (buttons & XINPUT_GAMEPAD_DPAD_UP) { - oldup = true; - ButtonStateImpulse(TranslateXtoMKB::upmapping, true);//down } + else { + oldup = false; + ButtonStateImpulse(TranslateXtoMKB::upmapping, false, 99);//release + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_UP) + { + oldup = true; + ButtonStateImpulse(TranslateXtoMKB::upmapping, true, 99);//down + } - if (olddown) - { - if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) - { - } - else { - olddown = false; - ButtonStateImpulse(TranslateXtoMKB::downmapping, false);//release - } - } - else if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) + if (olddown) + { + if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) { - olddown = true; - ButtonStateImpulse(TranslateXtoMKB::downmapping, true);//down } + else { + olddown = false; + ButtonStateImpulse(TranslateXtoMKB::downmapping, false, 99);//release + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) + { + olddown = true; + ButtonStateImpulse(TranslateXtoMKB::downmapping, true, 99);//down + } - if (oldstartoptions) //toggle fake cursor - { - if (oldstart && oldoptions) - { - } - else - { - oldstartoptions = false; - } - } - else if (oldstart && oldoptions)//fake cursor toggle + if (oldstartoptions) //toggle fake cursor + { + if (oldstart && oldoptions) { - Proto::FakeCursor::SetCursorVisibility(!Proto::FakeCursor::GetCursorVisibility()); - oldstartoptions = true; } - if (oldstart) + else { - if (buttons & XINPUT_GAMEPAD_START) - { - } - else { - oldstart = false; - ButtonStateImpulse(TranslateXtoMKB::startmapping, false);//release - } - } - else if (buttons & XINPUT_GAMEPAD_START) + oldstartoptions = false; + } + } + else if (oldstart && oldoptions)//fake cursor toggle + { + Proto::FakeCursor::SetCursorVisibility(!Proto::FakeCursor::GetCursorVisibility()); + Proto::FakeCursor::Showmessage = 3; + TranslateXtoMKB::RefreshWindow = 1;; + tick = 0; + oldstartoptions = true; + } + if (oldstart) + { + if (buttons & XINPUT_GAMEPAD_START) { - oldstart = true; - ButtonStateImpulse(TranslateXtoMKB::startmapping, true);//down } + else { + oldstart = false; + ButtonStateImpulse(TranslateXtoMKB::startmapping, false, 99);//release + } + } + else if (buttons & XINPUT_GAMEPAD_START) + { + oldstart = true; + ButtonStateImpulse(TranslateXtoMKB::startmapping, true, 99);//down + } - if (oldoptions) - { - if (buttons & XINPUT_GAMEPAD_BACK) - { - } - else { - oldoptions = false; - ButtonStateImpulse(TranslateXtoMKB::optionmapping, false);//release - } - } - else if (buttons & XINPUT_GAMEPAD_BACK) + if (oldoptions) + { + if (buttons & XINPUT_GAMEPAD_BACK) { - oldoptions = true; - ButtonStateImpulse(TranslateXtoMKB::optionmapping, true);//down } + else { + oldoptions = false; + ButtonStateImpulse(TranslateXtoMKB::optionmapping, false, 99);//release + } + } + else if (buttons & XINPUT_GAMEPAD_BACK) + { + oldoptions = true; + ButtonStateImpulse(TranslateXtoMKB::optionmapping, true, 99);//down + } - } //if mode above 0 - } //if controller - else { //no controller - showmessageMT = 12; - EnterCriticalSection(&ScanThread::critical); - TranslateXtoMKB::showmessage = 12; - LeaveCriticalSection(&ScanThread::critical); + } //if mode above 0 + } //if controller + else { //no controller + Proto::FakeCursor::Showmessage = 1; + TranslateXtoMKB::RefreshWindow = 1; + tick = 0; + } + if (tick < updatewindowtick) + tick++; + else { //need to update hwnd and bounds periodically + // EnterCriticalSection(&ScanThread::critical); + Proto::HwndSelector::UpdateMainHwnd(false); + Proto::HwndSelector::UpdateWindowBounds(); + tick = 0; + } + + if (Proto::FakeCursor::Showmessage != 0) { //drawing messages or something + if (counter < 500) { + counter++; } - if (tick < updatewindowtick) - tick++; - else { //need to update hwnd and bounds periodically - // EnterCriticalSection(&ScanThread::critical); - Proto::HwndSelector::UpdateMainHwnd(false); - Proto::HwndSelector::UpdateWindowBounds(); - // LeaveCriticalSection(&ScanThread::critical); - tick = 0; + else { + Proto::FakeCursor::Showmessage = 0; + TranslateXtoMKB::RefreshWindow = 1; + counter = 0; } + } + if (!ScanThread::scanoption) + { + // Proto::FakeCursor::Showmessage = TranslateXtoMKB::showmessage; + } + if (modeMT > 0) { + Sleep(1); + } + else Sleep(10); - EnterCriticalSection(&ScanThread::critical); - if (showmessageMT != 0) { //drawing messages or something - if (counter < 400) { //showmessage is critical - counter++; - } - else { - showmessageMT = 0; - TranslateXtoMKB::showmessage = 0; - counter = 0; - } - } - LeaveCriticalSection(&ScanThread::critical); - if (modeMT > 0) { - Sleep(1); - } - else Sleep(1); - if (showmessageMT == 99) - Sleep(1); - } //loop end but endless return; } void TranslateXtoMKB::Initialize(HMODULE hModule) { - RawInput::Initialize(); - g_hModule = hModule; - InstanceID = Proto::StateInfo::info.instanceIndex; - std::thread one(ThreadFunction, g_hModule); - one.detach(); - return; - } + RawInput::Initialize(); + g_hModule = hModule; + InstanceID = Proto::StateInfo::info.instanceIndex; + Proto::AddThreadToACL(GetCurrentThreadId()); + Sleep(50); + return; + } } \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h index fbc94a0..cf7ddd8 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h @@ -12,11 +12,13 @@ namespace ScreenshotInput public: static void Initialize(HMODULE g_hModule); + static void ThreadFunction(); //polling from idle drawfakecursor thread static void SendMouseClick(int x, int y, int z); + static int RefreshWindow; static int controllerID; static bool rawinputhook; static bool registerrawinputhook; - static int showmessage; + //static int showmessage; static int mode; static int Amapping; static int Bmapping; @@ -37,6 +39,9 @@ namespace ScreenshotInput static int optionmapping; static int startmapping; static bool lefthanded; + static int Sens; + static int Sensmult; + static bool SaveBmps; }; } \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/dllmain.cpp b/src/ProtoInput/ProtoInputHooks/dllmain.cpp index 07170fe..5b599e0 100644 --- a/src/ProtoInput/ProtoInputHooks/dllmain.cpp +++ b/src/ProtoInput/ProtoInputHooks/dllmain.cpp @@ -56,10 +56,8 @@ DWORD WINAPI StartThread(LPVOID lpParameter) Proto::FocusMessageLoop::SetupThread(); - Proto::FakeCursor::Initialise(); + Proto::FakeCursor::Initialise(dll_hModule); - if (Proto::RawInput::TranslateXinputtoMKB) - ScreenshotInput::TranslateXtoMKB::Initialize(dll_hModule); InitializeCriticalSection(&ScreenshotInput::ScanThread::critical); @@ -67,7 +65,7 @@ DWORD WINAPI StartThread(LPVOID lpParameter) (LPTHREAD_START_ROUTINE)GuiThread, dll_hModule, CREATE_SUSPENDED, &Proto::GuiThreadID); ResumeThread(hGuiThread); - + if (hGuiThread != nullptr) CloseHandle(hGuiThread); diff --git a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h index 291b0fd..d6cdf2f 100644 --- a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h +++ b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h @@ -286,6 +286,8 @@ struct PipeMessageSetXinputtoMKBkeys int XinputtoMKBstickdown; int XinputtoMKBoption; int XinputtoMKBstart; + int XinputtoMKBsens; + int XinputtoMKBsensmult; }; struct PipeMessageSetXinputtoMKBCFG { @@ -293,8 +295,16 @@ struct PipeMessageSetXinputtoMKBCFG bool scanoption; bool shoulderswap; bool astsatic; + bool aclick; + bool amove; bool bstsatic; + bool bclick; + bool bmove; bool xstsatic; + bool xclick; + bool xmove; bool ystsatic; + bool yclick; + bool ymove; }; } \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHost/Gui.cpp b/src/ProtoInput/ProtoInputHost/Gui.cpp index 4490a77..53fca71 100644 --- a/src/ProtoInput/ProtoInputHost/Gui.cpp +++ b/src/ProtoInput/ProtoInputHost/Gui.cpp @@ -261,8 +261,8 @@ bool Launch() //Xinput translate settings SetXinputtoMKBkeys(instanceHandle, currentProfile.XinputtoMKBAkey, currentProfile.XinputtoMKBBkey, currentProfile.XinputtoMKBXkey, currentProfile.XinputtoMKBYkey, currentProfile.XinputtoMKBRSkey, currentProfile.XinputtoMKBLSkey, currentProfile.XinputtoMKBrightkey, currentProfile.XinputtoMKBleftkey, currentProfile.XinputtoMKBupkey, currentProfile.XinputtoMKBdownkey, currentProfile.XinputtoMKBstickR, currentProfile.XinputtoMKBstickL, currentProfile.XinputtoMKBstickright, currentProfile.XinputtoMKBstickleft, currentProfile.XinputtoMKBstickup, currentProfile.XinputtoMKBstickdown, - currentProfile.XinputtoMKBoption, currentProfile.XinputtoMKBstart, currentProfile.XinputtoMKBstickinvert); - SetXinputtoMKBCFG(instanceHandle, currentProfile.XinputtoMKBstickinvert, currentProfile.ScanOption, currentProfile.Shoulderswappoints, currentProfile.XAstatic, currentProfile.XBstatic, currentProfile.XXstatic, currentProfile.XYstatic); + currentProfile.XinputtoMKBoption, currentProfile.XinputtoMKBstart, currentProfile.XinputtoMKBsens, currentProfile.XinputtoMKBsensmult); + SetXinputtoMKBCFG(instanceHandle, currentProfile.XinputtoMKBstickinvert, currentProfile.ScanOption, currentProfile.Shoulderswappoints, currentProfile.XAstatic, currentProfile.XAclick, currentProfile.XAmove, currentProfile.XBstatic, currentProfile.XBclick, currentProfile.XBmove, currentProfile.XXstatic, currentProfile.XXclick, currentProfile.XXmove, currentProfile.XYstatic, currentProfile.XYclick, currentProfile.XYmove); if (!instance.runtime) WakeUpProcess(instanceHandle); @@ -732,8 +732,8 @@ void SelectedInstanceWindow() ImGui::Checkbox("Translate X to MKB", ¤tProfile.TranslateXinputtoMKB); // ImGui::Separator(); ImGui::Spacing(); - ImGui::TextWrapped("Scanoption Will prescan and render coordinates if any BMPs or static points are loaded" - ""); + ImGui::TextWrapped("Scanoption Will prescan and render coordinates if any BMPs or static points are loaded." + "Place .BMP files next to exe. named A0 for A button and +1 for each bmp"); ImGui::Checkbox("Scanoption", ¤tProfile.ScanOption); // ImGui::Separator(); ImGui::Spacing(); @@ -751,6 +751,20 @@ void SelectedInstanceWindow() ImGui::Checkbox("X static", ¤tProfile.XXstatic); // ImGui::Checkbox("Y static", ¤tProfile.XYstatic); // ImGui::Separator(); + ImGui::Spacing(); + ImGui::TextWrapped("Input Actions on coordinate" + ""); + + ImGui::Spacing(); + ImGui::Checkbox("A click", ¤tProfile.XAclick); // + ImGui::Checkbox("A move", ¤tProfile.XAmove); // + ImGui::Checkbox("B click", ¤tProfile.XBclick); // + ImGui::Checkbox("B move", ¤tProfile.XBmove); // + ImGui::Checkbox("X click", ¤tProfile.XXclick); // + ImGui::Checkbox("X move", ¤tProfile.XXmove); // + ImGui::Checkbox("Y click", ¤tProfile.XYclick); // + ImGui::Checkbox("Y move", ¤tProfile.XYmove); // + ImGui::Separator(); ImGui::TextWrapped("Mappings:" ""); // A key @@ -1223,9 +1237,26 @@ void SelectedInstanceWindow() ImGui::Separator(); ImGui::Checkbox("Lefthanded Stick. moves mouse with left stick and button map on right stick. or opposite if disabled", ¤tProfile.XinputtoMKBstickinvert); // ImGui::Separator(); + ImGui::SliderInt("XtoMKB Sensitivity", (int*)¤tProfile.XinputtoMKBsens, 1, 40, "%d", ImGuiSliderFlags_AlwaysClamp); ImGui::Separator(); + ImGui::SliderInt("XtoMKB Sensitivity multiplier", (int*)¤tProfile.XinputtoMKBsensmult, 1, 20, "%d", ImGuiSliderFlags_AlwaysClamp); ImGui::PopID(); + bool stickinvert; + bool scanoption; + bool shoulderswap; + bool astsatic; + bool aclick; + bool amove; + bool bstsatic; + bool bclick; + bool bmove; + bool xstsatic; + bool xclick; + bool xmove; + bool ystsatic; + bool yclick; + bool ymove; } void OptionsMenu() diff --git a/src/ProtoInput/ProtoInputHost/Profiles.h b/src/ProtoInput/ProtoInputHost/Profiles.h index d2b0ba3..fa91ea3 100644 --- a/src/ProtoInput/ProtoInputHost/Profiles.h +++ b/src/ProtoInput/ProtoInputHost/Profiles.h @@ -79,9 +79,17 @@ struct Profile bool ScanOption = false; bool Shoulderswappoints = false; bool XAstatic = false; + bool XAclick = true; + bool XAmove = true; bool XBstatic = false; + bool XBclick = true; + bool XBmove = true; bool XXstatic = false; + bool XXclick = true; + bool XXmove = true; bool XYstatic = false; + bool XYclick = true; + bool XYmove = true; int XinputtoMKBAkey = 0x52; //R int XinputtoMKBBkey = 0x47; //G int XinputtoMKBXkey = 0x45; //E @@ -100,6 +108,8 @@ struct Profile int XinputtoMKBstickdown = 0x53; //S int XinputtoMKBoption = 0x1B; // int XinputtoMKBstart = 0x0D; + int XinputtoMKBsens = 15; + int XinputtoMKBsensmult = 4; bool useFakeClipCursor = true; @@ -144,6 +154,47 @@ struct Profile cereal::make_nvp("dinputToXinputRedirection", dinputToXinputRedirection), cereal::make_nvp("useOpenXinput", useOpenXinput), cereal::make_nvp("TranslateXinputtoMKB", TranslateXinputtoMKB), + cereal::make_nvp("XinputtoMKBstickinvert", XinputtoMKBstickinvert), + cereal::make_nvp("ScanOption", ScanOption), + + cereal::make_nvp("Shoulderswappoints", Shoulderswappoints), + cereal::make_nvp("XAstatic", XAstatic), + cereal::make_nvp("XAclick", XAclick), + cereal::make_nvp("XAmove", XAmove), + + cereal::make_nvp("XBstatic", XBstatic), + cereal::make_nvp("XBclick", XBclick), + cereal::make_nvp("XBmove", XBmove), + cereal::make_nvp("XXstatic", XXstatic), + + cereal::make_nvp("XXclick", XXclick), + cereal::make_nvp("XXmove", XXmove), + cereal::make_nvp("XYclick", XYclick), + cereal::make_nvp("XYmove", XYmove), + + cereal::make_nvp("XinputtoMKBAkey", XinputtoMKBAkey), + cereal::make_nvp("XinputtoMKBBkey", XinputtoMKBBkey), + cereal::make_nvp("XinputtoMKBXkey", XinputtoMKBXkey), + cereal::make_nvp("XinputtoMKBYkey", XinputtoMKBYkey), + cereal::make_nvp("XinputtoMKBRSkey", XinputtoMKBRSkey), + cereal::make_nvp("XinputtoMKBLSkey", XinputtoMKBLSkey), + cereal::make_nvp("XinputtoMKBrightkey", XinputtoMKBrightkey), + cereal::make_nvp("XinputtoMKBleftkey", XinputtoMKBleftkey), + cereal::make_nvp("XinputtoMKBupkey", XinputtoMKBupkey), + cereal::make_nvp("XinputtoMKBdownkey", XinputtoMKBdownkey), + cereal::make_nvp("XinputtoMKBstickR", XinputtoMKBstickR), + cereal::make_nvp("XinputtoMKBstickL", XinputtoMKBstickL), + cereal::make_nvp("XinputtoMKBstickright", XinputtoMKBstickright), + cereal::make_nvp("XinputtoMKBstickleft", XinputtoMKBstickleft), + + cereal::make_nvp("XinputtoMKBstickleft", XinputtoMKBstickleft), + cereal::make_nvp("XinputtoMKBstickup", XinputtoMKBstickup), + cereal::make_nvp("XinputtoMKBstickdown", XinputtoMKBstickdown), + cereal::make_nvp("XinputtoMKBoption", XinputtoMKBoption), + cereal::make_nvp("XinputtoMKBstart", XinputtoMKBstart), + cereal::make_nvp("XinputtoMKBsens", XinputtoMKBsens), + cereal::make_nvp("XinputtoMKBsensmult", XinputtoMKBsensmult), + cereal::make_nvp("useFakeClipCursor", useFakeClipCursor), cereal::make_nvp("showCursorWhenImageUpdated", showCursorWhenImageUpdated), diff --git a/src/ProtoInput/ProtoInputLoader/Inject.cpp b/src/ProtoInput/ProtoInputLoader/Inject.cpp index f2294ac..bbbd99f 100644 --- a/src/ProtoInput/ProtoInputLoader/Inject.cpp +++ b/src/ProtoInput/ProtoInputLoader/Inject.cpp @@ -697,7 +697,7 @@ void SetDontWaitWindowBorder(ProtoInstanceHandle instanceHandle, bool enabled) ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetDontWaitWindowBorder, &message); } } -void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright, int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, bool XinputtoMKBstickinvert) +void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright, int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, int XinputtoMKBsens, int XinputtoMKBsensmult) { if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) { @@ -725,12 +725,14 @@ void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, XinputtoMKBstickdown, XinputtoMKBoption, XinputtoMKBstart, + XinputtoMKBsens, + XinputtoMKBsensmult }; ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetXinputtoMKBkeys, &message); } } -void SetXinputtoMKBCFG(ProtoInstanceHandle instanceHandle, bool stickinvert, bool scanoption, bool shoulderswap, bool astatic, bool bstatic, bool xstatic, bool ystatic) +void SetXinputtoMKBCFG(ProtoInstanceHandle instanceHandle, bool stickinvert, bool scanoption, bool shoulderswap, bool astatic, bool aclick, bool amove, bool bstatic, bool bclick, bool bmove, bool xstatic, bool xclick, bool xmove, bool ystatic, bool yclick, bool ymove ) { if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) { @@ -744,9 +746,17 @@ void SetXinputtoMKBCFG(ProtoInstanceHandle instanceHandle, bool stickinvert, boo scanoption, shoulderswap, astatic, + aclick, + amove, bstatic, + bclick, + bmove, xstatic, + xclick, + xmove, ystatic, + yclick, + ymove }; ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetXinputtoMKBCFG, &message); diff --git a/src/ProtoInput/ProtoInputLoader/include/protoloader.h b/src/ProtoInput/ProtoInputLoader/include/protoloader.h index e8c9642..a8103bb 100644 --- a/src/ProtoInput/ProtoInputLoader/include/protoloader.h +++ b/src/ProtoInput/ProtoInputLoader/include/protoloader.h @@ -153,6 +153,6 @@ extern "C" __declspec(dllexport) void SetAdjustWindowRectSettings(ProtoInstanceH extern "C" __declspec(dllexport) void SetDontWaitWindowBorder(ProtoInstanceHandle instanceHandle, bool enabled); -extern "C" __declspec(dllexport) void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright, int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, bool XinputtoMKBstickinvert); +extern "C" __declspec(dllexport) void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright, int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, int XinputtoMKBsens, int XinputtoMKBsensmult); -extern "C" __declspec(dllexport) void SetXinputtoMKBCFG(ProtoInstanceHandle instanceHandle, bool stickinvert, bool scanoption, bool shoulderswap, bool astatic, bool bstatic, bool xstatic, bool ystatic); \ No newline at end of file +extern "C" __declspec(dllexport) void SetXinputtoMKBCFG(ProtoInstanceHandle instanceHandle, bool stickinvert, bool scanoption, bool shoulderswap, bool astatic, bool aclick, bool amove, bool bstatic, bool bclick, bool bmove, bool xstatic, bool xclick, bool xmove, bool ystatic, bool yclick, bool ymove); \ No newline at end of file From 3c25075723fbb8450b1f46f96c66f43c9218b32b Mon Sep 17 00:00:00 2001 From: messenils Date: Sun, 15 Feb 2026 10:43:28 +0100 Subject: [PATCH 12/20] Render now okay. dont know of any other problems --- src/ProtoInput/ProtoInputHooks/FakeCursor.cpp | 98 ++++++++++++------- src/ProtoInput/ProtoInputHooks/FakeCursor.h | 4 +- src/ProtoInput/ProtoInputHooks/ScanThread.cpp | 52 +++++----- .../ProtoInputHooks/TranslateXtoMKB.cpp | 28 +++--- .../ProtoInputHooks/TranslateXtoMKB.h | 1 + 5 files changed, 107 insertions(+), 76 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp index f9fc492..8e534ea 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp @@ -130,10 +130,11 @@ void FakeCursor::DrawMessage(HDC hdc, HWND window, HBRUSH Brush, int message) // FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! RECT wholewindow; GetClientRect(pointerWindow, &wholewindow); - + wholewindow.bottom = wholewindow.bottom / 2; FillRect(hdc, &wholewindow, Brush); // MessageBoxA(NULL, "Message Erased!", "Debug", MB_OK); - /// messageshown = false; + messageshown = false; + ScreenshotInput::TranslateXtoMKB::RefreshWindow = 1; //redraw cursor } if (!messageshown) { @@ -190,6 +191,7 @@ void FakeCursor::DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, { bool windowmoved = false; bool erasedA = false; + bool erased = false; bool erasedB = false; bool erasedX = false; bool erasedY = false; @@ -201,89 +203,90 @@ void FakeCursor::DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, windowmoved = true; //MessageBoxA(NULL, "Window moved!", "Debug", MB_OK); } - if (OldspotA.x != spotA.x) + if (OldspotA.x != spotA.x || OldspotA.y != spotA.y) { RECT wholewindow; GetClientRect(pointerWindow, &wholewindow); FillRect(hdc, &wholewindow, Brush); - erasedA = true; - // std::string text = "OldSpot:\nA = " + std::to_string(OldspotA.x) + - // "\nNewspot = " + std::to_string(spotA.x); - // MessageBoxA(NULL, text.c_str(), "Two Integers", MB_OK); + erased = true; + ScreenshotInput::TranslateXtoMKB::RefreshWindow = 1; //redraw cursor } if (OldspotB.x != spotB.x || OldspotB.y != spotB.y) //|| windowmoved) { - RECT fill{ OldspotB.x - 20, OldspotB.y - 20, OldspotB.x + 20, OldspotB.y + 20 }; - FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! - erasedB = true; + RECT wholewindow; + GetClientRect(pointerWindow, &wholewindow); + + FillRect(hdc, &wholewindow, Brush); + erased = true; + ScreenshotInput::TranslateXtoMKB::RefreshWindow = 1; //redraw cursor } if (OldspotX.x != spotX.x || OldspotX.y != spotX.y) //|| windowmoved) { - RECT fill{ OldspotX.x - 20, OldspotX.y - 20, OldspotX.x + 20, OldspotX.y + 20 }; - FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! - erasedX = true; + RECT wholewindow; + GetClientRect(pointerWindow, &wholewindow); + + FillRect(hdc, &wholewindow, Brush); + erased = true; + ScreenshotInput::TranslateXtoMKB::RefreshWindow = 1; //redraw cursor } if (OldspotY.x != spotY.x || OldspotY.y != spotY.y) //|| windowmoved) { - RECT fill{ OldspotY.x - 20, OldspotY.y - 20, OldspotY.x + 20, OldspotY.y + 20 }; - FillRect(hdc, &fill, Brush); // Note: window, not screen coordinates! - erasedY = true; + RECT wholewindow; + GetClientRect(pointerWindow, &wholewindow); + + FillRect(hdc, &wholewindow, Brush); + erased = true; + ScreenshotInput::TranslateXtoMKB::RefreshWindow = 1; //redraw cursor } OldspotA.x = spotA.x; - OldspotB = spotB; - OldspotX = spotX; - OldspotY = spotY; + OldspotA.y = spotA.y; + OldspotB.x = spotB.x; + OldspotB.y = spotB.y; + OldspotX.x = spotX.x; + OldspotX.y = spotX.y; + OldspotY.x = spotY.x; + OldspotY.y = spotY.y; - if (spotA.x != 0 && spotA.y != 0 && erasedA == true) + if (spotA.x != 0 && spotA.y != 0 && erased == true) { ClientToScreen(window, &spotA); DrawRedX(hdc, spotA.x, spotA.y); //MessageBoxA(NULL, "Spot A drawn!", "Debug", MB_OK); erasedA = false; } - if (spotB.x != 0 && spotB.y != 0 && erasedB == true) + if (spotB.x != 0 && spotB.y != 0 && erased == true) { ClientToScreen(window, &spotB); DrawBlueCircle(hdc, spotB.x, spotB.y); } - if (spotX.x != 0 && spotX.y != 0 && erasedX == true) + if (spotX.x != 0 && spotX.y != 0 && erased == true) { ClientToScreen(window, &spotX); DrawGreenTriangle(hdc, spotX.x, spotX.y); } - if (spotY.x != 0 && spotY.y != 0 && erasedY == true) + if (spotY.x != 0 && spotY.y != 0 && erased == true) { ClientToScreen(window, &spotY); DrawPinkSquare(hdc, spotY.x, spotY.y); } - - - OldTestpos = testpos; } -void FakeCursor::DrawCursor() -{ - if (oldHadShowCursor) //erase cursor - { - RECT fill{ oldX, oldY, oldX + cursorWidth, oldY + cursorHeight }; - FillRect(hdc, &fill, transparencyBrush); // Note: window, not screen coordinates! - - } - +void FakeCursor::DrawPointsandMessages() +{ if (ScreenshotInput::ScanThread::scanoption) { EnterCriticalSection(&ScreenshotInput::ScanThread::critical); selectorhwnd = (HWND)HwndSelector::GetSelectedHwnd(); - // FakeCursor::Showmessage = ScreenshotInput::TranslateXtoMKB::showmessage; + // FakeCursor::Showmessage = ScreenshotInput::TranslateXtoMKB::showmessage; POINT Apos = { ScreenshotInput::ScanThread::PointA.x, ScreenshotInput::ScanThread::PointA.y }; - POINT Bpos = { ScreenshotInput::ScanThread::PointB.x, ScreenshotInput::ScanThread::PointB.y }; + POINT Bpos = { ScreenshotInput::ScanThread::PointB.x, ScreenshotInput::ScanThread::PointB.y }; POINT Xpos = { ScreenshotInput::ScanThread::PointX.x, ScreenshotInput::ScanThread::PointX.y }; POINT Ypos = { ScreenshotInput::ScanThread::PointY.x, ScreenshotInput::ScanThread::PointY.y }; FakeCursor::DrawFoundSpots(hdc, Apos, Bpos, Xpos, Ypos, selectorhwnd, transparencyBrush); @@ -293,12 +296,24 @@ void FakeCursor::DrawCursor() else if (RawInput::TranslateXinputtoMKB) DrawMessage(hdc, (HWND)HwndSelector::GetSelectedHwnd(), transparencyBrush, FakeCursor::Showmessage); - oldHadShowCursor = showCursor; +} +void FakeCursor::DrawCursor() +{ POINT pos = { FakeMouseKeyboard::GetMouseState().x,FakeMouseKeyboard::GetMouseState().y }; + ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &pos); ScreenToClient(pointerWindow, &pos); + if (oldHadShowCursor) //erase cursor + { + RECT fill{ oldX, oldY, oldX + cursorWidth, oldY + cursorHeight }; + FillRect(hdc, &fill, transparencyBrush); // Note: window, not screen coordinates! + } + + oldHadShowCursor = showCursor; + + if (DrawFakeCursorFix) { pos.x -= cursoroffsetx; @@ -407,7 +422,9 @@ void FakeCursor::DrawCursor() } } else if (showCursor) + { DrawIcon(hdc, pos.x, pos.y, hCursor); + } oldX = pos.x; oldY = pos.y; } @@ -442,6 +459,11 @@ void FakeCursor::StartDrawLoopInternal() } else { ScreenshotInput::TranslateXtoMKB::ThreadFunction(); + if (ScreenshotInput::TranslateXtoMKB::RefreshPoint > 0) + { + DrawPointsandMessages(); + ScreenshotInput::TranslateXtoMKB::RefreshPoint--; + } if (ScreenshotInput::TranslateXtoMKB::RefreshWindow > 0) { DrawCursor(); diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.h b/src/ProtoInput/ProtoInputHooks/FakeCursor.h index 0a2cbbd..0a4a2e1 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.h +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.h @@ -39,9 +39,11 @@ namespace Proto bool toggleVisilbityShorcutEnabled = false; unsigned int toggleVisibilityVkey = VK_HOME; - void DrawCursor(); void DrawMessage(HDC hdc, HWND window, HBRUSH Brush, int message); void DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, POINT spotY, HWND window, HBRUSH Brush); + void DrawPointsandMessages(); + void DrawCursor(); + public: static FakeCursor state; diff --git a/src/ProtoInput/ProtoInputHooks/ScanThread.cpp b/src/ProtoInput/ProtoInputHooks/ScanThread.cpp index 942995a..63602f6 100644 --- a/src/ProtoInput/ProtoInputHooks/ScanThread.cpp +++ b/src/ProtoInput/ProtoInputHooks/ScanThread.cpp @@ -183,9 +183,10 @@ namespace ScreenshotInput { ScanThread::staticPointA[i].y = Y; ScanThread::PointA.x = X; ScanThread::PointA.y = Y; - if (Awas != ScanThread::startsearchA) + if (Aprevious.x != X || Aprevious.y != Y) ScanThread::UpdateWindow = true; - Awas = ScanThread::startsearchA; + Aprevious.x = X; + Aprevious.y = Y; LeaveCriticalSection(&ScanThread::critical); } else @@ -209,10 +210,10 @@ namespace ScreenshotInput { ScanThread::startsearchA = 0; ScanThread::PointA.x = 0; ScanThread::PointA.y = 0; - // if (Aprevious.x != X || Aprevious.y != Y) - // ScanThread::UpdateWindow = true; - // Aprevious.x = ScanThread::PointA.x; - // Aprevious.y = ScanThread::PointA.y; + if (Aprevious.x != X || Aprevious.y != Y) + ScanThread::UpdateWindow = true; + Aprevious.x = X; + Aprevious.y = Y; LeaveCriticalSection(&ScanThread::critical); } } @@ -232,9 +233,10 @@ namespace ScreenshotInput { ScanThread::staticPointB[i].x = X; ScanThread::staticPointB[i].y = Y; ScanThread::PointB.y = Y; - if (Bwas != i) + if (Bprevious.x != X || Bprevious.y != Y) ScanThread::UpdateWindow = true; - Bwas = i; + Bprevious.x = X; + Bprevious.y = Y; LeaveCriticalSection(&ScanThread::critical); } else @@ -257,10 +259,10 @@ namespace ScreenshotInput { ScanThread::startsearchB = 0; ScanThread::PointB.x = 0; ScanThread::PointB.y = 0; - // if (Bprevious.x != X || Bprevious.y != Y) - // ScanThread::UpdateWindow = true; - // Bprevious.x = ScanThread::PointB.x; - // Bprevious.y = ScanThread::PointB.y; + if (Bprevious.x != X || Bprevious.y != Y) + ScanThread::UpdateWindow = true; + Bprevious.x = X; + Bprevious.y = Y; LeaveCriticalSection(&ScanThread::critical); } } @@ -280,9 +282,10 @@ namespace ScreenshotInput { ScanThread::PointX.y = Y; ScanThread::staticPointX[i].x = X; ScanThread::staticPointX[i].y = Y; - if (Xwas != i) + if (Xprevious.x != X || Xprevious.y != Y) ScanThread::UpdateWindow = true; - Xwas = i; + Xprevious.x = X; + Xprevious.y = Y; LeaveCriticalSection(&ScanThread::critical); } else @@ -306,10 +309,10 @@ namespace ScreenshotInput { ScanThread::startsearchX = 0; ScanThread::PointX.x = 0; ScanThread::PointX.y = 0; - // if (Xprevious.x != X || Xprevious.y != Y) - // ScanThread::UpdateWindow = true; - // Xprevious.x = ScanThread::PointX.x; - // Xprevious.y = ScanThread::PointX.y; + if (Xprevious.x != X || Xprevious.y != Y) + ScanThread::UpdateWindow = true; + Xprevious.x = ScanThread::PointX.x; + Xprevious.y = ScanThread::PointX.y; LeaveCriticalSection(&ScanThread::critical); } } @@ -329,9 +332,10 @@ namespace ScreenshotInput { ScanThread::staticPointY[i].y = Y; ScanThread::PointY.x = X; ScanThread::PointY.y = Y; - if (Ywas != i) + if (Yprevious.x != X || Yprevious.y != Y) ScanThread::UpdateWindow = true; - Ywas = i; + Yprevious.x = X; + Yprevious.y = Y; LeaveCriticalSection(&ScanThread::critical); } else @@ -356,10 +360,10 @@ namespace ScreenshotInput { //input = scanYtype; ScanThread::PointY.x = 0; ScanThread::PointY.y = 0; - // if (Yprevious.x != X || Yprevious.y != Y) - // ScanThread::UpdateWindow = true; - // Yprevious.x = ScanThread::PointY.x; - // Yprevious.y = ScanThread::PointY.y; + if (Yprevious.x != X || Yprevious.y != Y) + ScanThread::UpdateWindow = true; + Yprevious.x = ScanThread::PointY.x; + Yprevious.y = ScanThread::PointY.y; LeaveCriticalSection(&ScanThread::critical); } } diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp index 60e1fb8..9e162e7 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -45,6 +45,7 @@ namespace ScreenshotInput int InstanceID = 0; //InstanceID copy from stateinfo.h int TranslateXtoMKB::RefreshWindow; + int TranslateXtoMKB::RefreshPoint; //from tunnell int TranslateXtoMKB::controllerID; bool TranslateXtoMKB::rawinputhook; //registerrawinputhook @@ -306,7 +307,7 @@ namespace ScreenshotInput ScanThread::SaveWindow10x10BMP(hwndhere, wpath.c_str(), muusjn.x, muusjn.y); // MessageBoxW(nullptr, wpath.c_str(), L"Path", MB_OK); - TranslateXtoMKB::RefreshWindow ++; + TranslateXtoMKB::RefreshPoint ++; counter = 0; } } @@ -422,7 +423,7 @@ namespace ScreenshotInput EnterCriticalSection(&ScanThread::critical); if (ScanThread::UpdateWindow) - TranslateXtoMKB::RefreshWindow = 1; + TranslateXtoMKB::RefreshPoint = 1; LeaveCriticalSection(&ScanThread::critical); modeMT = 1; if (TranslateXtoMKB::SaveBmps) { @@ -446,7 +447,7 @@ namespace ScreenshotInput Proto::ToggleWindow(); oldGUIkey = true; Proto::FakeCursor::Showmessage = 2; - TranslateXtoMKB::RefreshWindow = 1; + TranslateXtoMKB::RefreshPoint = 1; tick = 0; if (TranslateXtoMKB::mode == 1) //modechange { @@ -465,7 +466,7 @@ namespace ScreenshotInput if (Proto::FakeCursor::Showmessage == 1) {//remove disconnected message Proto::FakeCursor::Showmessage = 0; - TranslateXtoMKB::RefreshWindow = 1; + TranslateXtoMKB::RefreshPoint = 1; } if (modeMT > 0) { @@ -630,7 +631,7 @@ namespace ScreenshotInput ButtonStateImpulse(TranslateXtoMKB::Amapping, true, 0);//down } else ButtonStateImpulse(TranslateXtoMKB::Amapping, true, 0); - TranslateXtoMKB::RefreshWindow = 2; + TranslateXtoMKB::RefreshPoint = 2; } @@ -654,7 +655,7 @@ namespace ScreenshotInput ButtonStateImpulse(TranslateXtoMKB::Bmapping, true, 1);//down } else ButtonStateImpulse(TranslateXtoMKB::Bmapping, true, 1);//down - TranslateXtoMKB::RefreshWindow = 2; + TranslateXtoMKB::RefreshPoint = 2; } @@ -678,7 +679,7 @@ namespace ScreenshotInput ButtonStateImpulse(TranslateXtoMKB::Xmapping, true, 2);//down } else ButtonStateImpulse(TranslateXtoMKB::Xmapping, true, 2);//down - TranslateXtoMKB::RefreshWindow = 2; + TranslateXtoMKB::RefreshPoint = 2; } @@ -702,7 +703,7 @@ namespace ScreenshotInput ButtonStateImpulse(TranslateXtoMKB::Ymapping, true, 3);//down } else ButtonStateImpulse(TranslateXtoMKB::Ymapping, true, 3);//down - TranslateXtoMKB::RefreshWindow = 2; + TranslateXtoMKB::RefreshPoint = 2; } @@ -726,7 +727,7 @@ namespace ScreenshotInput ButtonStateImpulse(TranslateXtoMKB::RSmapping, true, 99); //down } else ButtonStateImpulse(TranslateXtoMKB::RSmapping, true, 99); //down - TranslateXtoMKB::RefreshWindow = 10; + TranslateXtoMKB::RefreshPoint = 10; } @@ -750,7 +751,7 @@ namespace ScreenshotInput ButtonStateImpulse(TranslateXtoMKB::LSmapping, true, 99);//down } else ButtonStateImpulse(TranslateXtoMKB::LSmapping, true, 99);//down - TranslateXtoMKB::RefreshWindow = 10; + TranslateXtoMKB::RefreshPoint = 10; } @@ -835,7 +836,7 @@ namespace ScreenshotInput { Proto::FakeCursor::SetCursorVisibility(!Proto::FakeCursor::GetCursorVisibility()); Proto::FakeCursor::Showmessage = 3; - TranslateXtoMKB::RefreshWindow = 1;; + TranslateXtoMKB::RefreshPoint = 1; tick = 0; oldstartoptions = true; } @@ -875,7 +876,7 @@ namespace ScreenshotInput } //if controller else { //no controller Proto::FakeCursor::Showmessage = 1; - TranslateXtoMKB::RefreshWindow = 1; + TranslateXtoMKB::RefreshPoint = 1; tick = 0; } if (tick < updatewindowtick) @@ -884,6 +885,7 @@ namespace ScreenshotInput // EnterCriticalSection(&ScanThread::critical); Proto::HwndSelector::UpdateMainHwnd(false); Proto::HwndSelector::UpdateWindowBounds(); + TranslateXtoMKB::RefreshPoint = 1; tick = 0; } @@ -893,7 +895,7 @@ namespace ScreenshotInput } else { Proto::FakeCursor::Showmessage = 0; - TranslateXtoMKB::RefreshWindow = 1; + TranslateXtoMKB::RefreshPoint = 1; counter = 0; } } diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h index cf7ddd8..ce3d16c 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.h @@ -15,6 +15,7 @@ namespace ScreenshotInput static void ThreadFunction(); //polling from idle drawfakecursor thread static void SendMouseClick(int x, int y, int z); static int RefreshWindow; + static int RefreshPoint; static int controllerID; static bool rawinputhook; static bool registerrawinputhook; From 834d0b9e37e7be529c0d8d8ce9d93baf3c16fa1f Mon Sep 17 00:00:00 2001 From: Messenils Date: Wed, 25 Feb 2026 16:11:07 +0100 Subject: [PATCH 13/20] New option: ProtoInput.ScaleInput. handles mouse scaling if any game do not react to resize messages --- .../ProtoInputHooks/GetCursorInfoHook.cpp | 6 +- .../ProtoInputHooks/GetCursorPosHook.cpp | 7 + .../ProtoInputHooks/HwndSelector.cpp | 109 ++++++- .../ProtoInputHooks/PipeCommunication.cpp | 6 +- .../ProtoInputHooks/ProtoInputHooks.vcxproj | 2 + .../ProtoInputHooks.vcxproj.filters | 6 + src/ProtoInput/ProtoInputHooks/Scaler.cpp | 131 ++++++++ src/ProtoInput/ProtoInputHooks/Scaler.h | 16 + .../ProtoInputHooks/SetCursorPosHook.cpp | 4 + src/ProtoInput/ProtoInputHooks/dllmain.cpp | 4 + .../ProtoInputHooks/pipeinclude/pipeinclude.h | 1 + src/ProtoInput/ProtoInputLoader/Inject.cpp | 4 +- .../ProtoInputLoader/include/protoloader.h | 2 +- src/ProtoInput/UpgradeLog.htm | 284 ++++++++++++++++++ 14 files changed, 561 insertions(+), 21 deletions(-) create mode 100644 src/ProtoInput/ProtoInputHooks/Scaler.cpp create mode 100644 src/ProtoInput/ProtoInputHooks/Scaler.h create mode 100644 src/ProtoInput/UpgradeLog.htm diff --git a/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp b/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp index 95baa9f..ef8ba87 100644 --- a/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/GetCursorInfoHook.cpp @@ -1,7 +1,7 @@ #include "GetCursorInfoHook.h" #include "FakeMouseKeyboard.h" #include "HwndSelector.h" - +#include "Scaler.h" namespace Proto { @@ -31,6 +31,10 @@ namespace Proto clientPos.x = clientWidth - 1; // Right edge } } + + //any scaling? + clientPos = Scaler::getfactor(clientPos); + ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &clientPos); pci->ptScreenPos.x = clientPos.x; pci->ptScreenPos.y = clientPos.y; diff --git a/src/ProtoInput/ProtoInputHooks/GetCursorPosHook.cpp b/src/ProtoInput/ProtoInputHooks/GetCursorPosHook.cpp index bc9448a..cf7f15d 100644 --- a/src/ProtoInput/ProtoInputHooks/GetCursorPosHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/GetCursorPosHook.cpp @@ -1,6 +1,7 @@ #include "GetCursorPosHook.h" #include "FakeMouseKeyboard.h" #include "HwndSelector.h" +#include "Scaler.h" namespace Proto { @@ -32,6 +33,12 @@ BOOL WINAPI Hook_GetCursorPos(LPPOINT lpPoint) lpPoint->x = clientWidth - 1; // Right edge } } + //any scaling? + POINT clientPos = { lpPoint->x, lpPoint->y }; + clientPos = Scaler::getfactor(clientPos); + + lpPoint->x = clientPos.x; + lpPoint->y = clientPos.y; ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), lpPoint); } diff --git a/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp b/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp index 06ef942..e3af7a4 100644 --- a/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp +++ b/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp @@ -3,6 +3,9 @@ #include #include "FakeCursor.h" #include "TranslateXtoMKB.h" +#include +#pragma comment(lib, "dwmapi.lib") + namespace Proto @@ -16,18 +19,54 @@ struct HandleData unsigned long pid; HWND hwnd; }; - -BOOL IsMainWindow(HWND handle) +int somonge = 0; +BOOL IsMainWindow(HWND hwnd) { - // Is top level & visible & not one of ours - return - GetWindow(handle, GW_OWNER) == (HWND)0 && - IsWindowVisible(handle) && - handle != (HWND)Proto::ConsoleHwnd && - handle != Proto::ProtoGuiHwnd && - handle != FakeCursor::GetPointerWindow(); + if (!IsWindow(hwnd)) return FALSE; + + // Must be visible + if (!IsWindowVisible(hwnd)) return FALSE; + + // Must not be a child window + if (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD) return FALSE; + + RECT rect; + int width; int height; + if (GetClientRect(hwnd, &rect)) + { + width = rect.right - rect.left; + } + if (width < 400) + { + //MessageBoxA(NULL, "neikasvarte. DWM bredder", "oja", MB_OK); + HRESULT hr = DwmGetWindowAttribute( + (HWND)hwnd, + DWMWA_EXTENDED_FRAME_BOUNDS, + &rect, + sizeof(rect) + ); + + if (SUCCEEDED(hr)) { + width = rect.right - rect.left; + } + + } + if (width < 400) + { + return FALSE; + } + + // Exclude your own windows + if (hwnd == (HWND)Proto::ConsoleHwnd) return FALSE; + if (hwnd == Proto::ProtoGuiHwnd) return FALSE; + if (hwnd == FakeCursor::GetPointerWindow()) return FALSE; + + if (GetWindow(hwnd, GW_OWNER) == (HWND)0) + return TRUE; + return FALSE; } + BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) { HandleData& data = *(HandleData*)lParam; @@ -50,14 +89,34 @@ void HwndSelector::UpdateMainHwnd(bool logOutput) HandleData data { GetCurrentProcessId(), nullptr }; EnumWindows(EnumWindowsCallback, (LPARAM)&data); - const auto hwnd = (intptr_t)data.hwnd; - + auto hwnd = (intptr_t)data.hwnd; + if (logOutput) { + + + if (hwnd == 0) + { printf("Warning: UpdateMainHwnd didn't find a main window\n"); - else + + } + else //EnumChildWindows(parent, EnumChildProc, (LPARAM)pid); printf("UpdateMainHwnd found hwnd %d (0x%X)\n", hwnd, hwnd); + // else { + // MessageBoxA(NULL, "neikasvarte ingen bredde likevel. prøver childs", "oja", MB_OK); + // EnumChildWindows((HWND)hwnd, EnumWindowsCallback, (LPARAM)&data); + // hwnd = (intptr_t)data.hwnd; + // if (hwnd == 0) + // { + // printf("Warning: UpdateMainHwnd didn't find a main window even after searching children\n"); + // } + // else + // { + // MessageBoxA(NULL, "oja, fant noe allikevel.", "oja", MB_OK); + // printf("UpdateMainHwnd found child hwnd %d (0x%X)\n", hwnd, hwnd); + // } + // } } if (data.hwnd != nullptr) @@ -69,11 +128,33 @@ void HwndSelector::UpdateWindowBounds() RECT rect; if (GetClientRect((HWND)selectedHwnd, &rect)) { - windowWidth = rect.right - rect.left; - windowHeight = rect.bottom - rect.top; + if ((rect.right - rect.left) > 5) + { + windowWidth = rect.right - rect.left; + windowHeight = rect.bottom - rect.top; + } + else { + HRESULT hr = DwmGetWindowAttribute( + (HWND)selectedHwnd, + DWMWA_EXTENDED_FRAME_BOUNDS, + &rect, + sizeof(rect) + ); + + if (SUCCEEDED(hr)) { + windowWidth = rect.right - rect.left; + windowHeight = rect.bottom - rect.top; + } + + } + } else fprintf(stderr, "GetClientRect failed in update main window bounds\n"); + if (windowWidth < 400) + windowWidth = 800; + if (windowHeight < 400) + windowHeight = 600; } void HwndSelector::SetSelectedHwnd(intptr_t set) diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index 9926cc0..e29e682 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -28,6 +28,7 @@ #include "RemoveBorderHook.h" #include "TranslateXtoMKB.h" #include "ScanThread.h" +#include "Scaler.h" namespace Proto { @@ -441,7 +442,7 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) SetWindowPosHook::posy = body->posy; SetWindowPosHook::width = body->width; SetWindowPosHook::height = body->height; - + Proto::Scaler::Settings(body->scale, body->width, body->height); break; } case ProtoPipe::PipeMessageType::SetSetWindowPosDontResize: @@ -693,10 +694,9 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) } endPipe: + printf("End of pipe thread\n"); - CloseHandle(pipe); - return 0; } diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj index 82f36fe..b00a36a 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj @@ -246,6 +246,7 @@ + @@ -300,6 +301,7 @@ + diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters index 7d5bbf3..97aa740 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters @@ -198,6 +198,9 @@ Source Files\Hooks + + Source Files + @@ -356,5 +359,8 @@ Source Files\Hooks + + Source Files + \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/Scaler.cpp b/src/ProtoInput/ProtoInputHooks/Scaler.cpp new file mode 100644 index 0000000..4342f3e --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/Scaler.cpp @@ -0,0 +1,131 @@ +#include "Scaler.h" +#include "FakeMouseKeyboard.h" +#include "HwndSelector.h" +#include "SetWindowPosHook.h" +#include +#include +#pragma comment(lib, "dwmapi.lib") + + +namespace Proto +{ + + int scalewidth = 0; + int scaleheight = 0; + int origwidth = 0; + int origheight = 0; + + bool Enableornot = false; + bool onlyonetimethis = false; + + WNDPROC g_OldWndProc = nullptr; + + POINT Scaler::getfactor(POINT pp){ + if (pp.x != 0 && pp.y != 0 && Enableornot && origwidth != 0 && scalewidth != 0) + { + float scalex = float(origwidth) / float(scalewidth); + float scaley = float(origheight) / float(scaleheight); + pp.x = static_cast(std::lround(pp.x * scalex)); + pp.y = static_cast(std::lround(pp.y * scaley)); + } + return pp; + } + LRESULT CALLBACK SubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch (msg) + { + case WM_MOUSEHOVER: // + MOVE // + click + { + const auto& state = Proto::FakeMouseKeyboard::GetMouseState(); + POINT clientPos = { state.x, state.y }; + clientPos = Scaler::getfactor(clientPos); + LPARAM newLParam = MAKELPARAM(clientPos.x, clientPos.y); + + return CallWindowProc(g_OldWndProc, hwnd, msg, wParam, newLParam); + break; + } + case WM_MOUSEMOVE: + { + const auto& state = Proto::FakeMouseKeyboard::GetMouseState(); + POINT clientPos = { state.x, state.y }; + clientPos = Scaler::getfactor(clientPos); + LPARAM newLParam = MAKELPARAM(clientPos.x, clientPos.y); + + return CallWindowProc(g_OldWndProc, hwnd, msg, wParam, newLParam); + break; + } + case WM_LBUTTONDOWN: + { + const auto& state = Proto::FakeMouseKeyboard::GetMouseState(); + POINT clientPos = { state.x, state.y }; + clientPos = Scaler::getfactor(clientPos); + LPARAM newLParam = MAKELPARAM(clientPos.x, clientPos.y); + return CallWindowProc(g_OldWndProc, hwnd, msg, wParam, newLParam); + + break; + } + case WM_LBUTTONUP: + { + const auto& state = Proto::FakeMouseKeyboard::GetMouseState(); + POINT clientPos = { state.x, state.y }; + clientPos = Scaler::getfactor(clientPos); + LPARAM newLParam = MAKELPARAM(clientPos.x, clientPos.y); + return CallWindowProc(g_OldWndProc, hwnd, msg, wParam, newLParam); + + break; + } + case WM_RBUTTONDOWN: + { + const auto& state = Proto::FakeMouseKeyboard::GetMouseState(); + POINT clientPos = { state.x, state.y }; + clientPos = Scaler::getfactor(clientPos); + LPARAM newLParam = MAKELPARAM(clientPos.x, clientPos.y); + return CallWindowProc(g_OldWndProc, hwnd, msg, wParam, newLParam); + + break; + } + case WM_RBUTTONUP: + { + const auto& state = Proto::FakeMouseKeyboard::GetMouseState(); + POINT clientPos = { state.x, state.y }; + clientPos = Scaler::getfactor(clientPos); + LPARAM newLParam = MAKELPARAM(clientPos.x, clientPos.y); + return CallWindowProc(g_OldWndProc, hwnd, msg, wParam, newLParam); + + break; + } + + } + // Forward all other messages unchanged + return CallWindowProc(g_OldWndProc, hwnd, msg, wParam, lParam); + } + + void Scaler::Install() + { + // MessageBoxA(NULL, "hihu", "letssee", MB_OK); + if (Enableornot && !onlyonetimethis) + { + //MessageBoxA(NULL, "Ohyea", "Scaler enabled", MB_OK); + Proto::HwndSelector::UpdateMainHwnd(); + Proto::HwndSelector::UpdateWindowBounds(); + origwidth = Proto::HwndSelector::windowWidth; + origheight = Proto::HwndSelector::windowHeight; + + g_OldWndProc = (WNDPROC)SetWindowLongPtr( + (HWND)Proto::HwndSelector::GetSelectedHwnd(), + GWLP_WNDPROC, + (LONG_PTR)SubclassProc + ); + onlyonetimethis = true; //or else crash + } + } + void Scaler::Settings(bool enabled, int scaletoX, int scaletoY) + { + if (enabled) + { + Enableornot = true; + scalewidth = scaletoX; + scaleheight = scaletoY; + } + } +} diff --git a/src/ProtoInput/ProtoInputHooks/Scaler.h b/src/ProtoInput/ProtoInputHooks/Scaler.h new file mode 100644 index 0000000..584ab32 --- /dev/null +++ b/src/ProtoInput/ProtoInputHooks/Scaler.h @@ -0,0 +1,16 @@ +#pragma once +#include "Hook.h" +#include "InstallHooks.h" + +namespace Proto +{ + + class Scaler + { + public: + static POINT getfactor(POINT pp); + static void Install(); + static void Settings(bool enabled, int scaletoX, int scaletoY); + }; + +} diff --git a/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.cpp b/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.cpp index f67b94f..d00f52c 100644 --- a/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.cpp @@ -3,6 +3,7 @@ #include "HwndSelector.h" #include "FakeMouseKeyboard.h" #include "FakeCursor.h" +#include "Scaler.h" namespace Proto { @@ -17,6 +18,9 @@ BOOL WINAPI Hook_SetCursorPos(int X, int Y) p.x = X; p.y = Y; + //any scaling here? + //p = WndProcHook::getfactor(p); + //SetCursorPos require screen coordinates (relative to 0,0 of monitor) ScreenToClient((HWND)HwndSelector::GetSelectedHwnd(), &p); diff --git a/src/ProtoInput/ProtoInputHooks/dllmain.cpp b/src/ProtoInput/ProtoInputHooks/dllmain.cpp index 5b599e0..0376553 100644 --- a/src/ProtoInput/ProtoInputHooks/dllmain.cpp +++ b/src/ProtoInput/ProtoInputHooks/dllmain.cpp @@ -11,6 +11,7 @@ #include "RawInput.h" #include "HookManager.h" #include "protoloader.h" +#include "Scaler.h" #include "PipeCommunication.h" #include "HwndSelector.h" #include "FocusMessageLoop.h" @@ -19,6 +20,7 @@ #include "TranslateXtoMKB.h" #include "ScanThread.h" + HMODULE dll_hModule; DWORD WINAPI GuiThread(LPVOID lpParameter) @@ -60,6 +62,8 @@ DWORD WINAPI StartThread(LPVOID lpParameter) InitializeCriticalSection(&ScreenshotInput::ScanThread::critical); + Sleep(1000); + Proto::Scaler::Install(); //or not HANDLE hGuiThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)GuiThread, dll_hModule, CREATE_SUSPENDED, &Proto::GuiThreadID); diff --git a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h index d6cdf2f..5f55780 100644 --- a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h +++ b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h @@ -176,6 +176,7 @@ struct PipeMessageSetSetWindowPosSettings int posy; int width; int height; + bool scale; }; struct PipeMessageSetSetWindowPosDontResize diff --git a/src/ProtoInput/ProtoInputLoader/Inject.cpp b/src/ProtoInput/ProtoInputLoader/Inject.cpp index bbbd99f..d03b502 100644 --- a/src/ProtoInput/ProtoInputLoader/Inject.cpp +++ b/src/ProtoInput/ProtoInputLoader/Inject.cpp @@ -396,7 +396,7 @@ void DinputHookAlsoHooksGetDeviceState(ProtoInstanceHandle instanceHandle, bool } } -void SetSetWindowPosSettings(ProtoInstanceHandle instanceHandle, int posx, int posy, int width, int height) +void SetSetWindowPosSettings(ProtoInstanceHandle instanceHandle, int posx, int posy, int width, int height, bool scale) { if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) { @@ -406,7 +406,7 @@ void SetSetWindowPosSettings(ProtoInstanceHandle instanceHandle, int posx, int p ProtoPipe::PipeMessageSetSetWindowPosSettings message { - posx, posy, width, height + posx, posy, width, height, scale }; ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetSetWindowPosSettings, &message); diff --git a/src/ProtoInput/ProtoInputLoader/include/protoloader.h b/src/ProtoInput/ProtoInputLoader/include/protoloader.h index a8103bb..a80572a 100644 --- a/src/ProtoInput/ProtoInputLoader/include/protoloader.h +++ b/src/ProtoInput/ProtoInputLoader/include/protoloader.h @@ -119,7 +119,7 @@ extern "C" __declspec(dllexport) void SetDinputDeviceGUID(ProtoInstanceHandle in // This MUST be called before calling InstallHook on the Dinput order hook extern "C" __declspec(dllexport) void DinputHookAlsoHooksGetDeviceState(ProtoInstanceHandle instanceHandle, bool enable); -extern "C" __declspec(dllexport) void SetSetWindowPosSettings(ProtoInstanceHandle instanceHandle, int posx, int posy, int width, int height); +extern "C" __declspec(dllexport) void SetSetWindowPosSettings(ProtoInstanceHandle instanceHandle, int posx, int posy, int width, int height, bool scale); extern "C" __declspec(dllexport) void SetSetWindowPosDontResize(ProtoInstanceHandle instanceHandle, bool enabled); diff --git a/src/ProtoInput/UpgradeLog.htm b/src/ProtoInput/UpgradeLog.htm new file mode 100644 index 0000000..5b72eec --- /dev/null +++ b/src/ProtoInput/UpgradeLog.htm @@ -0,0 +1,284 @@ + + + + Migration Report +

+ Migration Report -

Overview

ProjectPathErrorsWarningsMessages
BlackBone..\..\lib\Blackbone\src\BlackBone\BlackBone.vcxproj100
DEVOBJ..\..\lib\openxinput-OpenXinput1_4\DEVOBJ\DEVOBJ.vcxproj100
EasyHookDll..\..\lib\EasyHook\EasyHookDll\EasyHookDll.vcxproj100
OpenXinput..\..\lib\openxinput-OpenXinput1_4\OpenXinput.vcxproj100
ProtoInputHooksProtoInputHooks\ProtoInputHooks.vcxproj100
ProtoInputHostProtoInputHost\ProtoInputHost.vcxproj100
ProtoInputInjectorProtoInputInjector\ProtoInputInjector.vcxproj100
ProtoInputInjectorProxyProtoInputInjectorProxy\ProtoInputInjectorProxy.vcxproj100
ProtoInputLoaderProtoInputLoader\ProtoInputLoader.vcxproj100
ProtoInputUtilDynamicProtoInputUtilDynamic\ProtoInputUtilDynamic.vcxproj100
ProtoInputUtilStaticProtoInputUtil\ProtoInputUtil.vcxproj100
XinputXinput000
SolutionProtoInput.sln001

Solution and projects

BlackBone

Message
..\..\lib\Blackbone\src\BlackBone\BlackBone.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

DEVOBJ

Message
..\..\lib\openxinput-OpenXinput1_4\DEVOBJ\DEVOBJ.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

EasyHookDll

Message
..\..\lib\EasyHook\EasyHookDll\EasyHookDll.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

OpenXinput

Message
..\..\lib\openxinput-OpenXinput1_4\OpenXinput.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

ProtoInputHooks

Message
ProtoInputHooks\ProtoInputHooks.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

ProtoInputHost

Message
ProtoInputHost\ProtoInputHost.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

ProtoInputInjector

Message
ProtoInputInjector\ProtoInputInjector.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

ProtoInputInjectorProxy

Message
ProtoInputInjectorProxy\ProtoInputInjectorProxy.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

ProtoInputLoader

Message
ProtoInputLoader\ProtoInputLoader.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

ProtoInputUtilDynamic

Message
ProtoInputUtilDynamic\ProtoInputUtilDynamic.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

ProtoInputUtilStatic

Message
ProtoInputUtil\ProtoInputUtil.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

Xinput

Message
Xinput logged no messages. +

Solution

Message
+ Show 1 additional messages +
ProtoInput.sln: + The solution file does not require migration.
+ Hide 1 additional messages +
\ No newline at end of file From 60b3a068a6c6f9ba8128435a55ff3f57fc6418b7 Mon Sep 17 00:00:00 2001 From: Messenils Date: Sat, 28 Feb 2026 16:07:51 +0100 Subject: [PATCH 14/20] made the scaling manual, with 2 new lines --- .../ProtoInputHooks/PipeCommunication.cpp | 21 ++++++++-- .../ProtoInputHooks/PipeCommunication.h | 2 + src/ProtoInput/ProtoInputHooks/Scaler.cpp | 39 +++++++++++++------ src/ProtoInput/ProtoInputHooks/Scaler.h | 8 +++- src/ProtoInput/ProtoInputHooks/dllmain.cpp | 19 ++++----- .../ProtoInputHooks/pipeinclude/pipeinclude.h | 9 +++++ src/ProtoInput/ProtoInputLoader/Inject.cpp | 19 +++++++++ .../ProtoInputLoader/include/protoloader.h | 2 + 8 files changed, 91 insertions(+), 28 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index e29e682..4fcadc4 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -164,6 +164,7 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) else printf("Enabling TranslateXtoMKB"); } else printf("TranslateXtoMKB is set to false"); + SetEvent(evt); break; } @@ -442,7 +443,6 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) SetWindowPosHook::posy = body->posy; SetWindowPosHook::width = body->width; SetWindowPosHook::height = body->height; - Proto::Scaler::Settings(body->scale, body->width, body->height); break; } case ProtoPipe::PipeMessageType::SetSetWindowPosDontResize: @@ -613,6 +613,16 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) break; } + case ProtoPipe::PipeMessageType::SetManualScaling: + { + const auto body = reinterpret_cast(messageBuffer); + + printf("Received SetManualScaling with settings.from res (%d, %d), to (%d,%d)\n", body->oldX, body->oldY, body->newX, body->newY); + + Scaler::Settings(body->oldX, body->oldY, body->newX, body->newY); + + break; + } case ProtoPipe::PipeMessageType::SetXinputtoMKBkeys: { const auto body = reinterpret_cast(messageBuffer); @@ -681,12 +691,13 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) ScreenshotInput::ScanThread::scanYtype = 1; else if (body->yclick) ScreenshotInput::ScanThread::scanYtype = 2; - + break; } default: { fprintf(stderr, "Unrecongnised message type, exiting pipe\n"); + //MessageBoxA(NULL, "ukjent message", "quit pipe", MB_OK); goto endPipe; } } @@ -694,7 +705,7 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) } endPipe: - + MessageBoxA(NULL, "pipe ferdig", "rulle en", MB_OK); printf("End of pipe thread\n"); CloseHandle(pipe); return 0; @@ -702,10 +713,14 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) void StartPipeCommunication() { + evt = CreateEvent(nullptr, TRUE, FALSE, nullptr); + HANDLE hThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)PipeThread, GetModuleHandle(0), 0, 0); + WaitForSingleObject(evt, INFINITE); //waits on TranslateXtoMKB and input devices settings if (hThread != nullptr) CloseHandle(hThread); + } } diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.h b/src/ProtoInput/ProtoInputHooks/PipeCommunication.h index 7f046d3..276b503 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.h +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.h @@ -4,5 +4,7 @@ namespace Proto { void StartPipeCommunication(); +static HANDLE evt; + } diff --git a/src/ProtoInput/ProtoInputHooks/Scaler.cpp b/src/ProtoInput/ProtoInputHooks/Scaler.cpp index 4342f3e..d609238 100644 --- a/src/ProtoInput/ProtoInputHooks/Scaler.cpp +++ b/src/ProtoInput/ProtoInputHooks/Scaler.cpp @@ -21,7 +21,7 @@ namespace Proto WNDPROC g_OldWndProc = nullptr; POINT Scaler::getfactor(POINT pp){ - if (pp.x != 0 && pp.y != 0 && Enableornot && origwidth != 0 && scalewidth != 0) + if (pp.x != 0 && pp.y != 0 && Enableornot) { float scalex = float(origwidth) / float(scalewidth); float scaley = float(origheight) / float(scaleheight); @@ -106,10 +106,6 @@ namespace Proto if (Enableornot && !onlyonetimethis) { //MessageBoxA(NULL, "Ohyea", "Scaler enabled", MB_OK); - Proto::HwndSelector::UpdateMainHwnd(); - Proto::HwndSelector::UpdateWindowBounds(); - origwidth = Proto::HwndSelector::windowWidth; - origheight = Proto::HwndSelector::windowHeight; g_OldWndProc = (WNDPROC)SetWindowLongPtr( (HWND)Proto::HwndSelector::GetSelectedHwnd(), @@ -119,13 +115,34 @@ namespace Proto onlyonetimethis = true; //or else crash } } - void Scaler::Settings(bool enabled, int scaletoX, int scaletoY) + void Scaler::Uninstall() { - if (enabled) - { - Enableornot = true; - scalewidth = scaletoX; - scaleheight = scaletoY; + if (onlyonetimethis) + { + HWND hwnd = (HWND)Proto::HwndSelector::GetSelectedHwnd(); + + SetWindowLongPtr( + hwnd, + GWLP_WNDPROC, + (LONG_PTR)g_OldWndProc + ); + + onlyonetimethis = false; } } + + void Scaler::Settings(int oldX, int oldY, int newX, int newY) + { + Enableornot = true; + scalewidth = newX; + scaleheight = newY; + origwidth = oldX; + origheight = oldY; + if (scalewidth > 5 && scaleheight > 5 && origwidth > 5 && origheight > 5) + Enableornot = true; + else Enableornot = false; + if (Enableornot) + Scaler::Install(); + else Scaler::Uninstall(); + } } diff --git a/src/ProtoInput/ProtoInputHooks/Scaler.h b/src/ProtoInput/ProtoInputHooks/Scaler.h index 584ab32..3484c93 100644 --- a/src/ProtoInput/ProtoInputHooks/Scaler.h +++ b/src/ProtoInput/ProtoInputHooks/Scaler.h @@ -7,10 +7,14 @@ namespace Proto class Scaler { + private: + static void Install(); + static void Uninstall(); + public: static POINT getfactor(POINT pp); - static void Install(); - static void Settings(bool enabled, int scaletoX, int scaletoY); + + static void Settings(int oldX, int oldY, int newX, int newY); }; } diff --git a/src/ProtoInput/ProtoInputHooks/dllmain.cpp b/src/ProtoInput/ProtoInputHooks/dllmain.cpp index 0376553..f2dd30d 100644 --- a/src/ProtoInput/ProtoInputHooks/dllmain.cpp +++ b/src/ProtoInput/ProtoInputHooks/dllmain.cpp @@ -46,24 +46,20 @@ DWORD WINAPI StartThread(LPVOID lpParameter) std::cout << "Hooks DLL loaded\n"; - Proto::StartPipeCommunication(); - - Sleep(50); //let pipe finish - Proto::AddThreadToACL(GetCurrentThreadId()); - - Proto::RawInput::InitialiseRawInput(); - // Useful to add a pause if we need to attach a debugger - // MessageBoxW(NULL, L"Press OK to start", L"", MB_OK); Proto::HwndSelector::UpdateMainHwnd(); Proto::FocusMessageLoop::SetupThread(); Proto::FakeCursor::Initialise(dll_hModule); - + Proto::AddThreadToACL(GetCurrentThreadId()); + + Proto::StartPipeCommunication(); //must be placed before InitialiseRawInput + Sleep(50); + Proto::RawInput::InitialiseRawInput(); + // Useful to add a pause if we need to attach a debugger + // MessageBoxW(NULL, L"Press OK to start", L"", MB_OK); InitializeCriticalSection(&ScreenshotInput::ScanThread::critical); - Sleep(1000); - Proto::Scaler::Install(); //or not HANDLE hGuiThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)GuiThread, dll_hModule, CREATE_SUSPENDED, &Proto::GuiThreadID); @@ -74,7 +70,6 @@ DWORD WINAPI StartThread(LPVOID lpParameter) CloseHandle(hGuiThread); std::cout << "Reached end of startup thread\n"; - return 0; } diff --git a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h index 5f55780..0dfe28d 100644 --- a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h +++ b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h @@ -44,6 +44,7 @@ enum class PipeMessageType SetMoveWindowDontReposition, SetAdjustWindowRectSettings, SetDontWaitWindowBorder, + SetManualScaling, SetXinputtoMKBkeys, SetXinputtoMKBCFG }; @@ -267,6 +268,14 @@ struct PipeMessageSetDontWaitWindowBorder bool DontWaitWindowBorder; }; +struct PipeMessageSetManualScaling +{ + int oldX; + int oldY; + int newX; + int newY; +}; + struct PipeMessageSetXinputtoMKBkeys { int XinputtoMKBAkey; diff --git a/src/ProtoInput/ProtoInputLoader/Inject.cpp b/src/ProtoInput/ProtoInputLoader/Inject.cpp index d03b502..8807c2e 100644 --- a/src/ProtoInput/ProtoInputLoader/Inject.cpp +++ b/src/ProtoInput/ProtoInputLoader/Inject.cpp @@ -697,6 +697,25 @@ void SetDontWaitWindowBorder(ProtoInstanceHandle instanceHandle, bool enabled) ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetDontWaitWindowBorder, &message); } } +void SetManualScaling(ProtoInstanceHandle instanceHandle, int oldX, int oldY, int newX, int newY) +{ + if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) + { + auto& instance = find->second; + + WaitClientConnect(instance); + + ProtoPipe::PipeMessageSetManualScaling message + { + oldX, + oldY, + newX, + newY + }; + + ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetManualScaling, &message); + } +} void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright, int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, int XinputtoMKBsens, int XinputtoMKBsensmult) { if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) diff --git a/src/ProtoInput/ProtoInputLoader/include/protoloader.h b/src/ProtoInput/ProtoInputLoader/include/protoloader.h index a80572a..ddecb95 100644 --- a/src/ProtoInput/ProtoInputLoader/include/protoloader.h +++ b/src/ProtoInput/ProtoInputLoader/include/protoloader.h @@ -153,6 +153,8 @@ extern "C" __declspec(dllexport) void SetAdjustWindowRectSettings(ProtoInstanceH extern "C" __declspec(dllexport) void SetDontWaitWindowBorder(ProtoInstanceHandle instanceHandle, bool enabled); +extern "C" __declspec(dllexport) void SetManualScaling(ProtoInstanceHandle instanceHandle, int oldX, int oldY, int newX, int newY); + extern "C" __declspec(dllexport) void SetXinputtoMKBkeys(ProtoInstanceHandle instanceHandle, int XinputtoMKBAkey, int XinputtoMKBBkey, int XinputtoMKBXkey, int XinputtoMKBYkey, int XinputtoMKBRSkey, int XinputtoMKBLSkey, int XinputtoMKBrightkey, int XinputtoMKBleftkey, int XinputtoMKBupkey, int XinputtoMKBdownkey, int XinputtoMKBstickR, int XinputtoMKBstickL, int XinputtoMKBstickright, int XinputtoMKBstickleft, int XinputtoMKBstickup, int XinputtoMKBstickdown, int XinputtoMKBoption, int XinputtoMKBstart, int XinputtoMKBsens, int XinputtoMKBsensmult); extern "C" __declspec(dllexport) void SetXinputtoMKBCFG(ProtoInstanceHandle instanceHandle, bool stickinvert, bool scanoption, bool shoulderswap, bool astatic, bool aclick, bool amove, bool bstatic, bool bclick, bool bmove, bool xstatic, bool xclick, bool xmove, bool ystatic, bool yclick, bool ymove); \ No newline at end of file From 0bd05c7918227092d3861f9f3f1d17ae860f109b Mon Sep 17 00:00:00 2001 From: Messenils Date: Tue, 3 Mar 2026 22:55:24 +0100 Subject: [PATCH 15/20] gui thread startup moved to hotkey press. repaired a tunell error --- src/ProtoInput/ProtoInputHooks/Gui.cpp | 20 +- src/ProtoInput/ProtoInputHooks/Gui.h | 5 +- src/ProtoInput/ProtoInputHooks/GuiImpl.cpp | 7 + .../ProtoInputHooks/HwndSelector.cpp | 182 +++++------------- src/ProtoInput/ProtoInputHooks/dllmain.cpp | 16 +- .../ProtoInputHooks/pipeinclude/pipeinclude.h | 5 +- src/ProtoInput/ProtoInputLoader/Inject.cpp | 4 +- .../ProtoInputLoader/include/protoloader.h | 2 +- 8 files changed, 95 insertions(+), 146 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/Gui.cpp b/src/ProtoInput/ProtoInputHooks/Gui.cpp index da826a1..0882428 100644 --- a/src/ProtoInput/ProtoInputHooks/Gui.cpp +++ b/src/ProtoInput/ProtoInputHooks/Gui.cpp @@ -19,7 +19,6 @@ namespace Proto { - bool TranslateXisenabled = false; intptr_t ConsoleHwnd; static void HelpMarker(const char* desc) @@ -1029,5 +1028,24 @@ void RenderImgui() } ImGui::End(); } +DWORD WINAPI GuiThread(LPVOID lpParameter) +{ + std::cout << "Starting gui thread\n"; + + Proto::AddThreadToACL(GetCurrentThreadId()); + + Proto::ShowGuiImpl(); + + return 0; +} +void StartGUIThread() +{ + HANDLE hGuiThread = CreateThread(nullptr, 0, + (LPTHREAD_START_ROUTINE)GuiThread, Proto::hmodule, CREATE_SUSPENDED, &Proto::GuiThreadID); + ResumeThread(hGuiThread); + + if (hGuiThread != nullptr) + CloseHandle(hGuiThread); +} } diff --git a/src/ProtoInput/ProtoInputHooks/Gui.h b/src/ProtoInput/ProtoInputHooks/Gui.h index 2523157..4e1f0ae 100644 --- a/src/ProtoInput/ProtoInputHooks/Gui.h +++ b/src/ProtoInput/ProtoInputHooks/Gui.h @@ -8,11 +8,14 @@ namespace Proto extern unsigned long GuiThreadID; extern intptr_t ConsoleHwnd; extern HWND ProtoGuiHwnd; +extern HMODULE hmodule; + +void Start(); int ShowGuiImpl(); void RenderImgui(); - +void StartGUIThread(); void ToggleWindow(); void SetWindowVisible(bool visible); diff --git a/src/ProtoInput/ProtoInputHooks/GuiImpl.cpp b/src/ProtoInput/ProtoInputHooks/GuiImpl.cpp index 473fd36..ad50830 100644 --- a/src/ProtoInput/ProtoInputHooks/GuiImpl.cpp +++ b/src/ProtoInput/ProtoInputHooks/GuiImpl.cpp @@ -12,6 +12,7 @@ #include "FontData.h" #include "Cleanup.h" +bool guithreadstarted = false; //TODO: default to hidden constexpr bool defaultGuiToHidden = true; constexpr bool defaultConsoleToHidden = true; @@ -123,6 +124,12 @@ void Proto::ToggleWindow() void Proto::SetWindowVisible(bool visible) { + if (!guithreadstarted) + { + StartGUIThread(); + guithreadstarted = true; + Sleep(100); + } RawInput::rawInputState.guiOpened = visible; ShowWindow(ProtoGuiHwnd, visible ? SW_SHOW : SW_HIDE); } diff --git a/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp b/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp index e3af7a4..6ff3a54 100644 --- a/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp +++ b/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp @@ -2,165 +2,83 @@ #include "HwndSelector.h" #include #include "FakeCursor.h" -#include "TranslateXtoMKB.h" -#include -#pragma comment(lib, "dwmapi.lib") - namespace Proto { -intptr_t HwndSelector::selectedHwnd = 0; -int HwndSelector::windowWidth, HwndSelector::windowHeight; - -struct HandleData -{ - unsigned long pid; - HWND hwnd; -}; -int somonge = 0; -BOOL IsMainWindow(HWND hwnd) -{ - if (!IsWindow(hwnd)) return FALSE; + intptr_t HwndSelector::selectedHwnd = 0; + int HwndSelector::windowWidth, HwndSelector::windowHeight; - // Must be visible - if (!IsWindowVisible(hwnd)) return FALSE; - - // Must not be a child window - if (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD) return FALSE; + struct HandleData + { + unsigned long pid; + HWND hwnd; + }; - RECT rect; - int width; int height; - if (GetClientRect(hwnd, &rect)) + BOOL IsMainWindow(HWND handle) { - width = rect.right - rect.left; + // Is top level & visible & not one of ours + return + GetWindow(handle, GW_OWNER) == (HWND)0 && + IsWindowVisible(handle) && + handle != (HWND)Proto::ConsoleHwnd && + handle != Proto::ProtoGuiHwnd && + handle != FakeCursor::GetPointerWindow(); } - if (width < 400) - { - //MessageBoxA(NULL, "neikasvarte. DWM bredder", "oja", MB_OK); - HRESULT hr = DwmGetWindowAttribute( - (HWND)hwnd, - DWMWA_EXTENDED_FRAME_BOUNDS, - &rect, - sizeof(rect) - ); - - if (SUCCEEDED(hr)) { - width = rect.right - rect.left; - } - } - if (width < 400) + BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) { - return FALSE; - } + HandleData& data = *(HandleData*)lParam; - // Exclude your own windows - if (hwnd == (HWND)Proto::ConsoleHwnd) return FALSE; - if (hwnd == Proto::ProtoGuiHwnd) return FALSE; - if (hwnd == FakeCursor::GetPointerWindow()) return FALSE; + DWORD pid = 0; + GetWindowThreadProcessId(handle, &pid); - if (GetWindow(hwnd, GW_OWNER) == (HWND)0) - return TRUE; - return FALSE; -} + if (data.pid != pid || !IsMainWindow(handle)) + return TRUE; // Keep searching + data.hwnd = handle; -BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) -{ - HandleData& data = *(HandleData*)lParam; - - DWORD pid = 0; - GetWindowThreadProcessId(handle, &pid); - - if (data.pid != pid || !IsMainWindow(handle)) - return TRUE; // Keep searching - - data.hwnd = handle; - - return FALSE; -} - -void HwndSelector::UpdateMainHwnd(bool logOutput) -{ - // Go through all the top level windows, select the first that's visible & belongs to the process - - HandleData data { GetCurrentProcessId(), nullptr }; - EnumWindows(EnumWindowsCallback, (LPARAM)&data); - - auto hwnd = (intptr_t)data.hwnd; - - if (logOutput) + return FALSE; + } + + void HwndSelector::UpdateMainHwnd(bool logOutput) { + // Go through all the top level windows, select the first that's visible & belongs to the process + HandleData data{ GetCurrentProcessId(), nullptr }; + EnumWindows(EnumWindowsCallback, (LPARAM)&data); + const auto hwnd = (intptr_t)data.hwnd; - if (hwnd == 0) + if (logOutput) { - printf("Warning: UpdateMainHwnd didn't find a main window\n"); - + if (hwnd == 0) + printf("Warning: UpdateMainHwnd didn't find a main window\n"); + else + printf("UpdateMainHwnd found hwnd %d (0x%X)\n", hwnd, hwnd); } - else //EnumChildWindows(parent, EnumChildProc, (LPARAM)pid); - printf("UpdateMainHwnd found hwnd %d (0x%X)\n", hwnd, hwnd); - // else { - // MessageBoxA(NULL, "neikasvarte ingen bredde likevel. prøver childs", "oja", MB_OK); - // EnumChildWindows((HWND)hwnd, EnumWindowsCallback, (LPARAM)&data); - // hwnd = (intptr_t)data.hwnd; - // if (hwnd == 0) - // { - // printf("Warning: UpdateMainHwnd didn't find a main window even after searching children\n"); - // } - // else - // { - // MessageBoxA(NULL, "oja, fant noe allikevel.", "oja", MB_OK); - // printf("UpdateMainHwnd found child hwnd %d (0x%X)\n", hwnd, hwnd); - // } - // } + + if (data.hwnd != nullptr) + selectedHwnd = (intptr_t)data.hwnd; } - - if (data.hwnd != nullptr) - selectedHwnd = (intptr_t)data.hwnd; -} -void HwndSelector::UpdateWindowBounds() -{ - RECT rect; - if (GetClientRect((HWND)selectedHwnd, &rect)) + void HwndSelector::UpdateWindowBounds() { - if ((rect.right - rect.left) > 5) - { + RECT rect; + if (GetClientRect((HWND)selectedHwnd, &rect)) + { windowWidth = rect.right - rect.left; windowHeight = rect.bottom - rect.top; } - else { - HRESULT hr = DwmGetWindowAttribute( - (HWND)selectedHwnd, - DWMWA_EXTENDED_FRAME_BOUNDS, - &rect, - sizeof(rect) - ); - - if (SUCCEEDED(hr)) { - windowWidth = rect.right - rect.left; - windowHeight = rect.bottom - rect.top; - } - - } + else + fprintf(stderr, "GetClientRect failed in update main window bounds\n"); + } + void HwndSelector::SetSelectedHwnd(intptr_t set) + { + selectedHwnd = set; + UpdateWindowBounds(); } - else - fprintf(stderr, "GetClientRect failed in update main window bounds\n"); - if (windowWidth < 400) - windowWidth = 800; - if (windowHeight < 400) - windowHeight = 600; -} - -void HwndSelector::SetSelectedHwnd(intptr_t set) -{ - selectedHwnd = set; - UpdateWindowBounds(); -} -} +} \ No newline at end of file diff --git a/src/ProtoInput/ProtoInputHooks/dllmain.cpp b/src/ProtoInput/ProtoInputHooks/dllmain.cpp index f2dd30d..f53f91c 100644 --- a/src/ProtoInput/ProtoInputHooks/dllmain.cpp +++ b/src/ProtoInput/ProtoInputHooks/dllmain.cpp @@ -20,8 +20,7 @@ #include "TranslateXtoMKB.h" #include "ScanThread.h" - -HMODULE dll_hModule; +HMODULE Proto::hmodule; DWORD WINAPI GuiThread(LPVOID lpParameter) { @@ -36,6 +35,7 @@ DWORD WINAPI GuiThread(LPVOID lpParameter) DWORD WINAPI StartThread(LPVOID lpParameter) { + AllocConsole(); FILE* f = new FILE(); freopen_s(&f, "CONOUT$", "w", stdout); @@ -50,22 +50,22 @@ DWORD WINAPI StartThread(LPVOID lpParameter) Proto::FocusMessageLoop::SetupThread(); - Proto::FakeCursor::Initialise(dll_hModule); + Proto::FakeCursor::Initialise(Proto::hmodule); Proto::AddThreadToACL(GetCurrentThreadId()); - Proto::StartPipeCommunication(); //must be placed before InitialiseRawInput - Sleep(50); + Proto::StartPipeCommunication(); + InitializeCriticalSection(&ScreenshotInput::ScanThread::critical);//must be placed before InitialiseRawInput Proto::RawInput::InitialiseRawInput(); // Useful to add a pause if we need to attach a debugger // MessageBoxW(NULL, L"Press OK to start", L"", MB_OK); InitializeCriticalSection(&ScreenshotInput::ScanThread::critical); HANDLE hGuiThread = CreateThread(nullptr, 0, - (LPTHREAD_START_ROUTINE)GuiThread, dll_hModule, CREATE_SUSPENDED, &Proto::GuiThreadID); + (LPTHREAD_START_ROUTINE)GuiThread, Proto::hmodule, CREATE_SUSPENDED, &Proto::GuiThreadID); ResumeThread(hGuiThread); - + if (hGuiThread != nullptr) CloseHandle(hGuiThread); @@ -97,7 +97,7 @@ BOOL APIENTRY DllMain( HMODULE hModule, { case DLL_PROCESS_ATTACH: { - dll_hModule = hModule; + Proto::hmodule = hModule; HANDLE hThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)StartThread, hModule, 0, 0); diff --git a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h index 0dfe28d..dd0513e 100644 --- a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h +++ b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h @@ -88,6 +88,10 @@ struct PipeMessageWakeUpProcess { }; +//struct PipeMessageSetNoGUI +//{ +// bool SetNoGUI; +//}; struct PipeMesasgeUpdateMainWindowHandle { uint64_t hwnd = 0; @@ -177,7 +181,6 @@ struct PipeMessageSetSetWindowPosSettings int posy; int width; int height; - bool scale; }; struct PipeMessageSetSetWindowPosDontResize diff --git a/src/ProtoInput/ProtoInputLoader/Inject.cpp b/src/ProtoInput/ProtoInputLoader/Inject.cpp index 8807c2e..8711801 100644 --- a/src/ProtoInput/ProtoInputLoader/Inject.cpp +++ b/src/ProtoInput/ProtoInputLoader/Inject.cpp @@ -396,7 +396,7 @@ void DinputHookAlsoHooksGetDeviceState(ProtoInstanceHandle instanceHandle, bool } } -void SetSetWindowPosSettings(ProtoInstanceHandle instanceHandle, int posx, int posy, int width, int height, bool scale) +void SetSetWindowPosSettings(ProtoInstanceHandle instanceHandle, int posx, int posy, int width, int height) { if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) { @@ -406,7 +406,7 @@ void SetSetWindowPosSettings(ProtoInstanceHandle instanceHandle, int posx, int p ProtoPipe::PipeMessageSetSetWindowPosSettings message { - posx, posy, width, height, scale + posx, posy, width, height }; ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::SetSetWindowPosSettings, &message); diff --git a/src/ProtoInput/ProtoInputLoader/include/protoloader.h b/src/ProtoInput/ProtoInputLoader/include/protoloader.h index ddecb95..3c3e1ea 100644 --- a/src/ProtoInput/ProtoInputLoader/include/protoloader.h +++ b/src/ProtoInput/ProtoInputLoader/include/protoloader.h @@ -119,7 +119,7 @@ extern "C" __declspec(dllexport) void SetDinputDeviceGUID(ProtoInstanceHandle in // This MUST be called before calling InstallHook on the Dinput order hook extern "C" __declspec(dllexport) void DinputHookAlsoHooksGetDeviceState(ProtoInstanceHandle instanceHandle, bool enable); -extern "C" __declspec(dllexport) void SetSetWindowPosSettings(ProtoInstanceHandle instanceHandle, int posx, int posy, int width, int height, bool scale); +extern "C" __declspec(dllexport) void SetSetWindowPosSettings(ProtoInstanceHandle instanceHandle, int posx, int posy, int width, int height); extern "C" __declspec(dllexport) void SetSetWindowPosDontResize(ProtoInstanceHandle instanceHandle, bool enabled); From d977768481d88e7aebc33c3c8a77aa27fb925737 Mon Sep 17 00:00:00 2001 From: Messenils Date: Wed, 4 Mar 2026 12:22:20 +0100 Subject: [PATCH 16/20] i forget to delete the guithread in dllmain. now fixed, now the thread is not started before necessary --- src/ProtoInput/ProtoInputHooks/dllmain.cpp | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/dllmain.cpp b/src/ProtoInput/ProtoInputHooks/dllmain.cpp index f53f91c..d588a95 100644 --- a/src/ProtoInput/ProtoInputHooks/dllmain.cpp +++ b/src/ProtoInput/ProtoInputHooks/dllmain.cpp @@ -22,17 +22,6 @@ HMODULE Proto::hmodule; -DWORD WINAPI GuiThread(LPVOID lpParameter) -{ - std::cout << "Starting gui thread\n"; - - Proto::AddThreadToACL(GetCurrentThreadId()); - - Proto::ShowGuiImpl(); - - return 0; -} - DWORD WINAPI StartThread(LPVOID lpParameter) { @@ -58,17 +47,9 @@ DWORD WINAPI StartThread(LPVOID lpParameter) InitializeCriticalSection(&ScreenshotInput::ScanThread::critical);//must be placed before InitialiseRawInput Proto::RawInput::InitialiseRawInput(); // Useful to add a pause if we need to attach a debugger - // MessageBoxW(NULL, L"Press OK to start", L"", MB_OK); + InitializeCriticalSection(&ScreenshotInput::ScanThread::critical); - HANDLE hGuiThread = CreateThread(nullptr, 0, - (LPTHREAD_START_ROUTINE)GuiThread, Proto::hmodule, CREATE_SUSPENDED, &Proto::GuiThreadID); - - ResumeThread(hGuiThread); - - if (hGuiThread != nullptr) - CloseHandle(hGuiThread); - std::cout << "Reached end of startup thread\n"; return 0; } From 7721f97fb8cc23e33a976eabfb12e356da7dff62 Mon Sep 17 00:00:00 2001 From: Messenils Date: Sun, 22 Mar 2026 14:30:41 +0100 Subject: [PATCH 17/20] Added sens adjust hotkey for TranslateX. Start button + Up/Down -> browse setting to adjust. Start button +Left/Right change selected setting --- src/ProtoInput/ProtoInputHooks/FakeCursor.cpp | 34 ++++- .../ProtoInputHooks/HwndSelector.cpp | 9 +- src/ProtoInput/ProtoInputHooks/HwndSelector.h | 1 + .../ProtoInputHooks/PipeCommunication.cpp | 1 + .../ProtoInputHooks/TranslateXtoMKB.cpp | 128 ++++++++++++------ src/ProtoInput/ProtoInputHooks/dllmain.cpp | 5 +- 6 files changed, 128 insertions(+), 50 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp index 8e534ea..493bd37 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp @@ -158,6 +158,26 @@ void FakeCursor::DrawMessage(HDC hdc, HWND window, HBRUSH Brush, int message) TextOutW(hdc, here.x + 20, here.y + 20, TEXT("LOCK TOGGLED!"), 13); //14 messageshown = true; } + if (message == 5) { + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + TextOutW(hdc, here.x + 20, here.y + 20, TEXT("Window top!"), 11); //14 + messageshown = true; + } + if (message == 6) { + wchar_t buffer[25]; + swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), L"Sens Flat Adjust! (%d)", ScreenshotInput::TranslateXtoMKB::Sens); + TextOutW(hdc, here.x + 20, here.y + 20, buffer, (int)wcslen(buffer)); + TextOutW(hdc, here.x + 20, here.y + 40, TEXT("Press Up or Down!"), 17); //14 + messageshown = true; + } + if (message == 7) { + // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); + wchar_t buffer[25]; + swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), L"Sens Curve Adjust! (%d)", ScreenshotInput::TranslateXtoMKB::Sensmult); + TextOutW(hdc, here.x + 20, here.y + 20, buffer, (int)wcslen(buffer)); + TextOutW(hdc, here.x + 20, here.y + 40, TEXT("Press Up or Down!"), 17); + messageshown = true; + } if (ScreenshotInput::TranslateXtoMKB::SaveBmps) { // DrawGreenTriangle(hdc, here.x + 50, here.y + 50); TextOutW(hdc, here.x + 20, here.y + 0, TEXT("BMP SAVE MODE!"), 14); //14 @@ -278,7 +298,7 @@ void FakeCursor::DrawFoundSpots(HDC hdc, POINT spotA, POINT spotB, POINT spotX, OldTestpos = testpos; } -void FakeCursor::DrawPointsandMessages() +void FakeCursor::DrawPointsandMessages() //only on Xtranslate { if (ScreenshotInput::ScanThread::scanoption) { @@ -440,7 +460,7 @@ DWORD WINAPI FakeCursorDrawLoopThread(LPVOID lpParameter) void FakeCursor::StartDrawLoopInternal() { - int tick = 0; + int tick = 1; if (Proto::RawInput::TranslateXinputtoMKB) ScreenshotInput::TranslateXtoMKB::Initialize(GetModuleHandle(NULL)); @@ -456,8 +476,10 @@ void FakeCursor::StartDrawLoopInternal() //TODO: is this ok? (might eat cpu) Sleep(drawingEnabled ? 12 : 500); + tick = (tick + 1) % 200; } - else { + else + { ScreenshotInput::TranslateXtoMKB::ThreadFunction(); if (ScreenshotInput::TranslateXtoMKB::RefreshPoint > 0) { @@ -469,16 +491,14 @@ void FakeCursor::StartDrawLoopInternal() DrawCursor(); ScreenshotInput::TranslateXtoMKB::RefreshWindow--; } + tick = (tick + 1) % 2000; //guess this run about 10-12 times faster } - tick = (tick + 1) % 200; - if (tick == 0 && pointerWindow != GetForegroundWindow()) + if (tick == 0) { // Nucleus can put the game window above the pointer without this SetWindowPos(pointerWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE); } - - } } diff --git a/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp b/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp index 6ff3a54..c94e8e8 100644 --- a/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp +++ b/src/ProtoInput/ProtoInputHooks/HwndSelector.cpp @@ -10,6 +10,8 @@ namespace Proto intptr_t HwndSelector::selectedHwnd = 0; int HwndSelector::windowWidth, HwndSelector::windowHeight; + bool HwndSelector::RemoteHwndEnabled = false; + struct HandleData { unsigned long pid; @@ -45,7 +47,12 @@ namespace Proto void HwndSelector::UpdateMainHwnd(bool logOutput) { // Go through all the top level windows, select the first that's visible & belongs to the process - + if (HwndSelector::RemoteHwndEnabled) + { + if (logOutput) + printf("Remote hwnd enabled, skipping search for main window\n"); + return; + } HandleData data{ GetCurrentProcessId(), nullptr }; EnumWindows(EnumWindowsCallback, (LPARAM)&data); diff --git a/src/ProtoInput/ProtoInputHooks/HwndSelector.h b/src/ProtoInput/ProtoInputHooks/HwndSelector.h index 70f42a2..73f0a28 100644 --- a/src/ProtoInput/ProtoInputHooks/HwndSelector.h +++ b/src/ProtoInput/ProtoInputHooks/HwndSelector.h @@ -16,6 +16,7 @@ class HwndSelector static void SetSelectedHwnd(intptr_t set); static void UpdateMainHwnd(bool logOutput = true); static void UpdateWindowBounds(); + static bool RemoteHwndEnabled; }; } diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index 4fcadc4..7ad86dd 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -256,6 +256,7 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) printf("Received message to set main window handle to hwnd %lld (0x%llX)\n", body->hwnd, body->hwnd); // HwndSelector::selectedHwnd = body->hwnd; HwndSelector::SetSelectedHwnd((intptr_t)body->hwnd); + HwndSelector::RemoteHwndEnabled = true; } break; diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp index 9e162e7..16f7a14 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -481,18 +481,18 @@ namespace ScreenshotInput bool rightPressed = IsTriggerPressed(state.Gamepad.bRightTrigger); if (TranslateXtoMKB::lefthanded == 1) { - Xaxis = state.Gamepad.sThumbRX; - Yaxis = state.Gamepad.sThumbRY; - scrollXaxis = state.Gamepad.sThumbLX; - scrollYaxis = state.Gamepad.sThumbLY; - } - else - { Xaxis = state.Gamepad.sThumbLX; Yaxis = state.Gamepad.sThumbLY; scrollXaxis = state.Gamepad.sThumbRX; scrollYaxis = state.Gamepad.sThumbRY; } + else + { + Xaxis = state.Gamepad.sThumbRX; + Yaxis = state.Gamepad.sThumbRY; + scrollXaxis = state.Gamepad.sThumbLX; + scrollYaxis = state.Gamepad.sThumbLY; + } delta = CalculateUltimateCursorMove( Xaxis, Yaxis, @@ -789,38 +789,7 @@ namespace ScreenshotInput } - if (oldup) - { - if (buttons & XINPUT_GAMEPAD_DPAD_UP) - { - } - else { - oldup = false; - ButtonStateImpulse(TranslateXtoMKB::upmapping, false, 99);//release - } - } - else if (buttons & XINPUT_GAMEPAD_DPAD_UP) - { - oldup = true; - ButtonStateImpulse(TranslateXtoMKB::upmapping, true, 99);//down - } - - - if (olddown) - { - if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) - { - } - else { - olddown = false; - ButtonStateImpulse(TranslateXtoMKB::downmapping, false, 99);//release - } - } - else if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) - { - olddown = true; - ButtonStateImpulse(TranslateXtoMKB::downmapping, true, 99);//down - } + if (oldstartoptions) //toggle fake cursor { @@ -844,8 +813,12 @@ namespace ScreenshotInput { if (buttons & XINPUT_GAMEPAD_START) { + Proto::FakeCursor::Showmessage = 7; //adjust sensitivity + TranslateXtoMKB::RefreshPoint = 1; } else { + Proto::FakeCursor::Showmessage = 0; //adjust sensitivity + TranslateXtoMKB::RefreshPoint = 1; oldstart = false; ButtonStateImpulse(TranslateXtoMKB::startmapping, false, 99);//release } @@ -854,14 +827,19 @@ namespace ScreenshotInput { oldstart = true; ButtonStateImpulse(TranslateXtoMKB::startmapping, true, 99);//down + } if (oldoptions) { if (buttons & XINPUT_GAMEPAD_BACK) { + Proto::FakeCursor::Showmessage = 6; //adjust sensitivity + TranslateXtoMKB::RefreshPoint = 1; } else { + Proto::FakeCursor::Showmessage = 0; //adjust sensitivity + TranslateXtoMKB::RefreshPoint = 1; oldoptions = false; ButtonStateImpulse(TranslateXtoMKB::optionmapping, false, 99);//release } @@ -871,7 +849,75 @@ namespace ScreenshotInput oldoptions = true; ButtonStateImpulse(TranslateXtoMKB::optionmapping, true, 99);//down } + if (oldup) + { + if (buttons & XINPUT_GAMEPAD_DPAD_UP) + { + } + else { + if (Proto::FakeCursor::Showmessage == 6) + { + if (TranslateXtoMKB::Sens < 50) + { + TranslateXtoMKB::Sens++; + Proto::FakeCursor::Showmessage = 0; + ScreenshotInput::TranslateXtoMKB::RefreshPoint = 1; + } + } + if (Proto::FakeCursor::Showmessage == 7) + { + if (TranslateXtoMKB::Sensmult < 50) + { + TranslateXtoMKB::Sensmult++; + Proto::FakeCursor::Showmessage = 0; + ScreenshotInput::TranslateXtoMKB::RefreshPoint = 1; + } + } + oldup = false; + ButtonStateImpulse(TranslateXtoMKB::upmapping, false, 99);//release + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_UP) + { + oldup = true; + ButtonStateImpulse(TranslateXtoMKB::upmapping, true, 99);//down + } + + if (olddown) + { + if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) + { + } + else + { + if (Proto::FakeCursor::Showmessage == 6) + { + if (TranslateXtoMKB::Sens > 1) + { + TranslateXtoMKB::Sens--; + Proto::FakeCursor::Showmessage = 0; + ScreenshotInput::TranslateXtoMKB::RefreshPoint = 1; + } + } + if (Proto::FakeCursor::Showmessage == 7) + { + if (TranslateXtoMKB::Sensmult > 1) + { + TranslateXtoMKB::Sensmult--; + Proto::FakeCursor::Showmessage = 0; + ScreenshotInput::TranslateXtoMKB::RefreshPoint = 1; + } + } + olddown = false; + ButtonStateImpulse(TranslateXtoMKB::downmapping, false, 99);//release + } + } + else if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) + { + olddown = true; + ButtonStateImpulse(TranslateXtoMKB::downmapping, true, 99);//down + } } //if mode above 0 } //if controller else { //no controller @@ -889,8 +935,8 @@ namespace ScreenshotInput tick = 0; } - if (Proto::FakeCursor::Showmessage != 0) { //drawing messages or something - if (counter < 500) { + if (Proto::FakeCursor::Showmessage != 0 && Proto::FakeCursor::Showmessage != 6 && Proto::FakeCursor::Showmessage != 7) { //drawing messages or something + if (counter < 1000) { counter++; } else { diff --git a/src/ProtoInput/ProtoInputHooks/dllmain.cpp b/src/ProtoInput/ProtoInputHooks/dllmain.cpp index d588a95..344148b 100644 --- a/src/ProtoInput/ProtoInputHooks/dllmain.cpp +++ b/src/ProtoInput/ProtoInputHooks/dllmain.cpp @@ -35,7 +35,7 @@ DWORD WINAPI StartThread(LPVOID lpParameter) std::cout << "Hooks DLL loaded\n"; - Proto::HwndSelector::UpdateMainHwnd(); + Proto::FocusMessageLoop::SetupThread(); @@ -44,6 +44,9 @@ DWORD WINAPI StartThread(LPVOID lpParameter) Proto::AddThreadToACL(GetCurrentThreadId()); Proto::StartPipeCommunication(); + + Proto::HwndSelector::UpdateMainHwnd(); + InitializeCriticalSection(&ScreenshotInput::ScanThread::critical);//must be placed before InitialiseRawInput Proto::RawInput::InitialiseRawInput(); // Useful to add a pause if we need to attach a debugger From 5c2f885e0cb3dd4cda84351acfdf2c9040f5cf41 Mon Sep 17 00:00:00 2001 From: Messenils Date: Fri, 27 Mar 2026 23:23:51 +0100 Subject: [PATCH 18/20] added suboption TranslateKBMtoXinput within Xinputhook + added 2 seconds delay on settings ingame popup for the TranslateXtoKBM so start and back can be mapped without rendering settings unintentionally --- .../ProtoInputHooks/FakeMouseKeyboard.h | 1 + src/ProtoInput/ProtoInputHooks/Gui.cpp | 40 +- .../ProtoInputHooks/PipeCommunication.cpp | 14 +- .../ProtoInputHooks.vcxproj.filters | 3 + src/ProtoInput/ProtoInputHooks/RawInput.cpp | 11 +- src/ProtoInput/ProtoInputHooks/RawInput.h | 1 + .../ProtoInputHooks/TranslateXtoMKB.cpp | 32 +- src/ProtoInput/ProtoInputHooks/XinputHook.cpp | 391 +++++++++++++++++- src/ProtoInput/ProtoInputHooks/XinputHook.h | 2 +- .../ProtoInputHooks/pipeinclude/pipeinclude.h | 6 + src/ProtoInput/ProtoInputHost/Gui.cpp | 3 + src/ProtoInput/ProtoInputHost/Profiles.h | 2 + src/ProtoInput/ProtoInputLoader/Inject.cpp | 16 + .../ProtoInputLoader/include/protoloader.h | 2 + 14 files changed, 475 insertions(+), 49 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/FakeMouseKeyboard.h b/src/ProtoInput/ProtoInputHooks/FakeMouseKeyboard.h index f83313c..e8cb79d 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeMouseKeyboard.h +++ b/src/ProtoInput/ProtoInputHooks/FakeMouseKeyboard.h @@ -42,6 +42,7 @@ class FakeMouseKeyboard public: static const FakeMouseState& GetMouseState() { return mouseState; } + //static const FakeKeyboardState& GetKeyBoardState() { return keyboardState; } static void AddMouseDelta(int dx, int dy); static void SetMousePos(int x, int y); diff --git a/src/ProtoInput/ProtoInputHooks/Gui.cpp b/src/ProtoInput/ProtoInputHooks/Gui.cpp index 0882428..552cf30 100644 --- a/src/ProtoInput/ProtoInputHooks/Gui.cpp +++ b/src/ProtoInput/ProtoInputHooks/Gui.cpp @@ -16,6 +16,7 @@ #include "TranslateXtoMKB.h" #include "ScanThread.h" #include "GtoMnK_RawInput.h" +#include "XinputHook.h" namespace Proto { @@ -669,22 +670,25 @@ void XTranslateMenu() ImGui::Checkbox("Lefthanded Stick. moves mouse with left stick and button map on right stick. or opposite if disabled", &ScreenshotInput::TranslateXtoMKB::lefthanded); // ImGui::Separator(); ImGui::Separator(); - ImGui::Checkbox("Shoulder Swap BMPs", &ScreenshotInput::ScanThread::ShoulderNextBMP); // - ImGui::Separator(); - ImGui::Text("Input actions for Scanoption. 0 is move+click. 1 is only move. 2 is only click"); - ImGui::SliderInt("A coordinate", (int*)&ScreenshotInput::ScanThread::scanAtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); - ImGui::SliderInt("B coordinate", (int*)&ScreenshotInput::ScanThread::scanBtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); - ImGui::SliderInt("X coordinate", (int*)&ScreenshotInput::ScanThread::scanXtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); - ImGui::SliderInt("Y coordinate", (int*)&ScreenshotInput::ScanThread::scanYtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); - ImGui::Separator(); - ImGui::Text("Save BMP mode. buttons XYAB will save a bmp on press at fake cursor coordinate when enabled. This option also force ScanOption to deactivate"); - ImGui::Checkbox("Save BMP mode:", &ScreenshotInput::TranslateXtoMKB::SaveBmps); // - ImGui::Separator(); - ImGui::Text("Scanoption will need a restart to discover new bmps."); - ImGui::Checkbox("ScanOption:", &ScreenshotInput::ScanThread::scanoption); // - ImGui::Separator(); - if (!ScreenshotInput::ScanThread::scanoption) - ScreenshotInput::ScanThread::scanloop = false; + if (RawInput::TranslateXinputtoMKB) + { + ImGui::Checkbox("Shoulder Swap BMPs", &ScreenshotInput::ScanThread::ShoulderNextBMP); // + ImGui::Separator(); + ImGui::Text("Input actions for Scanoption. 0 is move+click. 1 is only move. 2 is only click"); + ImGui::SliderInt("A coordinate", (int*)&ScreenshotInput::ScanThread::scanAtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::SliderInt("B coordinate", (int*)&ScreenshotInput::ScanThread::scanBtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::SliderInt("X coordinate", (int*)&ScreenshotInput::ScanThread::scanXtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::SliderInt("Y coordinate", (int*)&ScreenshotInput::ScanThread::scanYtype, 0, 2, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::Separator(); + ImGui::Text("Save BMP mode. buttons XYAB will save a bmp on press at fake cursor coordinate when enabled. This option also force ScanOption to deactivate"); + ImGui::Checkbox("Save BMP mode:", &ScreenshotInput::TranslateXtoMKB::SaveBmps); // + ImGui::Separator(); + ImGui::Text("Scanoption will need a restart to discover new bmps."); + ImGui::Checkbox("ScanOption:", &ScreenshotInput::ScanThread::scanoption); // + ImGui::Separator(); + if (!ScreenshotInput::ScanThread::scanoption) + ScreenshotInput::ScanThread::scanloop = false; + } } void HooksMenu() { @@ -933,9 +937,9 @@ void RenderImgui() HooksMenu(); ImGui::EndTabItem(); } - if (RawInput::TranslateXinputtoMKB) + if (RawInput::TranslateXinputtoMKB || XinputHook::TranslateMKBtoXinput) { - if (ImGui::BeginTabItem("TranslateXtoMKB options")) + if (ImGui::BeginTabItem("Translation options")) { XTranslateMenu(); ImGui::EndTabItem(); diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index 7ad86dd..0ade911 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -410,6 +410,17 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) break; } + case ProtoPipe::PipeMessageType::TranslateMKBtoXinput: + { + const auto body = reinterpret_cast(messageBuffer); + + printf("Received set translate MKB to Xinput. also extended mousestate bounds. remember Xinputhook also%d\n", body->TranslateMKBtoXinput); + + XinputHook::TranslateMKBtoXinput = body->TranslateMKBtoXinput; + FakeMouseKeyboard::SetIgnoreMouseBounds(true); + + break; + } case ProtoPipe::PipeMessageType::SetDinputDeviceGuid: { const auto body = reinterpret_cast(messageBuffer); @@ -494,7 +505,8 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) FakeMouseKeyboard::SetIgnoreMouseBounds(body->allowOutOfBounds); FakeMouseKeyboard::SetExtendMouseBounds(body->extendBounds); - + if(XinputHook::TranslateMKBtoXinput) //override + FakeMouseKeyboard::SetIgnoreMouseBounds(true); break; } case ProtoPipe::PipeMessageType::SetToggleCursorVisibilityShortcut: diff --git a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters index 97aa740..4e3f5f3 100644 --- a/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters +++ b/src/ProtoInput/ProtoInputHooks/ProtoInputHooks.vcxproj.filters @@ -31,6 +31,9 @@ {a0d1a945-2bce-40dd-88b8-54724cf1b678} + + {2852b253-94b1-4a59-954e-55b28a17010b} + diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.cpp b/src/ProtoInput/ProtoInputHooks/RawInput.cpp index 69c5a6d..12aacdb 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.cpp +++ b/src/ProtoInput/ProtoInputHooks/RawInput.cpp @@ -16,6 +16,7 @@ #include "KeyboardButtonFilter.h" #include "MessageFilterHook.h" #include "TranslateXtoMKB.h" +#include "XinputHook.h" namespace Proto { @@ -213,7 +214,9 @@ void RawInput::ProcessMouseInput(const RAWMOUSE& data, HANDLE deviceHandle) FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_XBUTTON2, true); if ((data.usButtonFlags & RI_MOUSE_BUTTON_5_UP) != 0) FakeMouseKeyboard::ReceivedKeyPressOrRelease(VK_XBUTTON2, false); - RawInput::SendInputMessages(data); + + if (!XinputHook::TranslateMKBtoXinput) + RawInput::SendInputMessages(data); } void RawInput::SendKeyMessage(const RAWKEYBOARD& data, bool pressed) @@ -261,7 +264,8 @@ void RawInput::ProcessKeyboardInput(const RAWKEYBOARD& data, HANDLE deviceHandle const bool released = (data.Flags & RI_KEY_BREAK) != 0; const bool pressed = !released; - RawInput::SendKeyMessage(data, pressed); + if (!XinputHook::TranslateMKBtoXinput) + RawInput::SendKeyMessage(data, pressed); FakeMouseKeyboard::ReceivedKeyPressOrRelease(data.VKey, pressed); } @@ -403,7 +407,8 @@ void RawInput::ProcessRawInput(HRAWINPUT rawInputHandle, bool inForeground, cons inputBuffer[inputBufferCounter] = rawinput; const LPARAM x = (inputBufferCounter) | 0xAB000000; - PostMessageW(hwnd, WM_INPUT, RIM_INPUT, x); + if (!XinputHook::TranslateMKBtoXinput) + PostMessageW(hwnd, WM_INPUT, RIM_INPUT, x); } } } diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.h b/src/ProtoInput/ProtoInputHooks/RawInput.h index 07c2d00..ded1127 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.h +++ b/src/ProtoInput/ProtoInputHooks/RawInput.h @@ -53,6 +53,7 @@ class RawInput static HWND rawInputHwnd; static bool forwardRawInput; static bool TranslateXinputtoMKB; + static bool TranslateMKBtoXinput; // Passes input from all devices to the game. Proto Input doesn't process anything static bool rawInputBypass; diff --git a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp index 16f7a14..f5c49c9 100644 --- a/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp +++ b/src/ProtoInput/ProtoInputHooks/TranslateXtoMKB.cpp @@ -51,6 +51,11 @@ namespace ScreenshotInput bool TranslateXtoMKB::rawinputhook; //registerrawinputhook bool TranslateXtoMKB::registerrawinputhook; //registerrawinputhook + + int TranslateXtoMKB::stickrightmapping; + int TranslateXtoMKB::stickleftmapping; + int TranslateXtoMKB::stickupmapping; + int TranslateXtoMKB::stickdownmapping; int TranslateXtoMKB::Amapping; int TranslateXtoMKB::Bmapping; int TranslateXtoMKB::Xmapping; @@ -63,10 +68,6 @@ namespace ScreenshotInput int TranslateXtoMKB::downmapping; int TranslateXtoMKB::stickRpressmapping; int TranslateXtoMKB::stickLpressmapping; - int TranslateXtoMKB::stickrightmapping; - int TranslateXtoMKB::stickleftmapping; - int TranslateXtoMKB::stickupmapping; - int TranslateXtoMKB::stickdownmapping; int TranslateXtoMKB::optionmapping; int TranslateXtoMKB::startmapping; bool TranslateXtoMKB::lefthanded; @@ -89,7 +90,7 @@ namespace ScreenshotInput const float curve_exponent = 5.00f; // The exponential portion of the curve (1.0 to 10.0) //float sensitivity = 9.00f; // Base sensitivity / max speed (1.0 to 30.0) //float accel_multiplier = 1.90f; // Look Acceleration Multiplier (1.0 to 3.0) - + int startbuttontimer, backbuttontimer; ///////////////// bool leftPressedold = false; @@ -811,10 +812,16 @@ namespace ScreenshotInput } if (oldstart) { + if (buttons & XINPUT_GAMEPAD_START) { - Proto::FakeCursor::Showmessage = 7; //adjust sensitivity - TranslateXtoMKB::RefreshPoint = 1; + if (startbuttontimer < 1500) //delay setting menu. hold button to show + startbuttontimer++; + else + { + Proto::FakeCursor::Showmessage = 7; //adjust sensitivity + TranslateXtoMKB::RefreshPoint = 1; + } } else { Proto::FakeCursor::Showmessage = 0; //adjust sensitivity @@ -825,6 +832,7 @@ namespace ScreenshotInput } else if (buttons & XINPUT_GAMEPAD_START) { + startbuttontimer = 0; oldstart = true; ButtonStateImpulse(TranslateXtoMKB::startmapping, true, 99);//down @@ -834,8 +842,13 @@ namespace ScreenshotInput { if (buttons & XINPUT_GAMEPAD_BACK) { - Proto::FakeCursor::Showmessage = 6; //adjust sensitivity - TranslateXtoMKB::RefreshPoint = 1; + if (backbuttontimer < 1500) + backbuttontimer ++; + else + { + Proto::FakeCursor::Showmessage = 6; //adjust sensitivity + TranslateXtoMKB::RefreshPoint = 1; + } } else { Proto::FakeCursor::Showmessage = 0; //adjust sensitivity @@ -846,6 +859,7 @@ namespace ScreenshotInput } else if (buttons & XINPUT_GAMEPAD_BACK) { + backbuttontimer = 0; oldoptions = true; ButtonStateImpulse(TranslateXtoMKB::optionmapping, true, 99);//down } diff --git a/src/ProtoInput/ProtoInputHooks/XinputHook.cpp b/src/ProtoInput/ProtoInputHooks/XinputHook.cpp index 5764340..debc6fe 100644 --- a/src/ProtoInput/ProtoInputHooks/XinputHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/XinputHook.cpp @@ -5,6 +5,8 @@ #include "Gui.h" #include #include "OpenXinputWrapper.h" +#include "FakeMouseKeyboard.h" +#include "TranslateXtoMKB.h" namespace Proto @@ -14,6 +16,8 @@ constexpr LONG DINPUT_RANGE_MAX = 32767; constexpr LONG DINPUT_RANGE_MIN = -32768; bool XinputHook::useDinput = false; bool XinputHook::useOpenXinput = false; +bool XinputHook::TranslateMKBtoXinput = false; + IDirectInputDevice8W* dinputDevice = nullptr; GUID dinputDeviceGuid{}; std::wstring dinputDeviceName{}; @@ -72,36 +76,330 @@ inline std::pair GetTargetControllerIndex(DWORD dwUserIndex) return { false, 0 }; } -inline DWORD WINAPI XInputGetState_Inline(DWORD dwUserIndex, XINPUT_STATE* pState, bool extended) +bool IsKeyPressed(int Vkey) { + return FakeMouseKeyboard::IsKeyStatePressed(Vkey); +} +POINT oldmousepos; +POINT deltaL; +POINT deltaR; +POINT olddeltaL; +POINT olddeltaR; +int Akey = 65; +int Dkey = 68; +int Wkey = 87; +int Skey = 83; +bool oldA, oldB, oldX, oldY, oldtriggerleft, oldtriggerright, oldLS, oldRS, oldup, olddown, oldleft, oldright; +bool oldstart, oldback, oldstickRB, oldstickLB; +bool firstcall = false; +DWORD fakedwpacketnumber = 0; +bool changed; +SHORT LaxisX, LaxisY, RaxisX, RaxisY; +inline DWORD WINAPI XInputfromkbm(DWORD dwUserIndex, XINPUT_STATE* pState, bool extended) +{ + if (extended) getStateExCounter++; else getStateCounter++; + //ZeroMemory(pState, sizeof(pState)); + pState->Gamepad.wButtons = 0; + //kbmgamepad.wButtons = 0; + const auto& mousestate = FakeMouseKeyboard::GetMouseState(); + POINT Pos = { mousestate.x, mousestate.y }; - auto [ connected, targetControllerIndex ] = GetTargetControllerIndex(dwUserIndex); - - if (!connected) - return ERROR_DEVICE_NOT_CONNECTED; - if (XinputHook::useOpenXinput) + deltaL.x = (Pos.x - oldmousepos.x) * (2 * ScreenshotInput::TranslateXtoMKB::Sens); + deltaL.y = (Pos.y - oldmousepos.y) * (2 * ScreenshotInput::TranslateXtoMKB::Sens); + + oldmousepos.x = Pos.x; + oldmousepos.y = Pos.y; + + if (!firstcall) { - return OpenXinput::ProtoOpenXinputGetState(targetControllerIndex, pState, extended); + pState->Gamepad.sThumbLY = 0; + pState->Gamepad.sThumbLX = 0; + pState->Gamepad.sThumbRY = 0; + pState->Gamepad.sThumbRX = 0; + oldmousepos.x = 0; + oldmousepos.y = 0; + firstcall = true; } - if (!XinputHook::GetUseDinput()) + + if (LaxisX + deltaL.x < -32767) + LaxisX = -32767; + else if (LaxisX + deltaL.x > 32767) + LaxisX = 32767; + else LaxisX += deltaL.x; + if (LaxisY + deltaL.y < -32767) + deltaL.y = -32767; + else if (LaxisY + deltaL.y > 32767) + LaxisY = 32767; + else LaxisY += deltaL.y; + + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickrightmapping)) { - if (extended && XInputGetStateExPtr != nullptr) + //double time to zero + if (deltaR.x < 0) + deltaR.x = deltaR.x + (5 * ScreenshotInput::TranslateXtoMKB::Sens); + + if (deltaR.x < 32767 - (5 * ScreenshotInput::TranslateXtoMKB::Sens)) + deltaR.x = deltaR.x + (5 * ScreenshotInput::TranslateXtoMKB::Sens); + } + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickleftmapping)) + { + if (deltaR.x > 0) + deltaR.x = deltaR.x - (5 * ScreenshotInput::TranslateXtoMKB::Sens); + + if (deltaR.x > -32767 + (5 * ScreenshotInput::TranslateXtoMKB::Sens)) + deltaR.x = deltaR.x - (5 * ScreenshotInput::TranslateXtoMKB::Sens); + } + + //////////////////////// + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickupmapping)) + { + //double time to zero + if (deltaR.y < 0) + deltaR.y = deltaR.y + (5 * ScreenshotInput::TranslateXtoMKB::Sens); + + if (deltaR.y < 32767 - (5 * ScreenshotInput::TranslateXtoMKB::Sens)) + deltaR.y = deltaR.y + (5 * ScreenshotInput::TranslateXtoMKB::Sens); + } + + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickdownmapping)) + { + //double time to zero + if (deltaR.y > 0) + deltaR.y = deltaR.y - (5 * ScreenshotInput::TranslateXtoMKB::Sens); + + if (deltaR.y > -32767 + (5 * ScreenshotInput::TranslateXtoMKB::Sens)) + deltaR.y = deltaR.y - (5 * ScreenshotInput::TranslateXtoMKB::Sens); + } + + //back to deadzone + if (!IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickdownmapping) && !IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickupmapping)) + { + if (deltaR.y > 0 && deltaR.y - (5 * ScreenshotInput::TranslateXtoMKB::Sens) >= 0) + deltaR.y = deltaR.y - (5 * ScreenshotInput::TranslateXtoMKB::Sens); + else deltaR.y = 0; + + if (deltaR.y < 0 && deltaR.y + (5 * ScreenshotInput::TranslateXtoMKB::Sens) <= 0) + deltaR.y = deltaR.y - (5 * ScreenshotInput::TranslateXtoMKB::Sens); + else deltaR.y = 0; + } + + //back to deadzone + if (!IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickleftmapping) && !IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickrightmapping)) + { + if (deltaR.x > 0 && deltaR.x - (5 * ScreenshotInput::TranslateXtoMKB::Sens) >= 0) + deltaR.x = deltaR.x - (5 * ScreenshotInput::TranslateXtoMKB::Sens); + else deltaR.x = 0; + + if (deltaR.x < 0 && deltaR.x + (5 * ScreenshotInput::TranslateXtoMKB::Sens) <= 0) + deltaR.x = deltaR.x - (5 * ScreenshotInput::TranslateXtoMKB::Sens); + else deltaR.x = 0; + } + + RaxisX = deltaR.x; + RaxisY = deltaR.y; + + if (IsKeyPressed(VK_RBUTTON)) + { + if (pState->Gamepad.bLeftTrigger < 255) { - return XInputGetStateExPtr(targetControllerIndex, pState); + pState->Gamepad.bLeftTrigger++; + changed = true; } - return XInputGetStatePtr(targetControllerIndex, pState); + else pState->Gamepad.bLeftTrigger = 255; + } + else if (pState->Gamepad.bLeftTrigger > 0) + { + pState->Gamepad.bLeftTrigger--; + changed = true; + } + + if (IsKeyPressed(VK_LBUTTON)) + { + if (pState->Gamepad.bRightTrigger < 255) + { + pState->Gamepad.bRightTrigger++; + changed = true; + //MessageBoxA(NULL, "oja", "oja", MB_OK); + } + else pState->Gamepad.bRightTrigger = 255; + } + else if (pState->Gamepad.bRightTrigger > 0) + { + pState->Gamepad.bRightTrigger--; + changed = true; } + + + + + //normal buttons + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Amapping)) + { + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_A; + } + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_A; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Bmapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_B; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_B; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Ymapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_Y; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_Y; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Xmapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_X; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_X; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::LSmapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_LEFT_SHOULDER; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::RSmapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_RIGHT_SHOULDER; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::upmapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_DPAD_UP; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::downmapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_DPAD_DOWN; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::leftmapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_DPAD_LEFT; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::rightmapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_DPAD_RIGHT; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::startmapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_START; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_START; + + if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::optionmapping)) + pState->Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; + else + pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_BACK; + + + //increase dwpacketnumber if statechange + if (changed == false) + { + changed = + olddeltaL.x != deltaL.x || + olddeltaR.x != deltaR.x || + olddeltaL.y != deltaL.y || + olddeltaR.y != deltaR.y || + oldA != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Amapping) || + oldB != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Bmapping) || + oldX != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Xmapping) || + oldY != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Ymapping) || + oldtriggerleft != IsKeyPressed(VK_RBUTTON) || + oldtriggerright != IsKeyPressed(VK_LBUTTON) || + oldLS != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::LSmapping) || + oldRS != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::RSmapping) || + oldup != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::upmapping) || + olddown != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::downmapping) || + oldleft != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::leftmapping) || + + oldstart != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::startmapping) || + oldback != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::optionmapping) || + oldstickRB != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickRpressmapping) || + oldstickLB != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickLpressmapping) || + + oldright != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::rightmapping); + } + if (changed) + { + pState->dwPacketNumber++; + } + + oldA = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Amapping); + oldB = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Bmapping); + oldX = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Xmapping); + oldY = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Ymapping); + + oldLS = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::LSmapping); + oldRS = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::RSmapping); + oldup = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::upmapping); + olddown = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::downmapping); + oldleft = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::leftmapping); + oldright = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::rightmapping); + + oldstart = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::startmapping); + oldback = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::optionmapping); + oldstickRB = IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickRpressmapping); + oldstickLB != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickLpressmapping); + + oldtriggerleft = IsKeyPressed(VK_RBUTTON); + oldtriggerright = IsKeyPressed(VK_LBUTTON); + olddeltaL.x = deltaL.x; + olddeltaL.y = deltaL.y; + olddeltaR.x = deltaR.x; + olddeltaR.y = deltaR.y; + + if (!ScreenshotInput::TranslateXtoMKB::lefthanded) + { + pState->Gamepad.sThumbLY = LaxisY; + pState->Gamepad.sThumbLX = LaxisX; + pState->Gamepad.sThumbRY = RaxisY; + pState->Gamepad.sThumbRX = RaxisX; + } + else { + pState->Gamepad.sThumbLY = RaxisY; + pState->Gamepad.sThumbLX = RaxisX; + pState->Gamepad.sThumbRY = LaxisY; + pState->Gamepad.sThumbRX = LaxisX; + } + return ERROR_SUCCESS; + +} +inline DWORD WINAPI GetCapabilitiesfromkbm(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities) +{ + XINPUT_STATE state{}; + XInputfromkbm(dwUserIndex, &state, false); + + pCapabilities->Gamepad = state.Gamepad; + //pCapabilities->Flags = 0; + pCapabilities->SubType = XINPUT_DEVSUBTYPE_GAMEPAD; + pCapabilities->Type = XINPUT_DEVTYPE_GAMEPAD; + pCapabilities->Vibration.wLeftMotorSpeed = 0; + pCapabilities->Vibration.wRightMotorSpeed = 0; + return ERROR_SUCCESS; +} + +inline DWORD WINAPI XInputGetStateDinput_Inline(DWORD dwUserIndex, XINPUT_STATE* pState, bool extended) +{ + if (dinputDevice == nullptr) return ERROR_DEVICE_NOT_CONNECTED; + //WORK TODO TO DO is this an error? it is supposed to increase on statechange. looks like all time now? static DWORD packetNumber = 0; - pState->dwPacketNumber = packetNumber++; + pState->dwPacketNumber = packetNumber++; // memset(&(pState->Gamepad), 0, extended ? sizeof(XINPUT_GAMEPAD_EX) : sizeof(XINPUT_GAMEPAD)); dinputDevice->Poll(); DIJOYSTATE2 diState; @@ -152,17 +450,64 @@ inline DWORD WINAPI XInputGetState_Inline(DWORD dwUserIndex, XINPUT_STATE* pStat #undef TRIGGERDEADZONE return ERROR_SUCCESS; } + +inline DWORD WINAPI XInputGetState_Inline(DWORD dwUserIndex, XINPUT_STATE* pState, bool extended) +{ + if (extended) + getStateExCounter++; + else + getStateCounter++; + + auto [ connected, targetControllerIndex ] = GetTargetControllerIndex(dwUserIndex); + + if (!connected) + return ERROR_DEVICE_NOT_CONNECTED; + + if (XinputHook::useOpenXinput) + { + return OpenXinput::ProtoOpenXinputGetState(targetControllerIndex, pState, extended); + } + + if (!XinputHook::GetUseDinput()) + { + if (extended && XInputGetStateExPtr != nullptr) + { + return XInputGetStateExPtr(targetControllerIndex, pState); + } + return XInputGetStatePtr(targetControllerIndex, pState); + } + return XInputGetStateDinput_Inline(targetControllerIndex, pState, extended); +} + + + DWORD WINAPI Hook_XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState) { - return XInputGetState_Inline(dwUserIndex, pState, false); + if (!XinputHook::TranslateMKBtoXinput) + return XInputGetState_Inline(dwUserIndex, pState, false); + else if ((dwUserIndex == 0 && XinputHook::controllerIndex == 0) || (dwUserIndex == 1 && XinputHook::controllerIndex2 == 0) || (dwUserIndex == 2 && XinputHook::controllerIndex3 == 0) || (dwUserIndex == 3 && XinputHook::controllerIndex4 == 0)) { + return XInputfromkbm(dwUserIndex, pState, false); + } + else return XInputGetState_Inline(dwUserIndex, pState, false); } -DWORD WINAPI Hook_XInputGetStateEx(DWORD dwUserIndex, XINPUT_STATE* pState) +DWORD WINAPI Hook_XInputGetStateEx(DWORD dwUserIndex, XINPUT_STATE* pState) //XInputfromkbm { - return XInputGetState_Inline(dwUserIndex, pState, true); + if (!XinputHook::TranslateMKBtoXinput) + return XInputGetState_Inline(dwUserIndex, pState, true); + else if ((dwUserIndex == 0 && XinputHook::controllerIndex == 0) || (dwUserIndex == 1 && XinputHook::controllerIndex2 == 0) || (dwUserIndex == 2 && XinputHook::controllerIndex3 == 0) || (dwUserIndex == 3 && XinputHook::controllerIndex4 == 0)){ + return XInputfromkbm(dwUserIndex, pState, true); + } + else return XInputGetState_Inline(dwUserIndex, pState, true); } DWORD WINAPI Hook_XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration) { + if (XinputHook::TranslateMKBtoXinput) + { + if ((dwUserIndex == 0 && XinputHook::controllerIndex == 0) || (dwUserIndex == 1 && XinputHook::controllerIndex2 == 0) || (dwUserIndex == 2 && XinputHook::controllerIndex3 == 0) || (dwUserIndex == 3 && XinputHook::controllerIndex4 == 0)) + return ERROR_SUCCESS; + } + auto [connected, targetControllerIndex] = GetTargetControllerIndex(dwUserIndex); if (!connected) @@ -181,6 +526,11 @@ DWORD WINAPI Hook_XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration DWORD WINAPI Hook_XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities) { + if (XinputHook::TranslateMKBtoXinput) + { + if ((dwUserIndex == 0 && XinputHook::controllerIndex == 0) || (dwUserIndex == 1 && XinputHook::controllerIndex2 == 0) || (dwUserIndex == 2 && XinputHook::controllerIndex3 == 0) || (dwUserIndex == 3 && XinputHook::controllerIndex4 == 0)) + return GetCapabilitiesfromkbm(dwUserIndex, dwFlags, pCapabilities); + } auto [connected, targetControllerIndex] = GetTargetControllerIndex(dwUserIndex); if (!connected) @@ -331,7 +681,13 @@ void XinputHook::ShowGuiStatus() ImGui::SliderInt("Controller index 2", (int*)&controllerIndex2, 0, 16, "%d", ImGuiSliderFlags_AlwaysClamp); ImGui::SliderInt("Controller index 3", (int*)&controllerIndex3, 0, 16, "%d", ImGuiSliderFlags_AlwaysClamp); ImGui::SliderInt("Controller index 4", (int*)&controllerIndex4, 0, 16, "%d", ImGuiSliderFlags_AlwaysClamp); - + { + ImGui::PushID(123896); + ImGui::Checkbox("", &TranslateMKBtoXinput); + ImGui::SameLine(); + ImGui::TextWrapped("Enable KBM to Xinput. emulated Xinput gamepad"); + ImGui::PopID(); + } if (dinputDevice != nullptr) { ImGui::TextWrapped("Selected Dinput device \"%ws\" (GUID %lu-%u-%u)", @@ -397,6 +753,7 @@ void XinputHook::InstallImpl() XInputGetStateExPtr = t_XInputGetStateEx(GetProcAddress(GetModuleHandleW(L"xinput1_3.dll"), (LPCSTR)(100))); XInputGetStatePtr = t_XInputGetState(GetProcAddress(GetModuleHandleW(L"xinput1_3.dll"), "XInputGetState")); + //MessageBoxA(NULL, "hOOKED xINPUT", "Error", MB_OK); XInputSetStatePtr = t_XInputSetState(GetProcAddress(GetModuleHandleW(L"xinput1_3.dll"), "XInputSetState")); XInputGetCapabilitiesPtr = t_XInputGetCapabilities(GetProcAddress(GetModuleHandleW(L"xinput1_3.dll"), "XInputGetCapabilities")); @@ -430,4 +787,4 @@ void XinputHook::SetUseDinput(bool _useDinput) PollDinputDevices(); } -} \ No newline at end of file +} diff --git a/src/ProtoInput/ProtoInputHooks/XinputHook.h b/src/ProtoInput/ProtoInputHooks/XinputHook.h index 0ff62c5..0a49bbb 100644 --- a/src/ProtoInput/ProtoInputHooks/XinputHook.h +++ b/src/ProtoInput/ProtoInputHooks/XinputHook.h @@ -19,7 +19,7 @@ namespace Proto static unsigned int controllerIndex4; static bool useOpenXinput; - + static bool TranslateMKBtoXinput; const char* GetHookName() const override { return "Xinput"; } const char* GetHookDescription() const override { return diff --git a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h index dd0513e..e05e8e6 100644 --- a/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h +++ b/src/ProtoInput/ProtoInputHooks/pipeinclude/pipeinclude.h @@ -25,6 +25,7 @@ enum class PipeMessageType SetUseDinput, StopFocusMessageLoop, SetUseOpenXinput, + TranslateMKBtoXinput, SetDinputDeviceGuid, SetDinputHookGetDeviceState, SetSetWindowPosSettings, @@ -165,6 +166,11 @@ struct PipeMessageSetUseOpenXinput bool useOpenXinput; }; +struct PipeMessageSetTranslateMKBtoXinput +{ + bool TranslateMKBtoXinput; +}; + struct PipeMessageSetDinputDeviceGuid { GUID guid; diff --git a/src/ProtoInput/ProtoInputHost/Gui.cpp b/src/ProtoInput/ProtoInputHost/Gui.cpp index 53fca71..7c11fce 100644 --- a/src/ProtoInput/ProtoInputHost/Gui.cpp +++ b/src/ProtoInput/ProtoInputHost/Gui.cpp @@ -201,6 +201,7 @@ bool Launch() if (hookEnabled(BlockRawInputHookID)) InstallHook(instanceHandle, BlockRawInputHookID); SetUseOpenXinput(instanceHandle, currentProfile.useOpenXinput); + SetTranslateMKBtoXinput(instanceHandle, currentProfile.TranslateMKBtoXinput); SetUseDinputRedirection(instanceHandle, currentProfile.dinputToXinputRedirection); if (hookEnabled(XinputHookID)) InstallHook(instanceHandle, XinputHookID); @@ -1449,6 +1450,8 @@ void OptionsMenu() } ImGui::Checkbox("Use OpenXinput", ¤tProfile.useOpenXinput); + ImGui::Checkbox("Translate MKB to fake Xinput", ¤tProfile.TranslateMKBtoXinput); + ImGui::Checkbox("Dinput to Xinput redirection", ¤tProfile.dinputToXinputRedirection); ImGui::Checkbox("Use fake clip cursor", ¤tProfile.useFakeClipCursor); diff --git a/src/ProtoInput/ProtoInputHost/Profiles.h b/src/ProtoInput/ProtoInputHost/Profiles.h index fa91ea3..4a42c71 100644 --- a/src/ProtoInput/ProtoInputHost/Profiles.h +++ b/src/ProtoInput/ProtoInputHost/Profiles.h @@ -73,6 +73,7 @@ struct Profile bool dinputToXinputRedirection = false; bool useOpenXinput = false; + bool TranslateMKBtoXinput = false; bool TranslateXinputtoMKB = false; bool XinputtoMKBstickinvert = false; @@ -153,6 +154,7 @@ struct Profile cereal::make_nvp("dinputToXinputRedirection", dinputToXinputRedirection), cereal::make_nvp("useOpenXinput", useOpenXinput), + cereal::make_nvp("TranslateMKBtoXinput", TranslateMKBtoXinput), cereal::make_nvp("TranslateXinputtoMKB", TranslateXinputtoMKB), cereal::make_nvp("XinputtoMKBstickinvert", XinputtoMKBstickinvert), cereal::make_nvp("ScanOption", ScanOption), diff --git a/src/ProtoInput/ProtoInputLoader/Inject.cpp b/src/ProtoInput/ProtoInputLoader/Inject.cpp index 8711801..35e9bf9 100644 --- a/src/ProtoInput/ProtoInputLoader/Inject.cpp +++ b/src/ProtoInput/ProtoInputLoader/Inject.cpp @@ -239,6 +239,22 @@ void SetUseOpenXinput(ProtoInstanceHandle instanceHandle, bool useOpenXinput) } } +void SetTranslateMKBtoXinput(ProtoInstanceHandle instanceHandle, bool TranslateMKBtoXinput) +{ + if (const auto find = Proto::instances.find(instanceHandle); find != Proto::instances.end()) + { + auto& instance = find->second; + + WaitClientConnect(instance); + + ProtoPipe::PipeMessageSetTranslateMKBtoXinput message + { + TranslateMKBtoXinput + }; + + ProtoSendPipeMessage(instance.pipeHandle, ProtoPipe::PipeMessageType::TranslateMKBtoXinput, &message); + } +} extern "C" __declspec(dllexport) void SetupState(ProtoInstanceHandle instanceHandle, int instanceIndex) { if (instanceIndex < 1) diff --git a/src/ProtoInput/ProtoInputLoader/include/protoloader.h b/src/ProtoInput/ProtoInputLoader/include/protoloader.h index 3c3e1ea..007fdb6 100644 --- a/src/ProtoInput/ProtoInputLoader/include/protoloader.h +++ b/src/ProtoInput/ProtoInputLoader/include/protoloader.h @@ -98,6 +98,8 @@ extern "C" __declspec(dllexport) void SetUseDinputRedirection(ProtoInstanceHandl extern "C" __declspec(dllexport) void SetUseOpenXinput(ProtoInstanceHandle instanceHandle, bool useOpenXinput); +extern "C" __declspec(dllexport) void SetTranslateMKBtoXinput(ProtoInstanceHandle instanceHandle, bool TranslateMKBtoXinput); + // Both of these functions require RenameHandlesHookHookID hook extern "C" __declspec(dllexport) void AddHandleToRename(ProtoInstanceHandle instanceHandle, const wchar_t* name); From 16a31dd7aa9e497ebec022e3214734235aa25668 Mon Sep 17 00:00:00 2001 From: Messenils Date: Sun, 29 Mar 2026 17:29:07 +0200 Subject: [PATCH 19/20] translate option playable now --- src/ProtoInput/ProtoInputHooks/FakeCursor.cpp | 7 + .../ProtoInputHooks/GetAsyncKeyStateHook.cpp | 9 +- .../ProtoInputHooks/GetCursorPosHook.cpp | 17 +- .../ProtoInputHooks/GetKeyStateHook.cpp | 5 +- .../ProtoInputHooks/GetKeyboardStateHook.cpp | 5 +- .../ProtoInputHooks/PipeCommunication.cpp | 5 +- src/ProtoInput/ProtoInputHooks/RawInput.cpp | 21 +- .../ProtoInputHooks/SetCursorPosHook.cpp | 15 +- .../ProtoInputHooks/SetCursorPosHook.h | 2 +- src/ProtoInput/ProtoInputHooks/XinputHook.cpp | 282 +++++++----------- 10 files changed, 169 insertions(+), 199 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp index 493bd37..6fd47a5 100644 --- a/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp +++ b/src/ProtoInput/ProtoInputHooks/FakeCursor.cpp @@ -6,6 +6,8 @@ #include "ScanThread.h" #include "TranslateXtoMKB.h" #include "RawInput.h" +#include "SetCursorPosHook.h" +#include "XinputHook.h" #include namespace Proto @@ -322,6 +324,11 @@ void FakeCursor::DrawCursor() POINT pos = { FakeMouseKeyboard::GetMouseState().x,FakeMouseKeyboard::GetMouseState().y }; + if (XinputHook::TranslateMKBtoXinput) + { + pos.x = SetCursorPosHook::mousesethere.x; + pos.y = SetCursorPosHook::mousesethere.y; + } ClientToScreen((HWND)HwndSelector::GetSelectedHwnd(), &pos); ScreenToClient(pointerWindow, &pos); diff --git a/src/ProtoInput/ProtoInputHooks/GetAsyncKeyStateHook.cpp b/src/ProtoInput/ProtoInputHooks/GetAsyncKeyStateHook.cpp index d585819..896279f 100644 --- a/src/ProtoInput/ProtoInputHooks/GetAsyncKeyStateHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/GetAsyncKeyStateHook.cpp @@ -1,14 +1,21 @@ #include "GetAsyncKeyStateHook.h" #include "FakeMouseKeyboard.h" +#include "XinputHook.h" namespace Proto { SHORT WINAPI Hook_GetAsyncKeyState(int vKey) { + auto ret = (FakeMouseKeyboard::IsKeyStatePressed(vKey) ? 0b1000000000000000 : 0) | (FakeMouseKeyboard::IsAsyncKeyStatePressed(vKey) ? 1 : 0); FakeMouseKeyboard::ClearAsyncKeyState(vKey); - return ret; + if (!XinputHook::TranslateMKBtoXinput) + { + return ret; + } + else return 0; + } void GetAsyncKeyStateHook::InstallImpl() diff --git a/src/ProtoInput/ProtoInputHooks/GetCursorPosHook.cpp b/src/ProtoInput/ProtoInputHooks/GetCursorPosHook.cpp index cf7f15d..ed8a2b6 100644 --- a/src/ProtoInput/ProtoInputHooks/GetCursorPosHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/GetCursorPosHook.cpp @@ -2,6 +2,8 @@ #include "FakeMouseKeyboard.h" #include "HwndSelector.h" #include "Scaler.h" +#include "XinputHook.h" +#include "SetCursorPosHook.h" namespace Proto { @@ -10,10 +12,17 @@ BOOL WINAPI Hook_GetCursorPos(LPPOINT lpPoint) { if (lpPoint) { - const auto& state = FakeMouseKeyboard::GetMouseState(); - lpPoint->x = state.x; - lpPoint->y = state.y; - + if (!XinputHook::TranslateMKBtoXinput) + { + const auto& state = FakeMouseKeyboard::GetMouseState(); + lpPoint->x = state.x; + lpPoint->y = state.y; + } + else + { + lpPoint->x = SetCursorPosHook::mousesethere.x; + lpPoint->y = SetCursorPosHook::mousesethere.y; + } if (FakeMouseKeyboard::PutMouseInsideWindow) { int clientWidth = HwndSelector::windowWidth; diff --git a/src/ProtoInput/ProtoInputHooks/GetKeyStateHook.cpp b/src/ProtoInput/ProtoInputHooks/GetKeyStateHook.cpp index 58bf852..e117cb6 100644 --- a/src/ProtoInput/ProtoInputHooks/GetKeyStateHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/GetKeyStateHook.cpp @@ -1,12 +1,15 @@ #include "GetKeyStateHook.h" #include "FakeMouseKeyboard.h" +#include "XinputHook.h" namespace Proto { SHORT WINAPI Hook_GetKeyState(int nVirtKey) { - return FakeMouseKeyboard::IsKeyStatePressed(nVirtKey) ? 0b1000000000000000 : 0; + if (!XinputHook::TranslateMKBtoXinput) + return FakeMouseKeyboard::IsKeyStatePressed(nVirtKey) ? 0b1000000000000000 : 0; + else return 0; } void GetKeyStateHook::InstallImpl() diff --git a/src/ProtoInput/ProtoInputHooks/GetKeyboardStateHook.cpp b/src/ProtoInput/ProtoInputHooks/GetKeyboardStateHook.cpp index 3e0a122..1e73dcd 100644 --- a/src/ProtoInput/ProtoInputHooks/GetKeyboardStateHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/GetKeyboardStateHook.cpp @@ -1,5 +1,6 @@ #include "GetKeyboardStateHook.h" #include "FakeMouseKeyboard.h" +#include "XinputHook.h" namespace Proto { @@ -12,7 +13,9 @@ BOOL WINAPI Hook_GetKeyboardState(PBYTE lpKeyState) for (int vkey = 0; vkey < 256; ++vkey) { - lpKeyState[vkey] = FakeMouseKeyboard::IsKeyStatePressed(vkey) ? 0b10000000 : 0; + if (!XinputHook::TranslateMKBtoXinput) + lpKeyState[vkey] = FakeMouseKeyboard::IsKeyStatePressed(vkey) ? 0b10000000 : 0; + else lpKeyState[vkey] = 0; } } diff --git a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp index 0ade911..0d617ce 100644 --- a/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp +++ b/src/ProtoInput/ProtoInputHooks/PipeCommunication.cpp @@ -417,7 +417,6 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) printf("Received set translate MKB to Xinput. also extended mousestate bounds. remember Xinputhook also%d\n", body->TranslateMKBtoXinput); XinputHook::TranslateMKBtoXinput = body->TranslateMKBtoXinput; - FakeMouseKeyboard::SetIgnoreMouseBounds(true); break; } @@ -505,8 +504,6 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) FakeMouseKeyboard::SetIgnoreMouseBounds(body->allowOutOfBounds); FakeMouseKeyboard::SetExtendMouseBounds(body->extendBounds); - if(XinputHook::TranslateMKBtoXinput) //override - FakeMouseKeyboard::SetIgnoreMouseBounds(true); break; } case ProtoPipe::PipeMessageType::SetToggleCursorVisibilityShortcut: @@ -718,7 +715,7 @@ DWORD WINAPI PipeThread(LPVOID lpParameter) } endPipe: - MessageBoxA(NULL, "pipe ferdig", "rulle en", MB_OK); + MessageBoxA(NULL, "report this error: Pipe ended", "Pipe ended", MB_OK); printf("End of pipe thread\n"); CloseHandle(pipe); return 0; diff --git a/src/ProtoInput/ProtoInputHooks/RawInput.cpp b/src/ProtoInput/ProtoInputHooks/RawInput.cpp index 12aacdb..a7488ca 100644 --- a/src/ProtoInput/ProtoInputHooks/RawInput.cpp +++ b/src/ProtoInput/ProtoInputHooks/RawInput.cpp @@ -397,19 +397,20 @@ void RawInput::ProcessRawInput(HRAWINPUT rawInputHandle, bool inForeground, cons if ((allowMouse && usages[HID_USAGE_GENERIC_MOUSE]) || (allowKeyboard && usages[HID_USAGE_GENERIC_KEYBOARD])) // if ((allowMouse) || (allowKeyboard)) { - for (const auto& hwnd : forwardingWindows) - { - static size_t inputBufferCounter = 0; + + for (const auto& hwnd : forwardingWindows) + { + static size_t inputBufferCounter = 0; - // The game is going to lag behind the data we get by a few times, so store in an array and pass the index as a message parameter + // The game is going to lag behind the data we get by a few times, so store in an array and pass the index as a message parameter - inputBufferCounter = (inputBufferCounter + 1) % RawInputBufferSize; - inputBuffer[inputBufferCounter] = rawinput; + inputBufferCounter = (inputBufferCounter + 1) % RawInputBufferSize; + inputBuffer[inputBufferCounter] = rawinput; - const LPARAM x = (inputBufferCounter) | 0xAB000000; - if (!XinputHook::TranslateMKBtoXinput) - PostMessageW(hwnd, WM_INPUT, RIM_INPUT, x); - } + const LPARAM x = (inputBufferCounter) | 0xAB000000; + if (!XinputHook::TranslateMKBtoXinput) + PostMessageW(hwnd, WM_INPUT, RIM_INPUT, x); + } } } } diff --git a/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.cpp b/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.cpp index d00f52c..0d02558 100644 --- a/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.cpp @@ -3,28 +3,33 @@ #include "HwndSelector.h" #include "FakeMouseKeyboard.h" #include "FakeCursor.h" +#include "XinputHook.h" #include "Scaler.h" namespace Proto { bool SetCursorPosHook::blockSettingCursorPos = false; - +POINT SetCursorPosHook::mousesethere; BOOL WINAPI Hook_SetCursorPos(int X, int Y) { + if (!SetCursorPosHook::blockSettingCursorPos) { POINT p; p.x = X; p.y = Y; - //any scaling here? - //p = WndProcHook::getfactor(p); - //SetCursorPos require screen coordinates (relative to 0,0 of monitor) ScreenToClient((HWND)HwndSelector::GetSelectedHwnd(), &p); - FakeMouseKeyboard::SetMousePos(p.x, p.y); + if (XinputHook::TranslateMKBtoXinput) + { + SetCursorPosHook::mousesethere.x = p.x; + SetCursorPosHook::mousesethere.y = p.y; + } + if (!XinputHook::TranslateMKBtoXinput) + FakeMouseKeyboard::SetMousePos(p.x, p.y); FakeCursor::NotifyUpdatedCursorPosition(); } diff --git a/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.h b/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.h index 4efa2fa..a70e681 100644 --- a/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.h +++ b/src/ProtoInput/ProtoInputHooks/SetCursorPosHook.h @@ -13,7 +13,7 @@ class SetCursorPosHook final : public Hook public: //TODO: pipe option? static bool blockSettingCursorPos; - + static POINT mousesethere; const char* GetHookName() const override { return "Set Cursor Position"; } const char* GetHookDescription() const override { diff --git a/src/ProtoInput/ProtoInputHooks/XinputHook.cpp b/src/ProtoInput/ProtoInputHooks/XinputHook.cpp index debc6fe..1181d75 100644 --- a/src/ProtoInput/ProtoInputHooks/XinputHook.cpp +++ b/src/ProtoInput/ProtoInputHooks/XinputHook.cpp @@ -80,162 +80,132 @@ bool IsKeyPressed(int Vkey) { return FakeMouseKeyboard::IsKeyStatePressed(Vkey); } -POINT oldmousepos; POINT deltaL; POINT deltaR; POINT olddeltaL; POINT olddeltaR; -int Akey = 65; -int Dkey = 68; -int Wkey = 87; -int Skey = 83; bool oldA, oldB, oldX, oldY, oldtriggerleft, oldtriggerright, oldLS, oldRS, oldup, olddown, oldleft, oldright; bool oldstart, oldback, oldstickRB, oldstickLB; bool firstcall = false; DWORD fakedwpacketnumber = 0; bool changed; SHORT LaxisX, LaxisY, RaxisX, RaxisY; -inline DWORD WINAPI XInputfromkbm(DWORD dwUserIndex, XINPUT_STATE* pState, bool extended) +SHORT deadzone = 14000; +SHORT negativedeadzone = -14000; +SHORT oldcurrentX, oldcurrentY; +POINT axisvaluemouse(SHORT currentX, SHORT currentY) { - - if (extended) - getStateExCounter++; - else - getStateCounter++; - //ZeroMemory(pState, sizeof(pState)); - pState->Gamepad.wButtons = 0; - //kbmgamepad.wButtons = 0; const auto& mousestate = FakeMouseKeyboard::GetMouseState(); - POINT Pos = { mousestate.x, mousestate.y }; + POINT Pos = { mousestate.x - 100, mousestate.y - 100}; + int dx = Pos.x * (2 * ScreenshotInput::TranslateXtoMKB::Sens); + int dy = -Pos.y * (2 * ScreenshotInput::TranslateXtoMKB::Sens); + if (dx != 0 || dy != 0) + { + if (currentX + dx > 32767) currentX = 32767; + else if (currentX + dx < -32767) currentX = -32767; + else currentX += dx; - deltaL.x = (Pos.x - oldmousepos.x) * (2 * ScreenshotInput::TranslateXtoMKB::Sens); - deltaL.y = (Pos.y - oldmousepos.y) * (2 * ScreenshotInput::TranslateXtoMKB::Sens); - - oldmousepos.x = Pos.x; - oldmousepos.y = Pos.y; - - if (!firstcall) - { - pState->Gamepad.sThumbLY = 0; - pState->Gamepad.sThumbLX = 0; - pState->Gamepad.sThumbRY = 0; - pState->Gamepad.sThumbRX = 0; - oldmousepos.x = 0; - oldmousepos.y = 0; - firstcall = true; + if (currentY + dy > 32767) currentY = 32767; + else if (currentY + dy< -32767) currentY = -32767; + else currentY += dy; + changed = true; + FakeMouseKeyboard::SetMousePos(100, 100); } + POINT returnaxis; + returnaxis.x = currentX; + returnaxis.y = currentY; + return returnaxis; +} +SHORT axisvaluebutton(SHORT currentvalue, BOOL upkey, BOOL downkey) +{ + SHORT diditchange = currentvalue; + if (upkey && !downkey) + { + //jump to above deadzone + if (currentvalue < 12000) + currentvalue = 12000; - if (LaxisX + deltaL.x < -32767) - LaxisX = -32767; - else if (LaxisX + deltaL.x > 32767) - LaxisX = 32767; - else LaxisX += deltaL.x; - if (LaxisY + deltaL.y < -32767) - deltaL.y = -32767; - else if (LaxisY + deltaL.y > 32767) - LaxisY = 32767; - else LaxisY += deltaL.y; - - - if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickrightmapping)) - { - //double time to zero - if (deltaR.x < 0) - deltaR.x = deltaR.x + (5 * ScreenshotInput::TranslateXtoMKB::Sens); - - if (deltaR.x < 32767 - (5 * ScreenshotInput::TranslateXtoMKB::Sens)) - deltaR.x = deltaR.x + (5 * ScreenshotInput::TranslateXtoMKB::Sens); + //increase or stall at max + if (currentvalue + (7 * ScreenshotInput::TranslateXtoMKB::Sens) < 32767) + currentvalue = currentvalue + (7 * ScreenshotInput::TranslateXtoMKB::Sens); + else currentvalue = 32767; } + if (downkey && !upkey) + { + //jump to above dead + if (currentvalue > -12000) + currentvalue = -12000; - if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickleftmapping)) - { - if (deltaR.x > 0) - deltaR.x = deltaR.x - (5 * ScreenshotInput::TranslateXtoMKB::Sens); - - if (deltaR.x > -32767 + (5 * ScreenshotInput::TranslateXtoMKB::Sens)) - deltaR.x = deltaR.x - (5 * ScreenshotInput::TranslateXtoMKB::Sens); + //increase or stall + if (currentvalue - (7 * ScreenshotInput::TranslateXtoMKB::Sens) > -32767) + currentvalue = currentvalue - (7 * ScreenshotInput::TranslateXtoMKB::Sens); + else currentvalue = -32767; } + //drift to 0 + if (!downkey && !upkey) + { + if (currentvalue > 0 + (7 * ScreenshotInput::TranslateXtoMKB::Sens)) + currentvalue = currentvalue - (7 * ScreenshotInput::TranslateXtoMKB::Sens); - //////////////////////// - if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickupmapping)) - { - //double time to zero - if (deltaR.y < 0) - deltaR.y = deltaR.y + (5 * ScreenshotInput::TranslateXtoMKB::Sens); - - if (deltaR.y < 32767 - (5 * ScreenshotInput::TranslateXtoMKB::Sens)) - deltaR.y = deltaR.y + (5 * ScreenshotInput::TranslateXtoMKB::Sens); + if (currentvalue < 0 - (7 * ScreenshotInput::TranslateXtoMKB::Sens)) + currentvalue = currentvalue + (7 * ScreenshotInput::TranslateXtoMKB::Sens); } + if (diditchange != currentvalue) + changed = true; + return currentvalue; +} +inline DWORD WINAPI XInputfromkbm(DWORD dwUserIndex, XINPUT_STATE* pState, bool extended) +{ - if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickdownmapping)) - { - //double time to zero - if (deltaR.y > 0) - deltaR.y = deltaR.y - (5 * ScreenshotInput::TranslateXtoMKB::Sens); + if (extended) + getStateExCounter++; + else + getStateCounter++; - if (deltaR.y > -32767 + (5 * ScreenshotInput::TranslateXtoMKB::Sens)) - deltaR.y = deltaR.y - (5 * ScreenshotInput::TranslateXtoMKB::Sens); - } + pState->Gamepad.wButtons = 0; - //back to deadzone - if (!IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickdownmapping) && !IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickupmapping)) + if (!firstcall) { - if (deltaR.y > 0 && deltaR.y - (5 * ScreenshotInput::TranslateXtoMKB::Sens) >= 0) - deltaR.y = deltaR.y - (5 * ScreenshotInput::TranslateXtoMKB::Sens); - else deltaR.y = 0; - - if (deltaR.y < 0 && deltaR.y + (5 * ScreenshotInput::TranslateXtoMKB::Sens) <= 0) - deltaR.y = deltaR.y - (5 * ScreenshotInput::TranslateXtoMKB::Sens); - else deltaR.y = 0; + FakeMouseKeyboard::SetMousePos(100, 100); + pState->Gamepad.sThumbLY = 0; + pState->Gamepad.sThumbLX = 0; + pState->Gamepad.sThumbRY = 0; + pState->Gamepad.sThumbRX = 0; + if (ScreenshotInput::TranslateXtoMKB::upmapping == VK_UP || ScreenshotInput::TranslateXtoMKB::upmapping == VK_DOWN) + ScreenshotInput::TranslateXtoMKB::upmapping = VK_NUMPAD8; + if (ScreenshotInput::TranslateXtoMKB::downmapping == VK_UP || ScreenshotInput::TranslateXtoMKB::downmapping == VK_DOWN) + ScreenshotInput::TranslateXtoMKB::downmapping = VK_NUMPAD5; + if (ScreenshotInput::TranslateXtoMKB::leftmapping == VK_LEFT || ScreenshotInput::TranslateXtoMKB::leftmapping == VK_RIGHT) + ScreenshotInput::TranslateXtoMKB::leftmapping = VK_NUMPAD4; + if (ScreenshotInput::TranslateXtoMKB::rightmapping == VK_LEFT || ScreenshotInput::TranslateXtoMKB::rightmapping == VK_RIGHT) + ScreenshotInput::TranslateXtoMKB::rightmapping = VK_NUMPAD6; + firstcall = true; } - //back to deadzone - if (!IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickleftmapping) && !IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickrightmapping)) - { - if (deltaR.x > 0 && deltaR.x - (5 * ScreenshotInput::TranslateXtoMKB::Sens) >= 0) - deltaR.x = deltaR.x - (5 * ScreenshotInput::TranslateXtoMKB::Sens); - else deltaR.x = 0; - - if (deltaR.x < 0 && deltaR.x + (5 * ScreenshotInput::TranslateXtoMKB::Sens) <= 0) - deltaR.x = deltaR.x - (5 * ScreenshotInput::TranslateXtoMKB::Sens); - else deltaR.x = 0; - } + RaxisX = axisvaluebutton(RaxisX, IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickleftmapping), IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickrightmapping)); + RaxisY = axisvaluebutton(RaxisY, IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickupmapping), IsKeyPressed(ScreenshotInput::TranslateXtoMKB::stickdownmapping)); - RaxisX = deltaR.x; - RaxisY = deltaR.y; + POINT mouseaxis = axisvaluemouse(LaxisX, LaxisY); + LaxisX = mouseaxis.x; + LaxisY = mouseaxis.y; - if (IsKeyPressed(VK_RBUTTON)) - { - if (pState->Gamepad.bLeftTrigger < 255) - { - pState->Gamepad.bLeftTrigger++; - changed = true; - } - else pState->Gamepad.bLeftTrigger = 255; + if (IsKeyPressed(VK_RBUTTON)) { + pState->Gamepad.bLeftTrigger = 255; + //changed = true; } - else if (pState->Gamepad.bLeftTrigger > 0) - { - pState->Gamepad.bLeftTrigger--; - changed = true; + else { + pState->Gamepad.bLeftTrigger = 0; + //changed = true; } - if (IsKeyPressed(VK_LBUTTON)) - { - if (pState->Gamepad.bRightTrigger < 255) - { - pState->Gamepad.bRightTrigger++; - changed = true; - //MessageBoxA(NULL, "oja", "oja", MB_OK); - } - else pState->Gamepad.bRightTrigger = 255; + if (IsKeyPressed(VK_LBUTTON)) { + pState->Gamepad.bRightTrigger = 255; } - else if (pState->Gamepad.bRightTrigger > 0) - { - pState->Gamepad.bRightTrigger--; - changed = true; + else { + pState->Gamepad.bRightTrigger = 0; } @@ -243,82 +213,66 @@ inline DWORD WINAPI XInputfromkbm(DWORD dwUserIndex, XINPUT_STATE* pState, bool //normal buttons if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Amapping)) - { pState->Gamepad.wButtons |= XINPUT_GAMEPAD_A; - } - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_A; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Bmapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_B; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_B; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Ymapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_Y; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_Y; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Xmapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_X; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_X; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::LSmapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_LEFT_SHOULDER; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::RSmapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_RIGHT_SHOULDER; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::upmapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_DPAD_UP; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::downmapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_DPAD_DOWN; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::leftmapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_DPAD_LEFT; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::rightmapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_DPAD_RIGHT; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::startmapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_START; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_START; if (IsKeyPressed(ScreenshotInput::TranslateXtoMKB::optionmapping)) pState->Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; - else - pState->Gamepad.wButtons &= ~XINPUT_GAMEPAD_BACK; + if (ScreenshotInput::TranslateXtoMKB::lefthanded) + { + pState->Gamepad.sThumbLY = LaxisY; + pState->Gamepad.sThumbLX = LaxisX; + pState->Gamepad.sThumbRY = RaxisY; + pState->Gamepad.sThumbRX = RaxisX; + } + else { + pState->Gamepad.sThumbLY = RaxisY; + pState->Gamepad.sThumbLX = RaxisX; + pState->Gamepad.sThumbRY = LaxisY; + pState->Gamepad.sThumbRX = LaxisX; + } + //increase dwpacketnumber if statechange if (changed == false) { changed = - olddeltaL.x != deltaL.x || - olddeltaR.x != deltaR.x || - olddeltaL.y != deltaL.y || - olddeltaR.y != deltaR.y || oldA != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Amapping) || oldB != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Bmapping) || oldX != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Xmapping) || oldY != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::Ymapping) || - oldtriggerleft != IsKeyPressed(VK_RBUTTON) || - oldtriggerright != IsKeyPressed(VK_LBUTTON) || + oldtriggerleft != IsKeyPressed(0x4F) || + oldtriggerright != IsKeyPressed(0x50) || oldLS != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::LSmapping) || oldRS != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::RSmapping) || oldup != IsKeyPressed(ScreenshotInput::TranslateXtoMKB::upmapping) || @@ -356,24 +310,8 @@ inline DWORD WINAPI XInputfromkbm(DWORD dwUserIndex, XINPUT_STATE* pState, bool oldtriggerleft = IsKeyPressed(VK_RBUTTON); oldtriggerright = IsKeyPressed(VK_LBUTTON); - olddeltaL.x = deltaL.x; - olddeltaL.y = deltaL.y; - olddeltaR.x = deltaR.x; - olddeltaR.y = deltaR.y; - if (!ScreenshotInput::TranslateXtoMKB::lefthanded) - { - pState->Gamepad.sThumbLY = LaxisY; - pState->Gamepad.sThumbLX = LaxisX; - pState->Gamepad.sThumbRY = RaxisY; - pState->Gamepad.sThumbRX = RaxisX; - } - else { - pState->Gamepad.sThumbLY = RaxisY; - pState->Gamepad.sThumbLX = RaxisX; - pState->Gamepad.sThumbRY = LaxisY; - pState->Gamepad.sThumbRX = LaxisX; - } + return ERROR_SUCCESS; } @@ -397,7 +335,7 @@ inline DWORD WINAPI XInputGetStateDinput_Inline(DWORD dwUserIndex, XINPUT_STATE* if (dinputDevice == nullptr) return ERROR_DEVICE_NOT_CONNECTED; - //WORK TODO TO DO is this an error? it is supposed to increase on statechange. looks like all time now? + //WORK TODO TO DO is this an error? it is supposed to increase on statechange. doesnt look correct now? static DWORD packetNumber = 0; pState->dwPacketNumber = packetNumber++; // memset(&(pState->Gamepad), 0, extended ? sizeof(XINPUT_GAMEPAD_EX) : sizeof(XINPUT_GAMEPAD)); @@ -685,7 +623,7 @@ void XinputHook::ShowGuiStatus() ImGui::PushID(123896); ImGui::Checkbox("", &TranslateMKBtoXinput); ImGui::SameLine(); - ImGui::TextWrapped("Enable KBM to Xinput. emulated Xinput gamepad"); + ImGui::TextWrapped("Enable KBM to Xinput. emulate Xinput gamepad on controllerindex 0"); ImGui::PopID(); } if (dinputDevice != nullptr) From 5c2c2fb3a34c23131d748473325f053c935e36c8 Mon Sep 17 00:00:00 2001 From: Messenils Date: Sun, 29 Mar 2026 17:56:38 +0200 Subject: [PATCH 20/20] fixed imgui unique ids/text --- src/ProtoInput/ProtoInputHooks/Gui.cpp | 58 +++++++++++++------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/ProtoInput/ProtoInputHooks/Gui.cpp b/src/ProtoInput/ProtoInputHooks/Gui.cpp index 552cf30..cb8e00a 100644 --- a/src/ProtoInput/ProtoInputHooks/Gui.cpp +++ b/src/ProtoInput/ProtoInputHooks/Gui.cpp @@ -259,7 +259,7 @@ void XTranslateMenu() if (waitingKeyPressX) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##B"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##X"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -311,7 +311,7 @@ void XTranslateMenu() if (waitingKeyPressRS) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##RS"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -322,7 +322,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::RSmapping = X_RS; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##RS1"))//these need unique IDs or text { waitingKeyPressRS = true; lastVKkey = -1; @@ -337,7 +337,7 @@ void XTranslateMenu() if (waitingKeyPressLS) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##LS"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -348,7 +348,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::LSmapping = X_LS; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##LS1"))//these need unique IDs or text { waitingKeyPressLS = true; lastVKkey = -1; @@ -363,7 +363,7 @@ void XTranslateMenu() if (waitingKeyPressright) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##DR"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -374,7 +374,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::rightmapping = X_right; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##DR1"))//these need unique IDs or text { waitingKeyPressright = true; lastVKkey = -1; @@ -389,7 +389,7 @@ void XTranslateMenu() if (waitingKeyPressleft) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##DL"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -400,7 +400,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::leftmapping = X_left; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##DL1"))//these need unique IDs or text { waitingKeyPressleft = true; lastVKkey = -1; @@ -415,7 +415,7 @@ void XTranslateMenu() if (waitingKeyPressup) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##DU"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -426,7 +426,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::upmapping = X_up; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##DU1"))//these need unique IDs or text { waitingKeyPressup = true; lastVKkey = -1; @@ -441,7 +441,7 @@ void XTranslateMenu() if (waitingKeyPressdown) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##DD"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -452,7 +452,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::downmapping = X_down; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##DD1"))//these need unique IDs or text { waitingKeyPressdown = true; lastVKkey = -1; @@ -467,7 +467,7 @@ void XTranslateMenu() if (waitingKeyPressstickRpress) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##RSP"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -478,7 +478,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::stickRpressmapping = X_stickRpress; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##RSP1"))//these need unique IDs or text { waitingKeyPressstickRpress = true; lastVKkey = -1; @@ -493,7 +493,7 @@ void XTranslateMenu() if (waitingKeyPressstickLpress) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##LSP"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -504,7 +504,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::stickLpressmapping = X_stickLpress; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##LSP1"))//these need unique IDs or text { waitingKeyPressstickLpress = true; lastVKkey = -1; @@ -519,7 +519,7 @@ void XTranslateMenu() if (waitingKeyPressstickright) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##SRA"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -530,7 +530,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::stickrightmapping = X_stickright; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##SRA1"))//these need unique IDs or text { waitingKeyPressstickright = true; lastVKkey = -1; @@ -545,7 +545,7 @@ void XTranslateMenu() if (waitingKeyPressstickleft) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##SLA"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -556,7 +556,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::stickleftmapping = X_stickleft; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##SLA1"))//these need unique IDs or text { waitingKeyPressstickleft = true; lastVKkey = -1; @@ -571,7 +571,7 @@ void XTranslateMenu() if (waitingKeyPressstickup) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##SUA"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -582,7 +582,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::stickupmapping = X_stickup; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##SUA1"))//these need unique IDs or text { waitingKeyPressstickup = true; lastVKkey = -1; @@ -597,7 +597,7 @@ void XTranslateMenu() if (waitingKeyPressstickdown) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##SDA"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -608,7 +608,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::stickdownmapping = X_stickdown; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##SDA1"))//these need unique IDs or text { waitingKeyPressstickdown = true; lastVKkey = -1; @@ -623,7 +623,7 @@ void XTranslateMenu() if (waitingKeyPressoption) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##OPT"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -634,7 +634,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::optionmapping = X_option; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##OPT1"))//these need unique IDs or text { waitingKeyPressoption = true; lastVKkey = -1; @@ -649,7 +649,7 @@ void XTranslateMenu() if (waitingKeyPressstart) { //PushDisabled(); - ImGui::Button("Press Keyboard button...##Y"); //these need unique IDs or text + ImGui::Button("Press Keyboard button...##STA"); //these need unique IDs or text GetVK(); //PopDisabled(); // Sleep(100); @@ -660,7 +660,7 @@ void XTranslateMenu() ScreenshotInput::TranslateXtoMKB::startmapping = X_start; } } - else if (ImGui::Button("Click to change##Y1"))//these need unique IDs or text + else if (ImGui::Button("Click to change##STA1"))//these need unique IDs or text { waitingKeyPressstart = true; lastVKkey = -1;