This page introduces WinSyncScroll, a Windows desktop application that synchronizes scrolling between two windows in real-time. It explains what the application does, its key capabilities, high-level architecture, and operational modes.
For detailed information about specific subsystems, see:
Sources: README.md1-63
WinSyncScroll is a Windows-native application that enables users to scroll two windows simultaneously. When the user scrolls in a designated source window, the application automatically replicates the scroll action in a designated target window, maintaining synchronized viewing positions across both windows.
The application operates by intercepting low-level mouse events at the system level using Windows hooks (SetWindowsHookEx), processing those events through coordinate transformation logic, and then forwarding synthetic scroll events to the target window using either modern input simulation (SendInput) or legacy message posting (PostMessage).
Sources: README.md1-22 WinSyncScroll/ViewModels/MainViewModel.cs1-631
| Capability | Description |
|---|---|
| Real-time Scroll Synchronization | Captures scroll events (vertical and horizontal) from source window and replicates them in target window |
| Coordinate Transformation | Transforms mouse coordinates from source window space to target window space, accounting for window position and size differences |
| Dual Operational Modes | Supports both Standard mode (SendInput API) and Legacy mode (PostMessage API) for maximum compatibility |
| Window Selection | Provides UI for selecting any visible window as source or target from system-wide window enumeration |
| Process-Level Filtering | Optional strict process ID checking to prevent unintended scrolling when windows overlap |
| Multi-Framework Support | Targets both .NET 10.0 and .NET Framework 4.6.2 for broad Windows compatibility |
Sources: README.md15-48 WinSyncScroll/ViewModels/MainViewModel.cs60-65
The following diagram shows the primary architectural components using actual class names from the codebase:
Key Component Roles:
MainViewModel: Central orchestrator that manages application state, processes scroll events, transforms coordinates, and dispatches synthetic inputMouseHook: Installs low-level mouse hook using SetWindowsHookEx, filters events, and publishes relevant scroll events to a channelWinApiService: Enumerates system windows using EnumWindows, retrieves window metadata, and filters based on visibilityGeneralOptions: Strongly-typed configuration model loaded from appsettings.json with operational mode settingsWindowInfo: Immutable record containing window metadata (handle, process ID, window name, class name)Sources: WinSyncScroll/ViewModels/MainViewModel.cs28-124
The following sequence diagram illustrates how scroll events flow through the system from user action to target window scrolling, using actual method and API names:
Flow Stages:
MouseHook.LowLevelMouseProc receives WM_MOUSEWHEEL or WM_MOUSEHWHEEL from WindowsSourceRectHookEvents channel as MouseMessageInfo objectsMainViewModel.RunMouseEventProcessingLoopAsync reads from channel asynchronouslyAppState == Running and that source/target are selected and differentCalculateAbsoluteCoordinatesSendInput (Standard) or PostMessage (Legacy)1 to prevent original scroll from executingSources: WinSyncScroll/ViewModels/MainViewModel.cs225-408 README.md20-22
WinSyncScroll supports two distinct operational modes configured via appsettings.json:
Characteristics:
SendInput API with MOUSEEVENTF_WHEEL or MOUSEEVENTF_HWHEEL flagsINPUT structures: move to target → scroll → move back to sourceIsLegacyModeEnabled = false in configurationSources: WinSyncScroll/ViewModels/MainViewModel.cs139-183 WinSyncScroll/ViewModels/MainViewModel.cs343-360
Characteristics:
PostMessage API with WM_MOUSEWHEEL or WM_MOUSEHWHEEL messagesLegacyModeBehaviour enum: ParentOnly: Posts message only to target window handleChildrenOnly: Posts message only to child windowsBoth: Posts message to target and all visible child windowsIsLegacyModeEnabled = true in configurationSources: WinSyncScroll/ViewModels/MainViewModel.cs361-400 README.md28-36
The following table maps high-level system responsibilities to concrete implementation classes:
| Responsibility | Primary Class/File | Key Methods/Properties |
|---|---|---|
| UI Presentation | MainWindow (XAML) | Window layout, button bindings, ComboBox for window selection |
| State Orchestration | MainViewModel | RefreshWindowsAsync(), Start(), Stop(), RunMouseEventProcessingLoopAsync() |
| Event Interception | MouseHook | Install(), Uninstall(), LowLevelMouseProc(), HookEvents channel |
| Window Enumeration | WinApiService | ListWindows() |
| Configuration | appsettings.json + GeneralOptions | IsLegacyModeEnabled, IsStrictProcessIdCheckEnabled, LegacyModeBehaviour |
| Window Metadata | WindowInfo | WindowHandle, ProcessId, WindowName, ClassName, ProcessName |
| Coordinate Math | WinApiUtils | IsPointInRect(), GetHiLoWords() |
| DI Bootstrap | ContainerConfigurationUtils | Service registration, configuration binding |
| Application State | AppState enum | NotRunning, Running |
Sources: WinSyncScroll/ViewModels/MainViewModel.cs28-124 README.md24-40
WinSyncScroll is built as a Windows-specific application with the following requirements:
Sources: README.md42-48 WinSyncScroll/ViewModels/MainViewModel.cs66-68