Core Window Guide
This guide covers everything available through the InfiniLore.InfiniFrame package — the foundation of all InfiniFrame integrations
Contents
- Building a Window
- Window Configuration
- Browser Features
- Runtime Window Control
- Events
- Web Messaging
- Custom URL Schemes
- Dialogs
- Monitor Information
- DI Container Integration
Building a Window
All windows are created through InfiniFrameWindowBuilder using a fluent API
using InfiniFrame;
var window = InfiniFrameWindowBuilder.Create()
.SetTitle("My App")
.SetSize(1280, 720)
.Center()
.SetStartUrl("https://myapp.local")
.Build();
window.WaitForClose();
Build() creates and displays the native window immediately on the calling thread
The returned IInfiniFrameWindow gives you full control over the window at runtime
Window Configuration
All configuration methods are chainable and must be called before Build()
Title and Icon
builder
.SetTitle("My Application")
.SetIconFile("assets/icon.ico") // Windows and Linux only; .ico on Windows, .png on Linux
Size and Position
builder
.SetSize(1280, 720) // Width × Height
.SetMinSize(800, 600)
.SetMaxSize(1920, 1080)
.SetLocation(100, 100) // Left, Top in screen coordinates
.Center() // Center on the primary monitor
.SetUseOsDefaultSize(true) // Let the OS choose the initial size
.SetUseOsDefaultLocation(true)
Calling SetSize or SetLocation disables the corresponding OS default and centering behavior
Window State
builder
.SetMaximized(true)
.SetMinimized(true)
.SetFullScreen(true)
.SetResizable(false)
.SetTopMost(true) // Always on top
.SetChromeless(true) // Remove the native title bar and borders
.SetTransparent(true) // Enable window transparency
On Windows, enabling SetChromeless automatically disables UseOsDefaultLocation, UseOsDefaultSize, and Resizable since they are incompatible
Content
builder
.SetStartUrl("https://example.com")
.SetStartUrl(new Uri("https://example.com"))
.SetStartString("<html><body>Hello</body></html>") // Render HTML directly
SetStartUrl and SetStartString are mutually exclusive — the last one set wins
Browser Features
builder
.SetDevToolsEnabled(true)
.SetContextMenuEnabled(false)
.SetZoomEnabled(false)
.SetZoom(150) // Zoom level (100 = default)
.SetMediaAutoplayEnabled(true)
.SetFileSystemAccessEnabled(true)
.SetWebSecurityEnabled(false) // Disable CORS (use with caution)
.SetJavascriptClipboardAccessEnabled(true)
.SetMediaStreamEnabled(true) // Camera/microphone access
.SetSmoothScrollingEnabled()
.SetIgnoreCertificateErrorsEnabled()
.SetUserAgent("MyApp/1.0")
Notifications (Windows only)
builder
.SetNotificationsEnabled()
.SetNotificationRegistrationId("com.myapp.notifications") // Windows only
.GrantBrowserPermissions() // Auto-grant camera/mic permissions (Windows only)
Platform-specific browser parameters
The SetBrowserControlInitParameters method passes raw flags to the underlying browser engine:
// Windows — space-separated Chromium flags
builder.SetBrowserControlInitParameters("--disable-gpu --no-sandbox")
// Linux — JSON object matching WebKit2GTK settings
builder.SetBrowserControlInitParameters("{ \"enable_developer_extras\": true }")
// macOS — JSON object matching WKPreferences keys
builder.SetBrowserControlInitParameters("{ \"minimumFontSize\": 12 }")
Runtime Window Control
Once a window is built, IInfiniFrameWindow provides methods to control it at runtime
State and properties
window.Size // Current size (read-only)
window.Location // Current position (read-only)
window.MaxSize // Get or set the maximum size at runtime
window.MinSize // Get or set the minimum size at runtime
window.Focused // Whether the window currently has focus
window.Maximized // (via events, not a direct property at runtime)
window.ScreenDpi // Current DPI
window.Monitors // ImmutableArray<InfiniMonitor> — all connected monitors
window.MainMonitor // The monitor the window is currently on
Window operations
window.Close()
window.WaitForClose()
await window.WaitForCloseAsync()
STA requirement (Windows)
WebView2 is COM-based and requires the thread that calls Build() to be STA. Without [STAThread], the window opens but the browser control renders as a black screen, and Build() now throws InvalidOperationException to surface this early
// Required for all InfiniFrame apps on Windows
internal class Program {
[STAThread]
static void Main(string[] args) {
var window = InfiniFrameWindowBuilder.Create()
// ...
.Build();
window.WaitForClose();
}
}
Top-level statements cannot carry [STAThread] so use an explicit static void Main() as shown above
Note:
[STAThread]is silently ignored onasync Task Main. The async continuation runs on thread pool threads (MTA). Never useasync Task Mainas the entry point for an InfiniFrame application. Linux does not have this restriction because GTK has no COM apartment model. The native constructor callsgtk_init()itself and implicitly claims whichever thread callsBuild()as the GTK main thread
Cross-thread invocation
All UI operations must run on the window's thread — use Invoke to marshal work from a background thread:
Task.Run(() => {
// Background thread
window.Invoke(() => {
// Runs on the window thread
window.Close();
});
});
Events
Events are available through IInfiniFrameWindowEvents, accessible via IInfiniFrameWindowBuilder.Events
var builder = InfiniFrameWindowBuilder.Create();
builder.Events.WindowCreated.Add(() => Console.WriteLine("Window opened"));
builder.Events.WindowSizeChanged.Add(size => Console.WriteLine($"Resized to {size}"));
builder.Events.WindowLocationChanged.Add(loc => Console.WriteLine($"Moved to {loc}"));
builder.Events.WindowFocusIn.Add(() => Console.WriteLine("Focus gained"));
builder.Events.WindowFocusOut.Add(() => Console.WriteLine("Focus lost"));
builder.Events.WindowMaximized.Add(() => Console.WriteLine("Maximized"));
builder.Events.WindowMinimized.Add(() => Console.WriteLine("Minimized"));
builder.Events.WindowRestored.Add(() => Console.WriteLine("Restored"));
builder.Events.WebMessageReceived.Add(msg => Console.WriteLine($"Message: {msg}"));
var window = builder.Build();
window.WaitForClose();
Intercepting window close
Use WindowClosingRequested to cancel or intercept a close:
builder.Events.WindowClosingRequested.Add(() => {
// Return true to allow closing, false to cancel
return AskUserToConfirm();
});
Use WindowClosing to run cleanup before the window is destroyed:
builder.Events.WindowClosing.Add((window, cancel) => {
SaveAppState();
return false; // returning false here does not cancel — use WindowClosingRequested for that
});
See the generated C# API reference for the full event system documentation
Web Messaging
InfiniFrame provides a two-way messaging channel between JavaScript running in the browser control and your C# code
C# → JavaScript
window.SendWebMessage("hello from C#");
await window.SendWebMessageAsync("async hello");
In JavaScript, listen with:
window.external.receiveMessage(function(message) {
console.log("Received:", message);
});
JavaScript → C#
In JavaScript, send with:
window.external.sendMessage("hello from JS");
In C#, handle with:
builder.Events.WebMessageReceived.Add(message => {
Console.WriteLine($"From JS: {message}");
});
Or register a named handler through IInfiniFrameWindowMessageHandlers:
builder.MessageHandlers.RegisterMessageHandler("ping", (window, _) => {
window.SendWebMessage("pong");
});
Custom URL Schemes
You can intercept requests for custom URL schemes (e.g. app://) and serve content from C# code — useful for loading local assets or implementing a virtual file system
builder.RegisterCustomSchemeHandler("app", (sender, scheme, url, out string? contentType) => {
contentType = "text/html";
var html = "<html><body>Hello from custom scheme</body></html>";
return new MemoryStream(Encoding.UTF8.GetBytes(html));
});
- Up to 16 custom schemes can be registered before
Build()is called - Additional handlers can be added after
Build()viawindow.RegisterCustomSchemeHandler(...) - Scheme names are lowercased automatically
Dialogs
InfiniFrame exposes the native OS dialog system
Message box
var result = window.ShowMessage(
title: "Confirm",
text: "Are you sure you want to quit?",
buttons: InfiniFrameDialogButtons.YesNo,
icon: InfiniFrameDialogIcon.Question
);
if (result == InfiniFrameDialogResult.Yes) {
window.Close();
}
File pickers
// Open one or more files
string?[] files = window.ShowOpenFile(
title: "Open File",
defaultPath: null,
multiSelect: true,
filters: [("Images", ["png", "jpg", "gif"]), ("All Files", ["*"])]
);
// Open folder(s)
string?[] folders = window.ShowOpenFolder("Select Folder", multiSelect: false);
// Save file
string? path = window.ShowSaveFile(
title: "Save As",
defaultPath: null,
filters: [("Text Files", ["txt"])]
);
All dialogs also have async overloads (ShowOpenFileAsync, ShowSaveFileAsync, etc.)
Notifications (Windows only)
window.SendNotification("Update available", "A new version is ready to install");
Requires SetNotificationsEnabled() and SetNotificationRegistrationId(...) to be set during configuration
Monitor Information
// All connected monitors
foreach (InfiniMonitor monitor in window.Monitors) {
Console.WriteLine($"Monitor: {monitor.MonitorArea}, Work area: {monitor.WorkArea}, Scale: {monitor.Scale}");
}
// The monitor the window is currently on
InfiniMonitor main = window.MainMonitor;
DI Container Integration
When building with a ServiceProvider, the builder reads configuration from the InfiniFrame section automatically:
// appsettings.json
{
"InfiniFrame": {
"Title": "My App",
"Width": 1280,
"Height": 720
}
}
Pass the provider to Build:
var window = builder.Build(serviceProvider);
IInfiniFrameWindow will then be resolvable from the container if registered
Examples
InfiniFrameExample.WebApp.React(examples/InfiniFrameExample.WebApp.React) - custom URL scheme handler and web messaging with DI-resolved servicesInfiniFrameExample.BlazorWebView(examples/InfiniFrameExample.BlazorWebView) - window builder configuration with size, position, and icon