huh4k ~/dev
Case Study

CS2 Stretched Launcher & Display Engine

Native Windows system utility written in C# and .NET 9.0 using Win32 display APIs to dynamically enforce 1280×960 stretched resolution and restore native 1080p.

C# .NET 9.0 Win32 APIs P/Invoke Systems

Overview

Competitive Counter-Strike 2 players predominantly play on stretched 4:3 resolutions (commonly 1280×960) to enlarge player models and maximize monitor refresh rates. However, running a 4:3 resolution in borderless windowed mode or switching monitor modes manually across multiple displays is tedious and often scrambles desktop window layouts.

CS2 Stretched Launcher is a lightweight Windows utility written in C# that interfaces directly with Windows display subsystem APIs (User32.dll) to provide seamless, automated display switching.


Architectural Highlights

  • Direct Win32 P/Invoke: Bypasses slow third-party resolution utilities by directly calling EnumDisplaySettings and ChangeDisplaySettingsEx in user32.dll.
  • Registry & Display Device Targeting: Identifies the primary active display device and commits display changes directly to the registry (CDS_UPDATEREGISTRY).
  • Steam Protocol Dispatch: Triggers Counter-Strike 2 via Steam’s URI protocol handler (steam://rungameid/730).
  • Process Lifecycle Watchdog: Monitors the target cs2.exe process lifecycle asynchronously. The moment the game terminates, the utility catches the exit event and immediately restores the native resolution (e.g. 1920×1080 @ 240Hz).
// Win32 Resolution Switch Implementation
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettingsEx(
    string? lpszDeviceName, 
    ref DEVMODE lpDevMode, 
    IntPtr hwnd, 
    uint dwflags, 
    IntPtr lParam
);

public static void SwitchResolution(int width, int height)
{
    DEVMODE dm = default;
    dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
    dm.dmPelsWidth = width;
    dm.dmPelsHeight = height;
    dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;

    ChangeDisplaySettingsEx(null, ref dm, IntPtr.Zero, CDS_UPDATEREGISTRY, IntPtr.Zero);
}

Performance & Packaging

  • Built against .NET 9.0 with standalone Ahead-Of-Time (AOT) trimmed compilation options for zero-dependency execution.
  • Negligible memory footprint (<15MB RAM during game execution).