├── icon.ico ├── mouse.gif ├── resource.res ├── .gitattributes ├── resource.rc ├── LICENSE ├── README.md └── mouse.cpp /icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ran4erep/EmuMouse/main/icon.ico -------------------------------------------------------------------------------- /mouse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ran4erep/EmuMouse/main/mouse.gif -------------------------------------------------------------------------------- /resource.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ran4erep/EmuMouse/main/resource.res -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /resource.rc: -------------------------------------------------------------------------------- 1 | #include 2 | #define IDI_ICON1 101 3 | 4 | IDI_ICON1 ICON "icon.ico" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0) 2 | 3 | Copyright (c) 2025 ran4erep 4 | 5 | This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License. 6 | 7 | You are free to: 8 | - Share — copy and redistribute the material in any medium or format 9 | - Adapt — remix, transform, and build upon the material 10 | 11 | Under the following terms: 12 | - Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. 13 | - NonCommercial — You may not use the material for commercial purposes. 14 | 15 | The licensor cannot revoke these freedoms as long as you follow the license terms. 16 | 17 | Full license text: https://creativecommons.org/licenses/by-nc/4.0/legalcode 18 | 19 | Notices: 20 | - You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 21 | - No warranties are given. The license may not give you all of the permissions necessary for your intended use. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EmuMouse 2 | 3 | EmuMouse is a lightweight Windows utility that emulates mouse wheel scrolling using keyboard shortcuts. Perfect for users with malfunctioning mouse wheels or those who prefer keyboard-based scrolling. 4 | 5 | ## Features 6 | 7 | - Emulates mouse wheel using keyboard shortcuts: 8 | - Works with any application or game 9 | - Compatible with modifier keys (Shift, Ctrl, Alt) 10 | - Written in C++, which means low CPU and RAM usage 11 | - Works in background without UI 12 | - Zero configuration needed 13 | 14 | ## Why Use It? 15 | 16 | - Your mouse wheel is broken or malfunctioning 17 | - You prefer keyboard-based scrolling 18 | - You want to reduce wear on your mouse wheel 19 | 20 | ## How It Works 21 | 22 | The program runs in the background and listens for the following key combinations: 23 | - `Windows + Q`: Simulates mouse wheel scroll up 24 | - `Windows + A`: Simulates mouse wheel scroll down 25 | 26 | ## Installation 27 | 28 | 1. Download the latest release from [Releases](../../releases) 29 | 2. Run `EmuMouse.exe` 30 | 3. Start using Win+Q and Win+A for scrolling 31 | 32 | ## Building from Source 33 | 34 | Requirements: 35 | - MinGW-w64 or other C++ compiler with Windows API support 36 | - Windows SDK 37 | 38 | ### Compile resources 39 | windres resource.rc -O coff -o resource.res 40 | 41 | ### Compile program 42 | g++ -o EmuMouse.exe mouse.cpp resource.res -mwindows 43 | 44 | ## Auto-start with Windows 45 | To make the program start automatically with Windows: 46 | 47 | - Press Win + R 48 | - Type `shell:startup` 49 | - Copy EmuMouse.exe in the opened folder 50 | 51 | ## License 52 | [CC BY-NC 4.0](LICENSE) 53 | 54 | This software is licensed under Creative Commons Attribution-NonCommercial 4.0 International License. This means you can freely use and modify the code for non-commercial purposes, as long as you provide attribution to the original author. 55 | 56 | Commercial use is prohibited without explicit permission from the author. 57 | 58 | ## Author 59 | ran4erep 60 | 61 | Last updated: 2025-02-11 62 | 63 | ![](mouse.gif) 64 | -------------------------------------------------------------------------------- /mouse.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define WM_TRAYICON (WM_USER + 1) 5 | #define ID_TRAY_EXIT 1001 6 | #define IDI_ICON1 101 7 | 8 | HHOOK keyboardHook; 9 | bool isWindowsKeyPressed = false; 10 | HWND hwnd; 11 | NOTIFYICONDATA nid; 12 | 13 | LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { 14 | switch (msg) { 15 | case WM_TRAYICON: { 16 | if (lParam == WM_RBUTTONUP || lParam == WM_LBUTTONUP) { 17 | POINT pt; 18 | GetCursorPos(&pt); 19 | HMENU menu = CreatePopupMenu(); 20 | InsertMenu(menu, -1, MF_BYPOSITION | MF_STRING, ID_TRAY_EXIT, "Exit"); 21 | SetForegroundWindow(hwnd); 22 | TrackPopupMenu(menu, TPM_RIGHTALIGN | TPM_BOTTOMALIGN, pt.x, pt.y, 0, hwnd, NULL); 23 | DestroyMenu(menu); 24 | } 25 | return 0; 26 | } 27 | case WM_COMMAND: { 28 | if (LOWORD(wParam) == ID_TRAY_EXIT) { 29 | Shell_NotifyIcon(NIM_DELETE, &nid); 30 | PostQuitMessage(0); 31 | } 32 | return 0; 33 | } 34 | case WM_DESTROY: { 35 | Shell_NotifyIcon(NIM_DELETE, &nid); 36 | PostQuitMessage(0); 37 | return 0; 38 | } 39 | } 40 | return DefWindowProc(hwnd, msg, wParam, lParam); 41 | } 42 | 43 | LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { 44 | if (nCode >= 0) { 45 | KBDLLHOOKSTRUCT* kbStruct = (KBDLLHOOKSTRUCT*)lParam; 46 | 47 | if (kbStruct->vkCode == VK_LWIN || kbStruct->vkCode == VK_RWIN) { 48 | if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) { 49 | isWindowsKeyPressed = true; 50 | } else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) { 51 | isWindowsKeyPressed = false; 52 | } 53 | } 54 | 55 | if (isWindowsKeyPressed && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) { 56 | if (kbStruct->vkCode == 'Q') { 57 | mouse_event(MOUSEEVENTF_WHEEL, 0, 0, 120, 0); 58 | return 1; 59 | } 60 | else if (kbStruct->vkCode == 'A') { 61 | mouse_event(MOUSEEVENTF_WHEEL, 0, 0, -120, 0); 62 | return 1; 63 | } 64 | } 65 | } 66 | return CallNextHookEx(keyboardHook, nCode, wParam, lParam); 67 | } 68 | 69 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { 70 | WNDCLASSEX wc = {0}; 71 | wc.cbSize = sizeof(WNDCLASSEX); 72 | wc.lpfnWndProc = WndProc; 73 | wc.hInstance = hInstance; 74 | wc.lpszClassName = "EmuMouseClass"; 75 | 76 | if (!RegisterClassEx(&wc)) return 1; 77 | 78 | hwnd = CreateWindowEx(0, "EmuMouseClass", "EmuMouse", 79 | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 80 | CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); 81 | 82 | if (!hwnd) return 1; 83 | 84 | nid.cbSize = sizeof(NOTIFYICONDATA); 85 | nid.hWnd = hwnd; 86 | nid.uID = 1; 87 | nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; 88 | nid.uCallbackMessage = WM_TRAYICON; 89 | nid.hIcon = (HICON)LoadImage(hInstance, 90 | MAKEINTRESOURCE(IDI_ICON1), 91 | IMAGE_ICON, 92 | 16, 93 | 16, 94 | LR_DEFAULTCOLOR); 95 | strcpy(nid.szTip, "EmuMouse (Win+Q/A)"); 96 | 97 | Shell_NotifyIcon(NIM_ADD, &nid); 98 | 99 | keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, NULL, 0); 100 | if (!keyboardHook) { 101 | Shell_NotifyIcon(NIM_DELETE, &nid); 102 | return 1; 103 | } 104 | 105 | MSG msg; 106 | while (GetMessage(&msg, NULL, 0, 0)) { 107 | TranslateMessage(&msg); 108 | DispatchMessage(&msg); 109 | } 110 | 111 | UnhookWindowsHookEx(keyboardHook); 112 | return 0; 113 | } --------------------------------------------------------------------------------