MAUI .NET Set Window Size
Asked Answered
R

9

34

How can I set the window size in MAUI?

Background info: I only care about Windows for this application - I chose MAUI so I could use Blazor for a desktop application. For some reason the default window size is massive (takes up almost all of my 1440p screen space). The application I'm making only needs about 600x600. Having a way to make the window size fixed would also be helpful although I'm happy to have the app simply be responsive.

Rogelioroger answered 27/5, 2022 at 1:24 Comment(3)
github.com/dotnet/maui/discussions/2370Gleanings
Saw that. It appears to be no longer valid.Rogelioroger
It's insane for such a basic feature to be missing!Havana
S
30

UPDATE

For .Net 7, see also jeff's answer.

Other answers are also worth looking at.


Updated for Maui GA (I'll add to that discussion too):

#if WINDOWS
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Windows.Graphics;
#endif

namespace YourAppNameHere;

public partial class App : Application
{
    const int WindowWidth = 400;
    const int WindowHeight = 300;
    public App()
    {
        InitializeComponent();

        Microsoft.Maui.Handlers.WindowHandler.Mapper.AppendToMapping(nameof(IWindow), (handler, view) =>
        {
#if WINDOWS
            var mauiWindow = handler.VirtualView;
            var nativeWindow = handler.PlatformView;
            nativeWindow.Activate();
            IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(nativeWindow);
            WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
            AppWindow appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
            appWindow.Resize(new SizeInt32(WindowWidth, WindowHeight));
#endif
        });

        MainPage = new MainPage();
    }
    ...

OR if want to base it on requested dimensions of MainPage, before appending handler could do:

MainPage = new MainPage();
var width = (int)MainPage.WidthRequest;
var height = (int)MainPage.HeightRequest;

then use those dimensions (probably add some padding to get whole window size, because MainPage is client area).


NOTE: I was testing for Windows, so in the drop-down at upper-left of source text editor pane, I had selected ... (net6.0-windows10.0.19041.0). That's why I did not notice that I needed #if around the usings, to avoid errors on Android etc.

Shamikashamma answered 27/5, 2022 at 3:1 Comment(9)
Fails to compile: error CS0246: The type or namespace name 'WindowId' could not be found (are you missing a using directive or an assembly reference?) error CS0246: The type or namespace name 'AppWindow' could not be found (are you missing a using directive or an assembly reference?) error CS0246: The type or namespace name 'SizeInt32' could not be found (are you missing a using directive or an assembly reference?)Rogelioroger
Visual Studio suggests the needed usings. Click on each red underlined item. Select from the dropdown by the little icon that appears. learn.microsoft.com/en-us/visualstudio/ide/…Shamikashamma
The namespaces don't existRogelioroger
Please update your variables to declare with var so that this answer compilesRogelioroger
I've added the needed usings. Note that they have to be surrounded by #if to avoid intellisense errors. I see that using var would have avoided this. But I decided to instead show the namespaces that are used. (It RAN on Windows without #if around the usings, so I had not noticed that INTELLISENSE was complaining.)Shamikashamma
The usings "aren't required" if you write this code inside YourProject\Platforms\Windows\App.xaml.cs which makes more sense since you are setting the size just for windowsCleanly
How to get and set the full screen of the window instead of setting number manually ?Desperation
I don’t know. Please make a new question asking this. You can link back to this question, but explain you want full screen.Shamikashamma
to get fullscreen: if (appWindow.Presenter is OverlappedPresenter p){ p.Maximize();}Colleague
T
52

.NET7 in Visual Studio 2022 17.4 introduces a more elegant way to do this than .NET6 implementations. For a Windows specific app, just add the following code to App.xaml.cs

namespace sampleCode;

public partial class App : Application
{
    public App()
    {
        InitializeComponent();
        MainPage = new AppShell();
    }

    protected override Window CreateWindow(IActivationState activationState)
    {
        var window = base.CreateWindow(activationState);

        const int newWidth = 800;
        const int newHeight = 600;
        
        window.Width = newWidth;
        window.Height = newHeight;

        return window;
    }
}
Targett answered 15/11, 2022 at 15:3 Comment(2)
To prevent resizing set the Min/Max values at the same time. "window.MinimumHeight = window.MaximumHeight = window.Height = newHeight;"Nerta
Now the question is, when will Alt-F4 work by default on windows.Rogelioroger
S
30

UPDATE

For .Net 7, see also jeff's answer.

Other answers are also worth looking at.


Updated for Maui GA (I'll add to that discussion too):

#if WINDOWS
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Windows.Graphics;
#endif

namespace YourAppNameHere;

public partial class App : Application
{
    const int WindowWidth = 400;
    const int WindowHeight = 300;
    public App()
    {
        InitializeComponent();

        Microsoft.Maui.Handlers.WindowHandler.Mapper.AppendToMapping(nameof(IWindow), (handler, view) =>
        {
#if WINDOWS
            var mauiWindow = handler.VirtualView;
            var nativeWindow = handler.PlatformView;
            nativeWindow.Activate();
            IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(nativeWindow);
            WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
            AppWindow appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
            appWindow.Resize(new SizeInt32(WindowWidth, WindowHeight));
#endif
        });

        MainPage = new MainPage();
    }
    ...

OR if want to base it on requested dimensions of MainPage, before appending handler could do:

MainPage = new MainPage();
var width = (int)MainPage.WidthRequest;
var height = (int)MainPage.HeightRequest;

then use those dimensions (probably add some padding to get whole window size, because MainPage is client area).


NOTE: I was testing for Windows, so in the drop-down at upper-left of source text editor pane, I had selected ... (net6.0-windows10.0.19041.0). That's why I did not notice that I needed #if around the usings, to avoid errors on Android etc.

Shamikashamma answered 27/5, 2022 at 3:1 Comment(9)
Fails to compile: error CS0246: The type or namespace name 'WindowId' could not be found (are you missing a using directive or an assembly reference?) error CS0246: The type or namespace name 'AppWindow' could not be found (are you missing a using directive or an assembly reference?) error CS0246: The type or namespace name 'SizeInt32' could not be found (are you missing a using directive or an assembly reference?)Rogelioroger
Visual Studio suggests the needed usings. Click on each red underlined item. Select from the dropdown by the little icon that appears. learn.microsoft.com/en-us/visualstudio/ide/…Shamikashamma
The namespaces don't existRogelioroger
Please update your variables to declare with var so that this answer compilesRogelioroger
I've added the needed usings. Note that they have to be surrounded by #if to avoid intellisense errors. I see that using var would have avoided this. But I decided to instead show the namespaces that are used. (It RAN on Windows without #if around the usings, so I had not noticed that INTELLISENSE was complaining.)Shamikashamma
The usings "aren't required" if you write this code inside YourProject\Platforms\Windows\App.xaml.cs which makes more sense since you are setting the size just for windowsCleanly
How to get and set the full screen of the window instead of setting number manually ?Desperation
I don’t know. Please make a new question asking this. You can link back to this question, but explain you want full screen.Shamikashamma
to get fullscreen: if (appWindow.Presenter is OverlappedPresenter p){ p.Maximize();}Colleague
C
8

Since September 2022, it can be done more simply:

public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        MainPage = new AppShell();    
    }

    protected override Window CreateWindow(IActivationState activationState)
    {
        Window window = base.CreateWindow(activationState);
        window.Activated += Window_Activated;
        return window;
    }

    private async void Window_Activated(object sender, EventArgs e)
    {
    #if WINDOWS
        const int DefaultWidth = 1024;
        const int DefaultHeight = 800;

        var window = sender as Window;

        // change window size.
        window.Width = DefaultWidth;
        window.Height = DefaultHeight;

        // give it some time to complete window resizing task.
        await window.Dispatcher.DispatchAsync(() => { });

        var disp = DeviceDisplay.Current.MainDisplayInfo;

        // move to screen center
        window.X = (disp.Width / disp.Density - window.Width) / 2;
        window.Y = (disp.Height / disp.Density - window.Height) / 2;
    #endif    
    }
}

Related ticket: https://github.com/dotnet/maui/pull/4942

Counterpunch answered 29/10, 2022 at 3:15 Comment(2)
Is this available for public download yet. Or at least in my version of MAUI it's not there yet.Roomful
@Roomful Did you target .Net 7?Shamikashamma
S
6

This is How we did it :

https://github.com/BhangeeF16/MAUI-DOT-NET/blob/main/SampleApp/MauiProgram.cs

In MauiProgram.cs > CreateMauiApp

#if WINDOWS
    builder.ConfigureLifecycleEvents(events =>
    {
        events.AddWindows(wndLifeCycleBuilder =>
        {
            wndLifeCycleBuilder.OnWindowCreated(window =>
            {
                IntPtr nativeWindowHandle = WinRT.Interop.WindowNative.GetWindowHandle(window);
                WindowId win32WindowsId = Win32Interop.GetWindowIdFromWindow(nativeWindowHandle);
                AppWindow winuiAppWindow = AppWindow.GetFromWindowId(win32WindowsId);    
                if(winuiAppWindow.Presenter is OverlappedPresenter p)
                { 
                    p.Maximize();
                    //p.IsAlwaysOnTop=true;
                    p.IsResizable=false;
                    p.IsMaximizable = false;
                    p.IsMinimizable=false;
                }                     
                else
                {
                    const int width = 1920;
                    const int height = 1080;
                    winuiAppWindow.MoveAndResize(new RectInt32(1920 / 2 - width / 2, 1080 / 2 - height / 2, width, height));                      
                }                        
            });
        });
    });
#endif     
Scale answered 11/8, 2022 at 15:41 Comment(3)
For some reason, only IsResizable works. IsMaximizable = false seems to be ignored and I don't know how to disable maximization.Boltonia
That's a very nice solution. To make it even more platform secure (without the #if pragma) I added an extension point in MauiProgram to allow actions that modify the builder and add the code above to the winui platform startup code in CreateMauiApp.Hendecahedron
@SeriousM- extension point? I’d like to see exactly what you did. Perhaps add another answer? And put a link in these comments, so I get notified.Shamikashamma
S
5

I hate that I can't just put this minor edit in a comment instead of providing a whole new answer, but that's S.O. for you.

You can control the window size and enabling of maximise/minimise/resize by changing your Windows platform specific implementation to the following (in Platforms/Windows/App.xaml.cs). This avoids having to wrap platform specific code in #if feature gates.

public partial class App : MauiWinUIApplication
{
    /// <summary>
    /// Initializes the singleton application object.  This is the first line of authored code
    /// executed, and as such is the logical equivalent of main() or WinMain().
    /// </summary>
    public App()
    {
        this.InitializeComponent();

        Microsoft.Maui.Handlers.WindowHandler.Mapper.AppendToMapping(nameof(IWindow), (handler, view) =>
        {
            var mauiWindow = handler.VirtualView;
            var nativeWindow = handler.PlatformView;
            nativeWindow.Activate();

            // allow Windows to draw a native titlebar which respects IsMaximizable/IsMinimizable
            nativeWindow.ExtendsContentIntoTitleBar = false;

            IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(nativeWindow);
            WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
            AppWindow appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);

            // set a specific window size
            appWindow.Resize(new SizeInt32(480, 720));

            if (appWindow.Presenter is OverlappedPresenter p)
            {
                p.IsResizable = false;

                // these only have effect if XAML isn't responsible for drawing the titlebar.
                p.IsMaximizable = false;
                p.IsMinimizable = false;
            }
        });
    }

    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
Skald answered 29/3, 2023 at 14:54 Comment(1)
and how to center the screen?Lylelyles
P
3

How to set initial window size and center it (maui 7.0.59):

public partial class App : Application {

    public App() {
        InitializeComponent();
        MainPage = new AppShell();
    }

    protected override Window CreateWindow(IActivationState activationState) {
        var window = base.CreateWindow(activationState);
        window.Created += Window_Created;
        return window;
    }

    private async void Window_Created(object sender, EventArgs e) {
        const int defaultWidth = 1200;
        const int defaultHeight = 800;

        var window = (Window)sender;
        window.Width = defaultWidth;
        window.Height = defaultHeight;
        window.X = -defaultWidth;
        window.Y = -defaultHeight;

        await window.Dispatcher.DispatchAsync(() => {});

        var displayInfo = DeviceDisplay.Current.MainDisplayInfo;
        window.X = (displayInfo.Width / displayInfo.Density - window.Width) / 2;
        window.Y = (displayInfo.Height / displayInfo.Density - window.Height) / 2;
    }

}
Pelpel answered 12/3, 2023 at 5:26 Comment(1)
Multi-platform is as simple as prefixing the event association with if(OperatingSystem.IsWindows())...Frilling
F
2

If you only want to do this for the Desktop Platforms, then you can do something similar to @ToolmakerSteve but per-platform by overriding the OnLaunched function within the Platforms/Windows/App.xaml.cs for example.

using Microsoft.UI;
using Microsoft.UI.Windowing;
using Windows.Graphics;
using WinRT.Interop;
//...
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
    base.OnLaunched(args);

    var currentWindow = Application.Windows[0].Handler.PlatformView;
    IntPtr _windowHandle = WindowNative.GetWindowHandle(currentWindow);
    var windowId = Win32Interop.GetWindowIdFromWindow(_windowHandle);

    AppWindow appWindow = AppWindow.GetFromWindowId(windowId);
    appWindow.Resize(new SizeInt32(350, 600));
}

These methods of resizing are still not ideal as it will flicker when it's changing window size. This is simply because of the time taken between OnLaunch being fired and the window being resized by native win32 API calls. However, moving it directly to the Platform-specific code is a bit more semantic.

Unlike the other answer we cannot get the Requested dimensions from client pages to use as our Window dimensions.

Francefrancene answered 5/7, 2022 at 1:23 Comment(0)
N
1

[Agree to the previous answer regarding edit and comments (also rep requirements for comments)]

For those who prefer to use the Platforms/Windows/App.xaml.cs approach, you can easily get the screen size by adding in an 'Activated' event handler to the code (simple to expand if you want the displayInfo.Density too):

public partial class App : MauiWinUIApplication
{
    Microsoft.UI.Xaml.Window nativeWindow;
    int screenWidth, screenHeight;
    const int desiredWidth = 480;
    const int desiredHeight = 720;
    /// <summary>
    /// Initializes the singleton application object.  This is the first line of authored code
    /// executed, and as such is the logical equivalent of main() or WinMain().
    /// </summary>
    public App()
    {
        this.InitializeComponent();

        Microsoft.Maui.Handlers.WindowHandler.Mapper.AppendToMapping(nameof(IWindow), (handler, view) =>
        {
            IWindow mauiWindow = handler.VirtualView;
            nativeWindow = handler.PlatformView;
            nativeWindow.Activated += OnWindowActivated;
            nativeWindow.Activate();

            // allow Windows to draw a native titlebar which respects IsMaximizable/IsMinimizable
            nativeWindow.ExtendsContentIntoTitleBar = false;

            IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(nativeWindow);
            WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
            AppWindow appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);

            // set a specific window size
            appWindow.MoveAndResize(new RectInt32((screenWidth - desiredWidth) / 2, (screenHeight - desiredHeight) / 2, desiredWidth, desiredHeight));

            if (appWindow.Presenter is OverlappedPresenter p)
            {
                p.IsResizable = false;
                // these only have effect if XAML isn't responsible for drawing the titlebar.
                p.IsMaximizable = false;
                p.IsMinimizable = false;
            }
        });
    }

    private void OnWindowActivated(object sender, Microsoft.UI.Xaml.WindowActivatedEventArgs args)
    {
        // Retrieve the screen resolution
        var displayInfo = DeviceDisplay.Current.MainDisplayInfo;
        screenWidth = (int)displayInfo.Width;
        screenHeight = (int)displayInfo.Height;
        // Remove this event handler since it is not needed anymore
        nativeWindow.Activated -= OnWindowActivated;
    }
Nacreous answered 11/9, 2023 at 16:32 Comment(0)
T
1

✅ After .NET 7 Window On Launch can be easily resized like this On App.xaml.cs Page :

public partial class App : Application
{
    protected override Window CreateWindow(IActivationState activationState)
    {
        var window = base.CreateWindow(activationState);

        // Change the window Size
        window.Width = 600; window.Height = 600;

        // BONUS -> Center the window
        var displayInfo = DeviceDisplay.Current.MainDisplayInfo;
        window.X = (displayInfo.Width / displayInfo.Density - window.Width) / 2;
        window.Y = (displayInfo.Height / displayInfo.Density - window.Height) / 2;
        return window;
    }
}
Tudela answered 20/1 at 16:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.