Files
2026-04-17 14:55:32 -04:00

169 lines
8.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- Common/DTS.Common/Classes/WinApi/WindowsAPIHelpers.cs
generated_at: "2026-04-16T03:16:58.945801+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "32ac28362ec2b57c"
---
# WinApi
## Documentation: `WindowsAPIHelpers.cs`
---
### 1. **Purpose**
This module provides interoperability helpers for Windows API integration, specifically to support custom window sizing and positioning behavior in WPF applications. It defines P/Invoke-compatible structures (`POINT`, `RECT`, `MINMAXINFO`, `MONITORINFO`, `WINDOWPOS`, `WM`, `SWP`) and exposes two Win32 functions (`GetMonitorInfo`, `MonitorFromWindow`) to enable accurate adjustment of a windows maximized size and position to match the *work area* of the monitor on which the window resides—rather than the full screen (which may include taskbars or other non-client areas). This is typically used in response to the `WM_GETMINMAXINFO` message to prevent maximized windows from overlapping system UI elements.
---
### 2. **Public Interface**
#### Structs
- **`POINT`**
```csharp
[StructLayout(LayoutKind.Sequential)]
public struct POINT { public int x; public int y; public POINT(int x, int y); }
```
Represents a point in 2D space with integer coordinates. Used as a field in other structures.
- **`RECT`**
```csharp
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct RECT
{
public int left, top, right, bottom;
public static readonly RECT Empty;
public int Width { get; }
public int Height { get; }
public RECT(int left, int top, int right, int bottom);
public bool IsEmpty { get; }
public override string ToString();
public override bool Equals(object obj);
public override int GetHashCode();
public static bool operator ==(RECT, RECT);
public static bool operator !=(RECT, RECT);
}
```
Represents a rectangle with integer coordinates. Includes computed `Width` and `Height` properties, equality operators, and an `IsEmpty` check (true if `left >= right` or `top >= bottom`). Note: `Height` is computed as `bottom - top` (not `Math.Abs`), so negative heights are possible if `bottom < top`.
- **`MINMAXINFO`**
```csharp
[StructLayout(LayoutKind.Sequential)]
public struct MINMAXINFO
{
public POINT ptReserved;
public POINT ptMaxSize;
public POINT ptMaxPosition;
public POINT ptMinTrackSize;
public POINT ptMaxTrackSize;
}
```
Used to convey minimum/maximum tracking and maximized window geometry. Populated 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;
}
```
Contains monitor-specific information. `cbSize` is auto-initialized to the unmanaged size of the struct. `rcMonitor` is the full monitor rectangle; `rcWork` is the work area (excluding taskbars, etc.).
- **`WINDOWPOS`**
```csharp
[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPOS
{
public IntPtr hwnd;
public IntPtr hwndInsertAfter;
public int x, y, cx, cy;
public int flags;
}
```
Used in `WM_WINDOWPOSCHANGING`/`WM_WINDOWPOSCHANGED` messages. Not used directly in this file but defined for completeness.
#### Enums
- **`WM`**
```csharp
public enum WM { WINDOWMAX = 0x0024, WINDOWPOSCHANGING = 0x0046; }
```
Windows message constants. `WINDOWMAX` is likely a typo or nonstandard alias (standard is `WM_SYSCOMMAND` with `SC_MAXIMIZE`, or `WM_SIZE` with `SIZE_MAXIMIZED`). `WINDOWPOSCHANGING` is `WM_WINDOWPOSCHANGING`.
- **`SWP`**
```csharp
public enum SWP { NOMOVE = 0x0002; }
```
Flags for `SetWindowPos`. `NOMOVE` preserves current position.
#### Methods
- **`GetMinMaxInfo(IntPtr hwnd, IntPtr lParam)`**
```csharp
public static void GetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
```
Handles the `WM_GETMINMAXINFO` message by adjusting `ptMaxSize` and `ptMaxPosition` in the `MINMAXINFO` structure to fit the *work area* of the monitor containing `hwnd`. Uses `MonitorFromWindow` with `MONITOR_DEFAULTTONEAREST` (`0x00000002`) to locate the monitor, then calls `GetMonitorInfo` to retrieve monitor geometry. Writes the modified `MINMAXINFO` back to `lParam`.
#### P/Invoke Exports
- **`GetMonitorInfo`**
```csharp
[DllImport("user32")]
public static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
```
Retrieves monitor information. Caller must initialize `MONITORINFO.cbSize` before calling.
- **`MonitorFromWindow`**
```csharp
[DllImport("User32")]
public static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
```
Returns a handle to the monitor that contains the window. `flags` is typically `MONITOR_DEFAULTTONEAREST` (`0x00000002`).
---
### 3. **Invariants**
- `MONITORINFO.cbSize` **must** be set to `Marshal.SizeOf(typeof(MONITORINFO))` before calling `GetMonitorInfo`; otherwise, the call will fail (returns `false`).
- `RECT.IsEmpty` is defined as `left >= right || top >= bottom`. This implies a rectangle with `left == right` or `top == bottom` is considered empty.
- `RECT.Height` is computed as `bottom - top` (not `Math.Abs(bottom - top)`), so if `bottom < top`, `Height` is negative. This may indicate an inverted rectangle (e.g., from drag-select), but the code does not enforce non-negative height.
- `GetMinMaxInfo` assumes the window is on a valid monitor. If `MonitorFromWindow` returns `IntPtr.Zero`, no adjustment is made, and the original `MINMAXINFO` values are preserved.
- The `ptMaxPosition` values are computed as absolute offsets from the monitors left/top edge (`Math.Abs(rcWorkArea.left - rcMonitorArea.left)`), which correctly yields the top-left corner of the work area relative to the monitor.
---
### 4. **Dependencies**
#### Dependencies *on* this module:
- **WPF/Win32 interop layer**: This module is intended for use in WPF applications (evidenced by `System.Windows` namespace usage, though not directly referenced in this file). Likely consumed by window message handlers (e.g., `Window.SourceInitialized` or `OnSourceInitialized` overrides) to subclass window procedures and handle `WM_GETMINMAXINFO`.
- **`System.Runtime.InteropServices`**: Required for `StructLayout`, `DllImport`, `Marshal.PtrToStructure`, and `Marshal.StructureToPtr`.
#### Dependencies *of* this module:
- **`user32.dll`**: For `GetMonitorInfo` and `MonitorFromWindow`.
- **No external libraries beyond .NET Framework core types** (no NuGet dependencies implied).
#### Known consumers (inferred):
- Any class handling `WM_GETMINMAXINFO` (e.g., via `HwndSource.AddHook`) will call `WindowsAPIHelpers.GetMinMaxInfo`.
- Likely used in custom window management logic (e.g., `MainWindow.xaml.cs` or a base window class).
---
### 5. **Gotchas**
- **`RECT.Height` is *not* absolute**: `Height => bottom - top` (not `Math.Abs`). This may cause unexpected negative heights if rectangles are inverted. Use `Math.Abs` externally if needed.
- **`MONITORINFO` is a `class`, not a `struct`**: This is unusual for P/Invoke marshaling (typically `struct` is preferred). While it works due to `StructLayout`, it introduces heap allocation and reference semantics. Ensure the instance is not reused across threads without synchronization.
- **`WINDOWMAX` enum value is nonstandard**: The Win32 constant for maximization is `WM_SYSCOMMAND` with `SC_MAXIMIZE` (0xF030), not `0x0024`. `0x0024` is `WM_USER + 36` in some contexts but not a standard system message. This may be a typo or internal alias.
- **`rcMonitor` vs `rcWork` semantics**: `rcMonitor` is the full monitor bounds; `rcWork` excludes taskbars, etc. The code correctly uses `rcWork` for `ptMaxSize`/`ptMaxPosition`, but callers must understand this distinction.
- **No validation of `lParam` in `GetMinMaxInfo`**: Assumes `lParam` points to a valid `MINMAXINFO` structure. Passing `IntPtr.Zero` or invalid memory will cause a crash.
- **Missing `WM` constants**: Only two `WM` values are defined (`WINDOWMAX`, `WINDOWPOSCHANGING`). Other common messages (e.g., `WM_SIZE`, `WM_GETMINMAXINFO`) are not included, suggesting this is a partial set.
- **`MONITOR_DEFAULTTONEAREST` flag is hardcoded**: The `MonitorFromWindow` call uses `0x00000002` directly instead of a named constant (e.g., `MONITOR_DEFAULTTONEAREST = 2`). While correct, it reduces readability.
None identified beyond these.