24

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.

Sellorio
  • 1,806
  • 1
  • 16
  • 32

7 Answers7

33

.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;
    }
}
jeff28273
  • 422
  • 5
  • 11
  • 2
    To prevent resizing set the Min/Max values at the same time. "window.MinimumHeight = window.MaximumHeight = window.Height = newHeight;" – Mark Longmire May 11 '23 at 17:11
25

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.

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
  • 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?) – Sellorio May 27 '22 at 03:56
  • Visual Studio suggests the needed usings. Click on each red underlined item. Select from the dropdown by the little icon that appears. https://learn.microsoft.com/en-us/visualstudio/ide/find-and-fix-code-errors?view=vs-2022#use-quick-actions-to-fix-or-refactor-code – ToolmakerSteve May 27 '22 at 16:23
  • The namespaces don't exist – Sellorio May 28 '22 at 02:30
  • Please update your variables to declare with var so that this answer compiles – Sellorio May 28 '22 at 02:45
  • I've added the needed `using`s. 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 `using`s, so I had not noticed that INTELLISENSE was complaining.) – ToolmakerSteve May 29 '22 at 21:21
  • 1
    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 windows – Ewerton Jun 30 '22 at 18:18
  • How to get and set the full screen of the window instead of setting number manually ? – Khant Htet Naing Jul 28 '22 at 13:45
  • I don’t know. Please make a new question asking this. You can link back to this question, but explain you want full screen. – ToolmakerSteve Jul 28 '22 at 13:57
  • 1
    to get fullscreen: `if (appWindow.Presenter is OverlappedPresenter p){ p.Maximize();}` – wulf11 Aug 19 '22 at 07:40
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     
BNG016
  • 164
  • 1
  • 7
  • 3
    For some reason, only IsResizable works. `IsMaximizable = false` seems to be ignored and I don't know how to disable maximization. – JustAMartin Aug 20 '22 at 20:34
  • 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. – SeriousM Oct 24 '22 at 10:14
  • @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. – ToolmakerSteve Jun 30 '23 at 16:03
6

Since September 2022, it can be done with simpler way:

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

Michael Tsai
  • 661
  • 7
  • 17
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.

rlaphoenix
  • 136
  • 8
2

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;
    }

}
KTCO
  • 2,115
  • 23
  • 21
0

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();
    }