WinForms Host
The WinForms host embeds the engine inside a WinForms window and drives it from the form's UI thread. Its UI is deliberately minimal: a panel the game renders into and a working Pause/Resume button, ready to be extended with your own controls.
It is Windows-only at runtime, so it is never part of the default host set - add it explicitly:
2dog add --winforms # existing project
dotnet new 2dog -n MyGame --winforms true # new projectThen run it (on Windows):
dotnet run --project MyGame.winformsThe repository's own instance is demos/showcase/showcase.winforms.
How It Works
Godot 4.7 supports embedding out of the box via the --wid <window_id> argument – the same mechanism the Godot editor uses for its embedded game window. Given a native window handle, the engine creates its main window as a borderless popup owned by that handle instead of a regular top-level window. Because 2dog hosts pass arguments to Godot verbatim, no engine or API changes are involved:
_engine = new Engine("MyGame", Engine.ResolveProjectDir(),
[
"--wid", Handle.ToInt64().ToString(CultureInfo.InvariantCulture),
"--resolution", $"{panel.ClientSize.Width}x{panel.ClientSize.Height}",
"--position", "0,0",
]);Three consequences shape the host code:
- The host owns geometry. The embedded popup lives in screen coordinates and Godot refuses
window_set_sizefor it, so the form drives the window with rawSetWindowPosfromResizeandLocationChangedhandlers – exactly how the editor drives its embedded game window. - The host owns the frame loop. A classic WinForms game loop pumps
Iteration()fromApplication.Idlewhenever the message queue is empty, so Godot frames and UI events interleave on one STA thread, and WinForms event handlers can touch the scene tree directly. - Teardown happens before the owner window dies. The form disposes the instance and engine in
OnFormClosing, while its own handle still exists.
The Pause button pauses and resumes the running instance via GodotInstance.Pause()/Resume() straight from its click handler - the UI thread is the pump thread, so game state (including the scene tree via engine.Tree) is safe to touch from event handlers.
Limitations
- Windows only. The same
--widroute works on X11, so an Avalonia host could cover Linux; macOS would need Godot's separateembeddeddisplay server. (The project still restores and builds on Linux/macOS thanks toEnableWindowsTargeting; it just cannot run there.) - The embedded window always draws above the form's client area, so WinForms controls cannot overlap the game rectangle.
--widmarks the instance as embedded (Engine.is_embedded_in_editor()returnstrueto scripts).