You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While dragging a window by holding left click, right click in the grid section you want to resize from, continue dragging left click to the grid section you want to resize to and press right click again or let go of left click.
Double click the quickbar icon to launch settings.
Settings will be saved in your %appdata% folder.
If you select the option to run at startup, it will make an entry in shell:startup (you can go there in file explorer).
π» For Developers
Prerequisites
Visual Studio 2022 or VS Code.
.NET 10.0 SDK.
Windows OS (Required for Win32 API and WPF).
Building the Project
Clone the repository.
Open a terminal in the project root.
Run the following commands:
dotnet build
dotnet run
To build a production executable to the publish folder:
Installs a low-level mouse hook (WH_MOUSE_LL) to capture mouse events globally across all windows. Exposes events for left/right button and mouse movement.
The brain of the app. Listens to GlobalHook events, detects when a user is dragging a window + right-clicks, breaks the native drag loop, and spawns the GridOverlay.
Singleton that manages user preferences (grid dimensions per monitor, colors, dark mode, run-on-startup). Persists to %appdata%/TheGriddler/settings.json. Implements INotifyPropertyChanged for reactive WPF bindings.
A transparent, click-through WPF window that covers the active monitor. Renders a grid based on the monitor's configured rows/columns and handles selection rectangle drawing. Calculates physical pixel coordinates for snapping and applies DPI compensation for cross-monitor scenarios.
The settings UI allowing users to configure grid dimensions per monitor, pick colors, toggle dark mode, and enable run-on-startup.
π§ Windows APIs Used
The Griddler relies heavily on Win32 APIs via P/Invoke to achieve system-wide window management. All API declarations are centralized in Core/NativeMethods.cs.
Gets the current module handle for hook installation.
π Architecture & Design
Core Flow
Startup: App.xaml.cs initializes MainController and creates a system tray icon.
Hooking: GlobalHook installs a WH_MOUSE_LL hook to monitor all mouse events.
Drag Detection: When a right-click occurs while the left button is held, MainController checks if the foreground window is in a move/size loop using GetGUIThreadInfo.
Break Drag: If confirmed, WindowManager.BreakDragLoop sends WM_CANCELMODE and WM_LBUTTONUP to interrupt the native drag.
Overlay Display: A GridOverlay window is spawned covering the current monitor, showing a configurable grid.
Selection: Mouse movement updates the selection rectangle. On completion (right-click or left release), SnapAsync calculates target bounds in physical pixels.
Snapping: SetWindowPos moves/resizes the window to the selected grid cells. DPI compensation is applied for Per-Monitor DPI aware apps.
Design Principles
Separation of Concerns: UI logic in Views, native interop in Core, state in Models.
Reactive Settings: Settings implements INotifyPropertyChanged for automatic UI updates.
Per-Monitor Support: Grid dimensions and DPI handling work correctly across multi-monitor setups.
Minimal Footprint: Runs as a system tray app with no main window.
π Credits
Created by derac.
Inspired by WindowGrid by Joshua Wilding.
Happy Gridding!
About
The Griddler is a lightweight window management tool for Windows that allows you to snap windows to a configurable grid using your mouse. Inspired by WindowGrid.