--- source_files: - Common/DTS.CommonCore/Classes/WinApi/WindowsAPIHelpers.cs generated_at: "2026-04-16T02:41:05.548844+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "74033c59308d77b1" --- # WinApi ## Documentation: `WindowsAPIHelpers.cs` --- ### 1. **Purpose** This module provides low-level Windows API interop helpers for managing window placement and sizing behavior, specifically to ensure that maximized windows align with the *work area* (i.e., excluding taskbar, docked toolbars) of the appropriate monitor in multi-monitor setups. It defines P/Invoke signatures and supporting structures (`POINT`, `RECT`, `MINMAXINFO`, `MONITORINFO`, `WINDOWPOS`) and exposes a helper method `GetMinMaxInfo` that adjusts the `ptMaxSize` and `ptMaxPosition` fields of a `MINMAXINFO` structure during a `WM_GETMINMAXINFO` message. This ensures windows maximize correctly to the visible screen area of the monitor containing the window, rather than the primary monitor’s full screen bounds. --- ### 2. **Public Interface** #### Structs & Classes - **`POINT`** ```csharp [StructLayout(LayoutKind.Sequential)] public struct POINT { public int x; public int y; public POINT(int x, int y); } ``` Represents a point in screen coordinates. Used as a field in `MINMAXINFO` and elsewhere. - **`MINMAXINFO`** ```csharp [StructLayout(LayoutKind.Sequential)] public struct MINMAXINFO { public POINT ptReserved; public POINT ptMaxSize; public POINT ptMaxPosition; public POINT ptMinTrackSize; public POINT ptMaxTrackSize; } ``` Used in `WM_GETMINMAXINFO` to specify minimum/maximum tracking sizes and maximized window geometry. The `ptMaxSize` and `ptMaxPosition` fields are modified by `GetMinMaxInfo`. - **`MONITORINFO`** ```csharp [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class MONITORINFO { public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); public RECT rcMonitor = new RECT(); public RECT rcWork = new RECT(); public int dwFlags = 0; } ``` Container for monitor-specific information. `cbSize` is auto-initialized to the correct size. `rcMonitor` holds the full monitor bounds; `rcWork` holds the work area (usable screen space). - **`RECT`** ```csharp [StructLayout(LayoutKind.Sequential, Pack = 0)] public struct RECT { public int left, top, right, bottom; public static readonly RECT Empty; public int Width => Math.Abs(right - left); public int Height => bottom - top; public bool IsEmpty => left >= right || top >= bottom; // ... constructors, equality, operators ... } ``` Represents a rectangle in screen coordinates. Includes computed properties (`Width`, `Height`, `IsEmpty`) and value-based equality (`==`, `!=`, `Equals`, `GetHashCode`). Note: `Height` is computed as `bottom - top` (not `Math.Abs`), so negative heights are possible if `bottom < top`. - **`WINDOWPOS`** ```csharp [StructLayout(LayoutKind.Sequential)] public struct WINDOWPOS { public IntPtr hwnd; public IntPtr hwndInsertAfter; public int x, y, cx, cy; public int flags; } ``` Mirrors the Win32 `WINDOWPOS` structure used in `WM_WINDOWPOSCHANGING`/`WM_WINDOWPOSCHANGED`. #### Enums - **`WM`** ```csharp public enum WM { WINDOWMAX = 0x0024, WINDOWPOSCHANGING = 0x0046 } ``` Subset of Windows message constants. *Note:* `WINDOWMAX` is likely a typo/misnomer for `WM_WINDOWMAXIMIZED` (which does not exist); standard `WM_SYSCOMMAND` with `SC_MAXIMIZE` is more common. `WINDOWPOSCHANGING` is correctly `WM_WINDOWPOSCHANGING`. - **`SWP`** ```csharp public enum SWP { NOMOVE = 0x0002 } ``` Subset of `SetWindowPos` flags. `NOMOVE` preserves current position when resizing. #### Methods - **`GetMinMaxInfo(IntPtr hwnd, IntPtr lParam)`** ```csharp public static void GetMinMaxInfo(IntPtr hwnd, IntPtr lParam) ``` Reads a `MINMAXINFO` structure from `lParam`, queries the monitor containing `hwnd`, retrieves its work area (`rcWork`) and full monitor area (`rcMonitor`), then updates `mmi.ptMaxPosition` and `mmi.ptMaxSize` to align the maximized window with the work area of the *current* monitor. Writes the modified structure back to `lParam`. This is intended to be called in response to `WM_GETMINMAXINFO` (0x0024). - **`GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi)`** ```csharp [DllImport("user32")] public static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi); ``` P/Invoke wrapper for `GetMonitorInfoW`. Fills `lpmi` with monitor data. Caller must set `lpmi.cbSize` (handled by `MONITORINFO`’s field initializer). - **`MonitorFromWindow(IntPtr handle, int flags)`** ```csharp [DllImport("User32")] public static extern IntPtr MonitorFromWindow(IntPtr handle, int flags); ``` P/Invoke wrapper for `MonitorFromWindow`. Returns `IntPtr.Zero` on failure. Used with `MONITOR_DEFAULTTONEAREST` (`0x00000002`). --- ### 3. **Invariants** - **`MONITORINFO.cbSize` must be set correctly before calling `GetMonitorInfo`**: The `MONITORINFO` class initializes `cbSize` to `Marshal.SizeOf(typeof(MONITORINFO))` in its field initializer, ensuring correctness for P/Invoke. - **`RECT` dimensions assume left ≤ right and top ≤ bottom**: `Width` uses `Math.Abs(right - left)`, but `Height` does *not* (`bottom - top`). If `bottom < top`, `Height` will be negative. No validation enforces non-negative dimensions. - **`GetMinMaxInfo` modifies `ptMaxSize` and `ptMaxPosition` only**: Other `MINMAXINFO` fields (`ptReserved`, `ptMinTrackSize`, `ptMaxTrackSize`) are preserved as-is. - **Monitor query uses `MONITOR_DEFAULTTONEAREST`**: If `hwnd` is invalid or no monitor contains it, `MonitorFromWindow` returns `IntPtr.Zero`, and `GetMinMaxInfo` skips modification (no crash, but no adjustment either). --- ### 4. **Dependencies** - **Runtime Dependencies**: - `System.Runtime.InteropServices` (for `StructLayout`, `Marshal`, `DllImport`) - `System.Windows` (though no WPF types are used in this file—likely a legacy/unused reference) - Win32 `user32.dll` (for `GetMonitorInfo`, `MonitorFromWindow`) - **Consumers (inferred)**: This module is designed to be used by code handling `WM_GETMINMAXINFO` (e.g., in a WPF/WinForms window procedure). The method `GetMinMaxInfo` is called with the window handle and `lParam` from the message. No other direct dependencies are visible in the source. - **Missing Dependencies**: - `RECT` is used but not defined in this file—*this is a contradiction*. The source defines `RECT` here, but the `RECT` used in `MONITORINFO` is initialized as `new RECT()`. This implies `RECT` must be defined *here* (and it is), so no external dependency is needed. - No `using` for `System.Drawing` or other types—`RECT` is self-contained. --- ### 5. **Gotchas** - **`RECT.Height` is not absolute**: `Height => bottom - top` (not `Math.Abs`). If `bottom < top`, `Height` is negative. This may cause unexpected behavior if consumers assume non-negative height. - **`MONITORINFO` is a `class`, not a `struct`**: This is unusual for P/Invoke marshaling (where `struct` is typical). While it works due to `cbSize` initialization and `Marshal.PtrToStructure`/`StructureToPtr`, using a `class` here risks reference-type semantics (e.g., accidental sharing). A `struct` would be safer and more conventional. - **`GetMinMaxInfo` silently fails if monitor query fails**: If `MonitorFromWindow` returns `IntPtr.Zero` (e.g., invalid `hwnd`), no adjustment occurs. No error is logged or thrown—consumers must verify behavior. - **`WM.WINDOWMAX` is likely incorrect**: `0x0024` is `WM_SYSCOMMAND`, not a maximization message. `WM_GETMINMAXINFO` is `0x0024`—*this is the same value*. The enum name `WINDOWMAX` is misleading; it should be `GETMINMAXINFO`. This is a naming bug. - **`RECT.IsEmpty` uses `>=` (not `>`)**: `IsEmpty => left >= right || top >= bottom` correctly handles degenerate rectangles (e.g., `left == right`), but consumers may overlook that empty rectangles have zero area. - **No thread-safety guarantees**: `GetMinMaxInfo` mutates a `MINMAXINFO` via `Marshal.PtrToStructure`/`StructureToPtr`. While the operation is read-modify-write on a *copy* (safe), the use of `MONITORINFO` as a `class` (reference type) could introduce issues if reused across threads without copying. - **`MONITORINFO.rcMonitor` and `rcWork` are initialized to `new RECT()`**: `RECT()` sets all fields to `0`, so `rcMonitor` and `rcWork` start as `(0,0,0,0)`. This is safe for P/Invoke since `GetMonitorInfo` overwrites them. - **No handling of DPI scaling**: All coordinates are in *physical* pixels (Win32 convention). If the application is DPI-aware, callers must ensure `hwnd` corresponds to the correct DPI context. No DPI scaling is applied in `GetMinMaxInfo`. --- *No other issues are apparent from the source alone.*