├── Release ├── voidmouse.dll └── voidmouse.exe ├── README.md ├── LICENSE ├── dllhook ├── dllhook.def ├── dllhook.vcproj └── dllhook.c ├── voidmouse.c ├── voidmouse.sln └── voidmouse.vcproj /Release/voidmouse.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voidtools/voidMouse/HEAD/Release/voidmouse.dll -------------------------------------------------------------------------------- /Release/voidmouse.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voidtools/voidMouse/HEAD/Release/voidmouse.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # voidMouse 2 | Mouse driver hook that allows you to scroll windows with the middle mouse button + mouse move. 3 | 4 | AKA: universal scroll 5 | 6 | Download 7 | -------- 8 | 9 | https://github.com/voidtools/voidMouse/releases 10 | 11 | Install 12 | ------- 13 | 14 | Extract to an empty folder and run voidmouse.exe 15 | 16 | https://www.voidtools.com/forum/viewtopic.php?f=2&t=7505 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2025 voidtools 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /dllhook/dllhook.def: -------------------------------------------------------------------------------- 1 | ; 2 | 3 | ; File: winsock.def 4 | 5 | ; System: MS-Windows 3.x 6 | 7 | ; Summary: Module definition file for Windows Sockets DLL. 8 | 9 | ; 10 | 11 | 12 | 13 | LIBRARY SOCK ; Application's module name 14 | 15 | 16 | 17 | DESCRIPTION 'BSD Socket API for Windows' 18 | 19 | 20 | 21 | EXETYPE WINDOWS ; required for all windows applications 22 | 23 | 24 | 25 | STUB 'WINSTUB.EXE' ; generates error message if application 26 | 27 | ; is run without Windows 28 | 29 | 30 | 31 | ;CODE can be FIXED in memory because of potential upcalls 32 | 33 | CODE PRELOAD FIXED 34 | 35 | 36 | 37 | ;DATA must be SINGLE and at a FIXED location since this is a DLL 38 | 39 | DATA PRELOAD FIXED SINGLE 40 | 41 | 42 | 43 | HEAPSIZE 1024 44 | 45 | STACKSIZE 16384 46 | 47 | 48 | 49 | ; All functions that will be called by any Windows routine 50 | 51 | ; must be exported. Any additional exports beyond those defined 52 | 53 | ; here must have ordinal numbers 1000 or above. 54 | 55 | 56 | 57 | EXPORTS 58 | 59 | initializeHook @1 60 | 61 | UninitializeHook @2 62 | 63 | ;eof 64 | -------------------------------------------------------------------------------- /voidmouse.c: -------------------------------------------------------------------------------- 1 | /* 2 | TODO: 3 | Customize which mouse button to use for scrolling. 4 | Prevent voidMouse from running multiple instances when started multiple times. 5 | Customize scroll speed 6 | */ 7 | 8 | #define _WIN32_WINNT 0x0400 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | HMODULE hdll = 0; 15 | 16 | int install_hook(void) 17 | { 18 | int ret; 19 | 20 | ret = 0; 21 | 22 | hdll = LoadLibraryW(L"voidmouse.dll"); 23 | if (hdll) 24 | { 25 | void (__stdcall *initializeHook)(void); 26 | 27 | initializeHook = (void (__stdcall *)(void))GetProcAddress(hdll,"initializeHook"); 28 | if (initializeHook) 29 | { 30 | printf("call hook\n"); 31 | initializeHook(); 32 | } 33 | 34 | ret = 1; 35 | } 36 | else 37 | { 38 | printf("no dll %d\n",GetLastError()); 39 | } 40 | 41 | return ret; 42 | } 43 | 44 | void uninstall_hook(void) 45 | { 46 | if (hdll) 47 | { 48 | void (__stdcall *UninitializeHook)(void); 49 | 50 | UninitializeHook = (void (__stdcall *)(void))GetProcAddress(hdll,"UninitializeHook"); 51 | if (UninitializeHook) 52 | { 53 | UninitializeHook(); 54 | } 55 | 56 | FreeLibrary(hdll); 57 | hdll = 0; 58 | } 59 | } 60 | 61 | int WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) 62 | { 63 | MSG msg; 64 | int ret; 65 | 66 | // AllocConsole(); 67 | printf("voidmouse\n"); 68 | 69 | { 70 | HMODULE user32_hmod; 71 | 72 | user32_hmod = GetModuleHandleA("user32.dll"); 73 | if (user32_hmod) 74 | { 75 | printf("user32\n"); 76 | 77 | { 78 | BOOL (WINAPI *SetProcessDpiAwarenessContext_proc)(int value); 79 | 80 | SetProcessDpiAwarenessContext_proc = (void *)GetProcAddress(user32_hmod,"SetProcessDpiAwarenessContext"); 81 | 82 | if (SetProcessDpiAwarenessContext_proc) 83 | { 84 | printf("SetProcessDpiAwarenessContext_proc\n"); 85 | 86 | // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 87 | if (SetProcessDpiAwarenessContext_proc(-4)) 88 | { 89 | printf("SetProcessDpiAwarenessContext_proc OK\n"); 90 | } 91 | else 92 | { 93 | printf("SetProcessDpiAwarenessContext_proc FAILED %u\n",GetLastError()); 94 | } 95 | } 96 | } 97 | /* 98 | { 99 | HANDLE (WINAPI *GetThreadDpiAwarenessContext_proc)(void); 100 | 101 | GetThreadDpiAwarenessContext_proc = (void *)GetProcAddress(user32_hmod,"GetThreadDpiAwarenessContext"); 102 | 103 | if (GetThreadDpiAwarenessContext_proc) 104 | { 105 | HANDLE ctx; 106 | 107 | printf("GetThreadDpiAwarenessContext_proc\n"); 108 | 109 | ctx = GetThreadDpiAwarenessContext_proc(); 110 | if (ctx) 111 | { 112 | int (WINAPI *GetAwarenessFromDpiAwarenessContext_proc)(HANDLE ctx); 113 | 114 | printf("ctx %p\n",ctx); 115 | 116 | GetAwarenessFromDpiAwarenessContext_proc = (void *)GetProcAddress(user32_hmod,"GetAwarenessFromDpiAwarenessContext"); 117 | if (GetAwarenessFromDpiAwarenessContext_proc) 118 | { 119 | int level; 120 | 121 | level = GetAwarenessFromDpiAwarenessContext_proc(ctx); 122 | 123 | printf("DPI awareness level %d\n",level); 124 | } 125 | } 126 | } 127 | }*/ 128 | } 129 | } 130 | 131 | if (!install_hook()) 132 | { 133 | printf("install hook failed\n"); 134 | 135 | return 0; 136 | } 137 | 138 | 139 | loop: 140 | 141 | // update windows 142 | if (PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) 143 | { 144 | ret = (int)GetMessage(&msg,0,0,0); 145 | if (ret <= 0) goto exit_loop; 146 | 147 | // process normally... 148 | TranslateMessage(&msg); 149 | DispatchMessage(&msg); 150 | } 151 | else 152 | { 153 | WaitMessage(); 154 | } 155 | 156 | goto loop; 157 | 158 | exit_loop: 159 | 160 | return 0; 161 | } 162 | 163 | int __cdecl main(int argc,char **argv) 164 | { 165 | return WinMain(0,0,0,0); 166 | } -------------------------------------------------------------------------------- /dllhook/dllhook.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 25 | 28 | 31 | 34 | 37 | 40 | 52 | 55 | 58 | 61 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 94 | 95 | 103 | 106 | 109 | 112 | 115 | 118 | 127 | 130 | 133 | 136 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 168 | 171 | 172 | 173 | 174 | 175 | 176 | 181 | 184 | 185 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /voidmouse.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 9.00 2 | # Visual Studio 2005 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "voidmouse", "voidmouse.vcproj", "{80928F09-680A-45E8-B911-C54A3B865490}" 4 | ProjectSection(ProjectDependencies) = postProject 5 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B} = {BB901D25-D6E9-4921-B8B5-AFAA8B15062B} 6 | EndProjectSection 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dllhook", "dllhook\dllhook.vcproj", "{BB901D25-D6E9-4921-B8B5-AFAA8B15062B}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Debug|x64 = Debug|x64 14 | Release ALPHA|Win32 = Release ALPHA|Win32 15 | Release ALPHA|x64 = Release ALPHA|x64 16 | release BETA|Win32 = release BETA|Win32 17 | release BETA|x64 = release BETA|x64 18 | Release MinDependency|Win32 = Release MinDependency|Win32 19 | Release MinDependency|x64 = Release MinDependency|x64 20 | Release MinSize|Win32 = Release MinSize|Win32 21 | Release MinSize|x64 = Release MinSize|x64 22 | Release|Win32 = Release|Win32 23 | Release|x64 = Release|x64 24 | Unicode Debug|Win32 = Unicode Debug|Win32 25 | Unicode Debug|x64 = Unicode Debug|x64 26 | Unicode Release MinDependency|Win32 = Unicode Release MinDependency|Win32 27 | Unicode Release MinDependency|x64 = Unicode Release MinDependency|x64 28 | Unicode Release MinSize|Win32 = Unicode Release MinSize|Win32 29 | Unicode Release MinSize|x64 = Unicode Release MinSize|x64 30 | EndGlobalSection 31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 32 | {80928F09-680A-45E8-B911-C54A3B865490}.Debug|Win32.ActiveCfg = Debug|Win32 33 | {80928F09-680A-45E8-B911-C54A3B865490}.Debug|Win32.Build.0 = Debug|Win32 34 | {80928F09-680A-45E8-B911-C54A3B865490}.Debug|x64.ActiveCfg = Debug|x64 35 | {80928F09-680A-45E8-B911-C54A3B865490}.Debug|x64.Build.0 = Debug|x64 36 | {80928F09-680A-45E8-B911-C54A3B865490}.Release ALPHA|Win32.ActiveCfg = Release ALPHA|Win32 37 | {80928F09-680A-45E8-B911-C54A3B865490}.Release ALPHA|Win32.Build.0 = Release ALPHA|Win32 38 | {80928F09-680A-45E8-B911-C54A3B865490}.Release ALPHA|x64.ActiveCfg = Release ALPHA|x64 39 | {80928F09-680A-45E8-B911-C54A3B865490}.Release ALPHA|x64.Build.0 = Release ALPHA|x64 40 | {80928F09-680A-45E8-B911-C54A3B865490}.release BETA|Win32.ActiveCfg = release BETA|Win32 41 | {80928F09-680A-45E8-B911-C54A3B865490}.release BETA|Win32.Build.0 = release BETA|Win32 42 | {80928F09-680A-45E8-B911-C54A3B865490}.release BETA|x64.ActiveCfg = release BETA|x64 43 | {80928F09-680A-45E8-B911-C54A3B865490}.release BETA|x64.Build.0 = release BETA|x64 44 | {80928F09-680A-45E8-B911-C54A3B865490}.Release MinDependency|Win32.ActiveCfg = release BETA|x64 45 | {80928F09-680A-45E8-B911-C54A3B865490}.Release MinDependency|x64.ActiveCfg = release BETA|x64 46 | {80928F09-680A-45E8-B911-C54A3B865490}.Release MinDependency|x64.Build.0 = release BETA|x64 47 | {80928F09-680A-45E8-B911-C54A3B865490}.Release MinSize|Win32.ActiveCfg = release BETA|x64 48 | {80928F09-680A-45E8-B911-C54A3B865490}.Release MinSize|x64.ActiveCfg = release BETA|x64 49 | {80928F09-680A-45E8-B911-C54A3B865490}.Release MinSize|x64.Build.0 = release BETA|x64 50 | {80928F09-680A-45E8-B911-C54A3B865490}.Release|Win32.ActiveCfg = Release|Win32 51 | {80928F09-680A-45E8-B911-C54A3B865490}.Release|Win32.Build.0 = Release|Win32 52 | {80928F09-680A-45E8-B911-C54A3B865490}.Release|x64.ActiveCfg = Release|x64 53 | {80928F09-680A-45E8-B911-C54A3B865490}.Release|x64.Build.0 = Release|x64 54 | {80928F09-680A-45E8-B911-C54A3B865490}.Unicode Debug|Win32.ActiveCfg = Debug|Win32 55 | {80928F09-680A-45E8-B911-C54A3B865490}.Unicode Debug|Win32.Build.0 = Debug|Win32 56 | {80928F09-680A-45E8-B911-C54A3B865490}.Unicode Debug|x64.ActiveCfg = Debug|x64 57 | {80928F09-680A-45E8-B911-C54A3B865490}.Unicode Debug|x64.Build.0 = Debug|x64 58 | {80928F09-680A-45E8-B911-C54A3B865490}.Unicode Release MinDependency|Win32.ActiveCfg = Release|x64 59 | {80928F09-680A-45E8-B911-C54A3B865490}.Unicode Release MinDependency|x64.ActiveCfg = Release|x64 60 | {80928F09-680A-45E8-B911-C54A3B865490}.Unicode Release MinDependency|x64.Build.0 = Release|x64 61 | {80928F09-680A-45E8-B911-C54A3B865490}.Unicode Release MinSize|Win32.ActiveCfg = Release|x64 62 | {80928F09-680A-45E8-B911-C54A3B865490}.Unicode Release MinSize|x64.ActiveCfg = Release|x64 63 | {80928F09-680A-45E8-B911-C54A3B865490}.Unicode Release MinSize|x64.Build.0 = Release|x64 64 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Debug|Win32.ActiveCfg = Debug|Win32 65 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Debug|Win32.Build.0 = Debug|Win32 66 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Debug|x64.ActiveCfg = Debug|Win32 67 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release ALPHA|Win32.ActiveCfg = Release|Win32 68 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release ALPHA|Win32.Build.0 = Release|Win32 69 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release ALPHA|x64.ActiveCfg = Release|Win32 70 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.release BETA|Win32.ActiveCfg = Release|Win32 71 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.release BETA|Win32.Build.0 = Release|Win32 72 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.release BETA|x64.ActiveCfg = Release|Win32 73 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release MinDependency|Win32.ActiveCfg = Release|Win32 74 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release MinDependency|Win32.Build.0 = Release|Win32 75 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release MinDependency|x64.ActiveCfg = Release|Win32 76 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release MinSize|Win32.ActiveCfg = Release|Win32 77 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release MinSize|Win32.Build.0 = Release|Win32 78 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release MinSize|x64.ActiveCfg = Release|Win32 79 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release|Win32.ActiveCfg = Release|Win32 80 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release|Win32.Build.0 = Release|Win32 81 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Release|x64.ActiveCfg = Release|Win32 82 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Unicode Debug|Win32.ActiveCfg = Debug|Win32 83 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Unicode Debug|Win32.Build.0 = Debug|Win32 84 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Unicode Debug|x64.ActiveCfg = Debug|Win32 85 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Unicode Release MinDependency|Win32.ActiveCfg = Release|Win32 86 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Unicode Release MinDependency|Win32.Build.0 = Release|Win32 87 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Unicode Release MinDependency|x64.ActiveCfg = Release|Win32 88 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Unicode Release MinSize|Win32.ActiveCfg = Release|Win32 89 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Unicode Release MinSize|Win32.Build.0 = Release|Win32 90 | {BB901D25-D6E9-4921-B8B5-AFAA8B15062B}.Unicode Release MinSize|x64.ActiveCfg = Release|Win32 91 | EndGlobalSection 92 | GlobalSection(SolutionProperties) = preSolution 93 | HideSolutionNode = FALSE 94 | EndGlobalSection 95 | EndGlobal 96 | -------------------------------------------------------------------------------- /dllhook/dllhook.c: -------------------------------------------------------------------------------- 1 | 2 | #define _WIN32_WINNT 0x0400 3 | #include 4 | #include 5 | #include 6 | 7 | HHOOK hhook = 0; 8 | HMODULE hmod = 0; 9 | int isdown=0; 10 | int moved; 11 | int downx; 12 | int downy; 13 | int ofsx; 14 | int ofsy; 15 | int dx; 16 | int dy; 17 | int down_hwnd=0; 18 | HANDLE hthread = 0; 19 | CRITICAL_SECTION cs; 20 | HANDLE hevent = 0; 21 | volatile int terminate = 0; 22 | HWND mclick_hwnd = 0; 23 | int mclick_x; 24 | int mclick_y; 25 | 26 | static DWORD __stdcall thread_proc(void *param); 27 | 28 | 29 | int is_scrollbar_window(wchar_t *classname) 30 | { 31 | if (wcsicmp(classname,L"ScrollBar") == 0) 32 | { 33 | return 1; 34 | } 35 | 36 | return 0; 37 | } 38 | 39 | 40 | int hscroll(HWND hwnd,int x) 41 | { 42 | if (GetWindowLong(hwnd,GWL_STYLE) & WS_HSCROLL) 43 | { 44 | SCROLLINFO si; 45 | 46 | ZeroMemory(&si,sizeof(SCROLLINFO)); 47 | si.cbSize = sizeof(SCROLLINFO); 48 | si.fMask = SIF_POS; 49 | 50 | if (GetScrollInfo(hwnd,SB_HORZ,&si)) 51 | { 52 | if (x > 0) 53 | { 54 | SendMessage(hwnd,WM_HSCROLL,MAKEWPARAM(SB_LINERIGHT,0),(LPARAM)NULL); 55 | 56 | x--; 57 | } 58 | 59 | if (x < 0) 60 | { 61 | SendMessage(hwnd,WM_HSCROLL,MAKEWPARAM(SB_LINELEFT,0),(LPARAM)NULL); 62 | 63 | x++; 64 | } 65 | 66 | return 1; 67 | } 68 | } 69 | 70 | return 0; 71 | } 72 | 73 | int vscroll(HWND hwnd,int y) 74 | { 75 | if (GetWindowLong(hwnd,GWL_STYLE) & WS_VSCROLL) 76 | { 77 | SCROLLINFO si; 78 | 79 | ZeroMemory(&si,sizeof(SCROLLINFO)); 80 | si.cbSize = sizeof(SCROLLINFO); 81 | si.fMask = SIF_POS; 82 | 83 | if (GetScrollInfo(hwnd,SB_VERT,&si)) 84 | { 85 | if (y > 0) 86 | { 87 | SendMessage(hwnd,WM_VSCROLL,MAKEWPARAM(SB_LINEDOWN,0),(LPARAM)NULL); 88 | 89 | y--; 90 | } 91 | 92 | if (y < 0) 93 | { 94 | SendMessage(hwnd,WM_VSCROLL,MAKEWPARAM(SB_LINEUP,0),(LPARAM)NULL); 95 | 96 | y++; 97 | } 98 | 99 | return 1; 100 | } 101 | } 102 | 103 | return 0; 104 | } 105 | 106 | int is_tooltip_window(HWND hwnd) 107 | { 108 | wchar_t classname[MAX_PATH]; 109 | 110 | GetClassName(hwnd,classname,MAX_PATH); 111 | 112 | if (wcscmp(classname,L"tooltips_class32") == 0) 113 | { 114 | return 1; 115 | } 116 | 117 | return 0; 118 | } 119 | 120 | typedef struct myEnumWindowsProcParam_s 121 | { 122 | HWND hwnd; 123 | POINT pt; 124 | 125 | }myEnumWindowsProcParam_t; 126 | 127 | BOOL CALLBACK myEnumWindowsProc(HWND hwnd,LPARAM lParam) 128 | { 129 | RECT rect; 130 | 131 | GetWindowRect(hwnd,&rect); 132 | 133 | if (PtInRect(&rect,((myEnumWindowsProcParam_t *)lParam)->pt)) 134 | { 135 | if (!is_tooltip_window(hwnd)) 136 | { 137 | ((myEnumWindowsProcParam_t *)lParam)->hwnd = hwnd; 138 | 139 | return FALSE; 140 | } 141 | } 142 | 143 | return TRUE; 144 | } 145 | 146 | HWND myWindowFromPoint(POINT pt) 147 | { 148 | myEnumWindowsProcParam_t param; 149 | param.hwnd = 0; 150 | param.pt = pt; 151 | 152 | EnumWindows(myEnumWindowsProc,(LPARAM)¶m); 153 | 154 | if (param.hwnd) 155 | { 156 | EnumChildWindows(param.hwnd,myEnumWindowsProc,(LPARAM)¶m); 157 | } 158 | 159 | return param.hwnd; 160 | } 161 | 162 | int is_vs_window(HWND hwnd) 163 | { 164 | wchar_t classname[MAX_PATH]; 165 | 166 | GetClassName(hwnd,classname,MAX_PATH); 167 | 168 | if (wcscmp(classname,L"VsTextEditPane") == 0) 169 | { 170 | if (GetWindowLong(hwnd,GWL_STYLE) & WS_VSCROLL) 171 | { 172 | return 0; 173 | } 174 | 175 | if (GetWindowLong(hwnd,GWL_STYLE) & WS_HSCROLL) 176 | { 177 | return 0; 178 | } 179 | 180 | return 1; 181 | } 182 | 183 | return 0; 184 | } 185 | 186 | int is_explorer_window(HWND hwnd) 187 | { 188 | wchar_t classname[MAX_PATH]; 189 | 190 | GetClassName(hwnd,classname,MAX_PATH); 191 | 192 | if (wcscmp(classname,L"DirectUIHWND") == 0) 193 | { 194 | return 1; 195 | } 196 | 197 | return 0; 198 | } 199 | 200 | int is_vved_window(HWND hwnd) 201 | { 202 | wchar_t classname[MAX_PATH]; 203 | 204 | GetClassName(hwnd,classname,MAX_PATH); 205 | 206 | if (wcscmp(classname,L"VOID_VECTOR_ED_EDIT") == 0) 207 | { 208 | return 1; 209 | } 210 | 211 | return 0; 212 | } 213 | 214 | int is_ws_scroll_window(HWND hwnd) 215 | { 216 | if ((GetWindowStyle(hwnd) & WS_VSCROLL)) 217 | { 218 | SCROLLINFO si; 219 | 220 | ZeroMemory(&si,sizeof(SCROLLINFO)); 221 | si.cbSize = sizeof(SCROLLINFO); 222 | si.fMask = SIF_POS; 223 | 224 | if (GetScrollInfo(hwnd,SB_VERT,&si)) 225 | { 226 | return 1; 227 | } 228 | } 229 | 230 | if ((GetWindowStyle(hwnd) & WS_HSCROLL)) 231 | { 232 | SCROLLINFO si; 233 | 234 | ZeroMemory(&si,sizeof(SCROLLINFO)); 235 | si.cbSize = sizeof(SCROLLINFO); 236 | si.fMask = SIF_POS; 237 | 238 | if (GetScrollInfo(hwnd,SB_HORZ,&si)) 239 | { 240 | return 1; 241 | } 242 | } 243 | 244 | return 0; 245 | } 246 | 247 | int is_firefox_window(HWND hwnd) 248 | { 249 | wchar_t classname[MAX_PATH]; 250 | 251 | GetClassName(hwnd,classname,MAX_PATH); 252 | 253 | if (wcscmp(classname,L"MozillaWindowClass") == 0) 254 | { 255 | return 1; 256 | } 257 | 258 | return 0; 259 | } 260 | 261 | int is_treeview_window(HWND hwnd) 262 | { 263 | wchar_t classname[MAX_PATH]; 264 | 265 | GetClassName(hwnd,classname,MAX_PATH); 266 | 267 | if (wcscmp(classname,L"SysTreeView32") == 0) 268 | { 269 | return 1; 270 | } 271 | 272 | return 0; 273 | } 274 | 275 | int is_hscroll_hwnd(HWND hwnd) 276 | { 277 | wchar_t classname[MAX_PATH]; 278 | 279 | GetClassName(hwnd,classname,MAX_PATH); 280 | 281 | if (wcscmp(classname,L"ScrollBar") == 0) 282 | { 283 | if (!(GetWindowLong(hwnd,GWL_STYLE) & SBS_VERT)) 284 | { 285 | return 1; 286 | } 287 | } 288 | 289 | return 0; 290 | } 291 | 292 | int is_vscroll_hwnd(HWND hwnd) 293 | { 294 | wchar_t classname[MAX_PATH]; 295 | 296 | GetClassName(hwnd,classname,MAX_PATH); 297 | 298 | if (wcscmp(classname,L"ScrollBar") == 0) 299 | { 300 | if (GetWindowLong(hwnd,GWL_STYLE) & SBS_VERT) 301 | { 302 | return 1; 303 | } 304 | } 305 | 306 | return 0; 307 | } 308 | 309 | BOOL CALLBACK enum_child_hscroll_hwnd_proc(HWND hwnd,LPARAM lParam) 310 | { 311 | if (is_hscroll_hwnd(hwnd)) 312 | { 313 | *((HWND *)lParam) = hwnd; 314 | 315 | return FALSE; 316 | } 317 | 318 | return TRUE; 319 | } 320 | 321 | BOOL CALLBACK enum_child_vscroll_hwnd_proc(HWND hwnd,LPARAM lParam) 322 | { 323 | if (is_vscroll_hwnd(hwnd)) 324 | { 325 | *((HWND *)lParam) = hwnd; 326 | 327 | return FALSE; 328 | } 329 | 330 | return TRUE; 331 | } 332 | 333 | HWND get_child_hscroll_hwnd(HWND parent) 334 | { 335 | HWND hwnd; 336 | 337 | hwnd = 0; 338 | 339 | EnumChildWindows(parent,enum_child_hscroll_hwnd_proc,&hwnd); 340 | 341 | return hwnd; 342 | } 343 | 344 | HWND get_child_vscroll_hwnd(HWND parent) 345 | { 346 | HWND hwnd; 347 | 348 | hwnd = 0; 349 | 350 | EnumChildWindows(parent,enum_child_vscroll_hwnd_proc,&hwnd); 351 | 352 | return hwnd; 353 | } 354 | 355 | int scroll_vs(HWND hwnd,int dx,int dy) 356 | { 357 | if (is_vs_window(hwnd)) 358 | { 359 | int pos; 360 | 361 | // horz 362 | pos = SendMessage(GetDlgItem(GetParent(hwnd),1),SBM_GETPOS,0,0); 363 | 364 | SendMessage(GetDlgItem(GetParent(hwnd),1),SBM_SETPOS,pos + dx,TRUE); 365 | SendMessage(GetParent(hwnd),WM_HSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos + dx),GetDlgItem(GetParent(hwnd),1)); 366 | 367 | // vert 368 | pos = SendMessage(GetDlgItem(GetParent(hwnd),2),SBM_GETPOS,0,0); 369 | 370 | SendMessage(GetDlgItem(GetParent(hwnd),2),SBM_SETPOS,pos + dy,TRUE); 371 | SendMessage(GetParent(hwnd),WM_VSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos + dy),GetDlgItem(GetParent(hwnd),2)); 372 | 373 | return 1; 374 | } 375 | 376 | return 0; 377 | } 378 | 379 | int scroll_vved(HWND hwnd,int dx,int dy) 380 | { 381 | if (is_vved_window(hwnd)) 382 | { 383 | return 1; 384 | } 385 | 386 | return 0; 387 | } 388 | 389 | int scroll_explorer(HWND hwnd,int dx,int dy) 390 | { 391 | if (is_explorer_window(hwnd)) 392 | { 393 | HWND scroll_hwnd; 394 | 395 | scroll_hwnd = get_child_hscroll_hwnd(hwnd); 396 | if (scroll_hwnd) 397 | { 398 | int pos; 399 | 400 | pos = SendMessage(scroll_hwnd,SBM_GETPOS,0,0); 401 | 402 | SendMessage(scroll_hwnd,SBM_SETPOS,pos + dx,TRUE); 403 | SendMessage(scroll_hwnd,WM_HSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos + dx),scroll_hwnd); 404 | } 405 | 406 | scroll_hwnd = get_child_vscroll_hwnd(hwnd); 407 | if (scroll_hwnd) 408 | { 409 | int pos; 410 | 411 | pos = SendMessage(scroll_hwnd,SBM_GETPOS,0,0); 412 | 413 | SendMessage(scroll_hwnd,SBM_SETPOS,pos + (dy * 100),TRUE); 414 | SendMessage(scroll_hwnd,WM_VSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos + (dy * 100)),scroll_hwnd); 415 | } 416 | 417 | return 1; 418 | } 419 | 420 | return 0; 421 | } 422 | 423 | int scroll_ws_scroll(HWND hwnd,int dx,int dy) 424 | { 425 | if (is_ws_scroll_window(hwnd)) 426 | { 427 | int pos; 428 | 429 | if ((GetWindowStyle(hwnd) & WS_VSCROLL)) 430 | { 431 | SCROLLINFO si; 432 | 433 | ZeroMemory(&si,sizeof(SCROLLINFO)); 434 | si.cbSize = sizeof(SCROLLINFO); 435 | si.fMask = SIF_POS; 436 | 437 | if (GetScrollInfo(hwnd,SB_VERT,&si)) 438 | { 439 | pos = si.nPos + dy; 440 | 441 | ZeroMemory(&si,sizeof(SCROLLINFO)); 442 | si.cbSize = sizeof(SCROLLINFO); 443 | si.fMask = SIF_TRACKPOS; 444 | si.nTrackPos = pos; 445 | SetScrollInfo(hwnd,SB_VERT,&si,FALSE); 446 | 447 | SendMessage(hwnd,WM_VSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos),0); 448 | } 449 | } 450 | 451 | if ((GetWindowStyle(hwnd) & WS_HSCROLL)) 452 | { 453 | SCROLLINFO si; 454 | 455 | ZeroMemory(&si,sizeof(SCROLLINFO)); 456 | si.cbSize = sizeof(SCROLLINFO); 457 | si.fMask = SIF_POS; 458 | 459 | if (GetScrollInfo(hwnd,SB_HORZ,&si)) 460 | { 461 | pos = si.nPos + dx; 462 | 463 | ZeroMemory(&si,sizeof(SCROLLINFO)); 464 | si.cbSize = sizeof(SCROLLINFO); 465 | si.fMask = SIF_TRACKPOS; 466 | si.nTrackPos = pos; 467 | SetScrollInfo(hwnd,SB_HORZ,&si,FALSE); 468 | 469 | SendMessage(hwnd,WM_HSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos),0); 470 | } 471 | } 472 | 473 | return 1; 474 | } 475 | 476 | return 0; 477 | } 478 | 479 | 480 | int scroll_firefox(HWND hwnd,int dx,int dy) 481 | { 482 | if (is_firefox_window(hwnd)) 483 | { 484 | int pos; 485 | SCROLLINFO si; 486 | 487 | ZeroMemory(&si,sizeof(SCROLLINFO)); 488 | si.cbSize = sizeof(SCROLLINFO); 489 | si.fMask = SIF_POS; 490 | 491 | GetScrollInfo(hwnd,SB_VERT,&si); 492 | pos = si.nPos; 493 | 494 | // pos = GetScrollPos(hwnd,SB_VERT); 495 | printf("%d\n",pos) ; 496 | SendMessage(hwnd,WM_VSCROLL,MAKEWPARAM(SB_THUMBTRACK, dx),0); 497 | 498 | return 1; 499 | } 500 | 501 | return 0; 502 | } 503 | 504 | int scroll_treeview(HWND hwnd,int dx,int dy) 505 | { 506 | if (is_treeview_window(hwnd)) 507 | { 508 | int pos; 509 | SCROLLINFO si; 510 | 511 | /* 512 | pos = GetScrollPos(hwnd,SB_HORZ); 513 | SetScrollPos(hwnd,SB_HORZ,pos + dx,TRUE); 514 | SendMessage(hwnd,WM_HSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos + dx),0); 515 | */ 516 | 517 | 518 | pos = GetScrollPos(hwnd,SB_VERT); 519 | SendMessage(hwnd,WM_VSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos + dy),hwnd); 520 | 521 | return 1; 522 | } 523 | 524 | return 0; 525 | } 526 | 527 | LRESULT CALLBACK LowLevelMouseProc(int nCode,WPARAM wParam,LPARAM lParam) 528 | { 529 | MSLLHOOKSTRUCT *mhs; 530 | 531 | mhs = (MSLLHOOKSTRUCT *)lParam; 532 | 533 | if (nCode < 0) 534 | { 535 | // do not process the message 536 | 537 | return CallNextHookEx(hhook, nCode, wParam, lParam); 538 | } 539 | 540 | // printf("code %08x: %08x %08x\n",nCode,wParam,lParam); 541 | 542 | if (wParam == WM_MBUTTONDOWN) 543 | { 544 | 545 | // HWND hwnd; 546 | 547 | // hwnd = WindowFromPoint(mhs->pt); 548 | // if (!is_vved_window(hwnd)) 549 | { 550 | EnterCriticalSection(&cs); 551 | isdown = 1; 552 | downx = mhs->pt.x; 553 | downy = mhs->pt.y; 554 | dx = 0; 555 | dy = 0; 556 | moved = 0; 557 | down_hwnd = WindowFromPoint(mhs->pt); 558 | 559 | if (down_hwnd) 560 | { 561 | if (is_tooltip_window(down_hwnd)) 562 | { 563 | down_hwnd = myWindowFromPoint(mhs->pt); 564 | } 565 | } 566 | 567 | LeaveCriticalSection(&cs); 568 | 569 | printf("down2 %d %d\n",downx,downy); 570 | 571 | return -1; 572 | } 573 | } 574 | else 575 | if (wParam == WM_MOUSEMOVE) 576 | { 577 | // printf("moved %d %d\n",mhs->pt.x,mhs->pt.y); 578 | 579 | EnterCriticalSection(&cs); 580 | 581 | if (isdown) 582 | { 583 | dx += (mhs->pt.x - downx); 584 | dy += (mhs->pt.y - downy); 585 | 586 | if ((dx) || (dy)) 587 | { 588 | moved = 1; 589 | } 590 | 591 | LeaveCriticalSection(&cs); 592 | 593 | SetEvent(hevent); 594 | 595 | return -1; 596 | } 597 | 598 | LeaveCriticalSection(&cs); 599 | } 600 | else 601 | if (wParam == WM_MBUTTONUP) 602 | { 603 | int eatit; 604 | 605 | eatit = 0; 606 | 607 | EnterCriticalSection(&cs); 608 | 609 | printf("mup %d %d\n",isdown,moved); 610 | 611 | if (isdown) 612 | { 613 | if (!moved) 614 | { 615 | mclick_hwnd = down_hwnd; 616 | mclick_x = downx; 617 | mclick_y = downy; 618 | 619 | SetEvent(hevent); 620 | } 621 | 622 | eatit = 1; 623 | isdown = 0; 624 | } 625 | LeaveCriticalSection(&cs); 626 | 627 | if (eatit) 628 | { 629 | return -1; 630 | } 631 | } 632 | 633 | return CallNextHookEx(hhook, nCode, wParam, lParam); 634 | } 635 | 636 | __declspec( dllexport ) void __stdcall UninitializeHook(void) 637 | { 638 | if (hhook) 639 | { 640 | UnhookWindowsHookEx(hhook); 641 | 642 | hhook = 0; 643 | } 644 | 645 | terminate = 1; 646 | WaitForSingleObject(hthread,INFINITE); 647 | CloseHandle(hthread); 648 | DeleteCriticalSection(&cs); 649 | CloseHandle(hevent); 650 | } 651 | 652 | __declspec( dllexport ) void __stdcall initializeHook(void) 653 | { 654 | DWORD threadid; 655 | 656 | hevent = CreateEvent(0,FALSE,FALSE,0); 657 | InitializeCriticalSection(&cs); 658 | 659 | hthread = CreateThread(0,0,thread_proc,0,0,&threadid); 660 | 661 | hhook = SetWindowsHookEx(WH_MOUSE_LL,LowLevelMouseProc,hmod,0); 662 | } 663 | 664 | 665 | BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) 666 | { 667 | if (ul_reason_for_call == DLL_PROCESS_ATTACH) 668 | { 669 | hmod = hModule; 670 | } 671 | 672 | return TRUE; 673 | } 674 | 675 | static DWORD __stdcall thread_proc(void *param) 676 | { 677 | // AllocConsole(); 678 | // freopen("CONOUT$", "wt", stdout); 679 | 680 | for(;;) 681 | { 682 | WaitForSingleObject(hevent,INFINITE); 683 | 684 | if (terminate) 685 | { 686 | return 0; 687 | } 688 | 689 | { 690 | POINT p; 691 | int temp_dx; 692 | int temp_dy; 693 | int temp_isdown; 694 | int temp_downx; 695 | int temp_downy; 696 | HWND hwnd; 697 | HWND temp_mclick_hwnd; 698 | int temp_mclick_x; 699 | int temp_mclick_y; 700 | 701 | EnterCriticalSection(&cs); 702 | 703 | /* 704 | if (dx < 0) 705 | { 706 | dx = -(dx * dx); 707 | } 708 | else 709 | { 710 | dx = dx * dx; 711 | } 712 | 713 | dx /= 9; 714 | 715 | if (dy < 0) 716 | { 717 | dy = -(dy * dy); 718 | } 719 | else 720 | { 721 | dy = dy * dy; 722 | } 723 | 724 | dy /= 9; 725 | */ 726 | temp_dx = dx + ofsx; 727 | temp_dy = dy + ofsy; 728 | ofsx = 0; 729 | ofsy = 0; 730 | temp_isdown = isdown; 731 | temp_downx = downx; 732 | temp_downy = downy; 733 | dx = 0; 734 | dy = 0; 735 | hwnd = down_hwnd; 736 | temp_mclick_hwnd = mclick_hwnd; 737 | temp_mclick_x = mclick_x; 738 | temp_mclick_y = mclick_y; 739 | mclick_hwnd = 0; 740 | 741 | LeaveCriticalSection(&cs); 742 | 743 | // move teh window! 744 | p.x = temp_downx; 745 | p.y = temp_downy; 746 | 747 | { 748 | int vs_dy; 749 | 750 | vs_dy = temp_dy / 3; 751 | 752 | if (scroll_vs(hwnd,temp_dx,vs_dy)) 753 | { 754 | ofsy += temp_dy - (vs_dy * 3); 755 | temp_dx = 0; 756 | temp_dy = 0; 757 | } 758 | } 759 | /* 760 | if (scroll_vved(hwnd,temp_dx,temp_dy)) 761 | { 762 | temp_dx = 0; 763 | temp_dy = 0; 764 | } 765 | */ 766 | if (scroll_explorer(hwnd,temp_dx,temp_dy)) 767 | { 768 | temp_dx = 0; 769 | temp_dy = 0; 770 | } 771 | 772 | /* 773 | if (scroll_ws_scroll(hwnd,temp_dx,temp_dy)) 774 | { 775 | temp_dx = 0; 776 | temp_dy = 0; 777 | } 778 | */ 779 | if (is_firefox_window(hwnd)) 780 | { 781 | if (temp_dx) 782 | { 783 | SendMessage(hwnd,0x020E,MAKEWPARAM(0,temp_dx*3),MAKELPARAM(p.x,p.y)); 784 | } 785 | 786 | if (temp_dy) 787 | { 788 | SendMessage(hwnd,WM_MOUSEWHEEL,MAKEWPARAM(0,-temp_dy*3),MAKELPARAM(p.x,p.y)); 789 | } 790 | 791 | temp_dx = 0; 792 | temp_dy = 0; 793 | } 794 | 795 | /* 796 | if (scroll_treeview(hwnd,temp_dx,temp_dy)) 797 | { 798 | temp_dx = 0; 799 | temp_dy = 0; 800 | } 801 | */ 802 | if (temp_dx) 803 | { 804 | if (hscroll(hwnd,temp_dx)) 805 | { 806 | temp_dx = 0; 807 | } 808 | } 809 | 810 | if (temp_dy) 811 | { 812 | if (vscroll(hwnd,temp_dy)) 813 | { 814 | temp_dy = 0; 815 | } 816 | } 817 | 818 | if (temp_dx) 819 | { 820 | int wx; 821 | 822 | wx = temp_dx / WHEEL_DELTA; 823 | 824 | if (wx) SendMessage(hwnd,0x020E,MAKEWPARAM(0,wx * WHEEL_DELTA),MAKELPARAM(p.x,p.y)); 825 | 826 | ofsx += temp_dx - (wx * WHEEL_DELTA); 827 | } 828 | 829 | if (temp_dy) 830 | { 831 | int wy; 832 | 833 | wy = temp_dy / WHEEL_DELTA; 834 | 835 | if (wy) SendMessage(hwnd,WM_MOUSEWHEEL,MAKEWPARAM(0,-wy * WHEEL_DELTA),MAKELPARAM(p.x,p.y)); 836 | 837 | ofsy += temp_dy - (wy * WHEEL_DELTA); 838 | } 839 | 840 | if (temp_mclick_hwnd) 841 | { 842 | POINT pt; 843 | 844 | pt.x = temp_mclick_x; 845 | pt.y = temp_mclick_y; 846 | 847 | ScreenToClient(temp_mclick_hwnd,&pt); 848 | 849 | printf("mclick %d\n",temp_mclick_hwnd); 850 | 851 | PostMessage(temp_mclick_hwnd,WM_MBUTTONDOWN,0,MAKELPARAM(pt.x,pt.y)); 852 | PostMessage(temp_mclick_hwnd,WM_MBUTTONUP,MK_MBUTTON,MAKELPARAM(pt.x,pt.y)); 853 | } 854 | } 855 | 856 | 857 | } 858 | 859 | return 0; 860 | } 861 | 862 | -------------------------------------------------------------------------------- /voidmouse.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 22 | 23 | 24 | 32 | 35 | 38 | 41 | 44 | 47 | 50 | 68 | 71 | 74 | 77 | 93 | 96 | 99 | 102 | 105 | 108 | 111 | 114 | 117 | 118 | 126 | 129 | 132 | 135 | 138 | 141 | 145 | 157 | 160 | 163 | 166 | 176 | 179 | 182 | 185 | 188 | 191 | 194 | 197 | 200 | 201 | 210 | 214 | 217 | 220 | 223 | 226 | 229 | 253 | 256 | 259 | 263 | 283 | 286 | 291 | 294 | 297 | 300 | 303 | 306 | 310 | 311 | 320 | 323 | 326 | 329 | 332 | 335 | 339 | 360 | 363 | 366 | 369 | 387 | 390 | 395 | 398 | 401 | 404 | 407 | 410 | 413 | 414 | 423 | 427 | 430 | 433 | 436 | 439 | 442 | 466 | 469 | 472 | 476 | 496 | 499 | 505 | 508 | 511 | 514 | 517 | 520 | 524 | 525 | 534 | 537 | 540 | 543 | 546 | 549 | 553 | 574 | 577 | 580 | 583 | 601 | 604 | 610 | 613 | 616 | 619 | 622 | 625 | 628 | 629 | 638 | 642 | 645 | 648 | 651 | 654 | 657 | 681 | 684 | 687 | 691 | 711 | 714 | 720 | 723 | 726 | 729 | 732 | 735 | 739 | 740 | 749 | 752 | 755 | 758 | 761 | 764 | 768 | 789 | 792 | 795 | 798 | 816 | 819 | 825 | 828 | 831 | 834 | 837 | 840 | 843 | 844 | 845 | 846 | 847 | 848 | 852 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | --------------------------------------------------------------------------------