MAUI .NET Установка размера окна
Как установить размер окна в MAUI?
Справочная информация: меня интересует только Windows для этого приложения — я выбрал MAUI, чтобы использовать Blazor для настольного приложения. По какой-то причине размер окна по умолчанию огромен (занимает почти все мое экранное пространство 1440p). Приложение, которое я делаю, требует только около 600x600. Также было бы полезно иметь возможность зафиксировать размер окна, хотя я рад, что приложение просто отзывчиво.
9 ответов
.NET7 в Visual Studio 2022 17.4 представляет более элегантный способ сделать это, чем реализации .NET6. Для конкретного приложения Windows просто добавьте следующий код в 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;
}
}
Обновлено для Maui GA (я тоже добавлю к этому обсуждению):
#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();
}
...
ИЛИ, если вы хотите основывать его на запрошенных размерах MainPage, прежде чем обработчик добавления может сделать:
MainPage = new MainPage();
var width = (int)MainPage.WidthRequest;
var height = (int)MainPage.HeightRequest;
затем используйте эти размеры (возможно, добавьте некоторые отступы, чтобы получить размер всего окна, потому что MainPage - это клиентская область).
ПРИМЕЧАНИЕ. Я тестировал для Windows, поэтому в раскрывающемся списке в верхнем левом углу панели редактора исходного текста я выбрал
... (net6.0-windows10.0.19041.0)
. Вот почему я не заметил, что мне нужно
#if
вокруг
using
s, чтобы избежать ошибок на Android и т. д.
С сентября 2022 года это можно сделать проще:
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
}
}
Связанный билет: https://github.com/dotnet/maui/pull/4942
Вот как мы это сделали:
https://github.com/BhangeeF16/MAUI-DOT-NET/blob/main/SampleApp/MauiProgram.cs
В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
Как установить начальный размер окна и отцентрировать его (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;
}
}
Ненавижу, что не могу просто внести это незначительное изменение в комментарий вместо того, чтобы дать совершенно новый ответ, но это ТАК для вас.
Вы можете контролировать размер окна и включать максимизацию/минимизацию/изменение размера, изменив реализацию конкретной платформы Windows на следующую (в
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();
}
Если вы хотите сделать это только для настольных платформ, вы можете сделать что-то похожее на @ToolmakerSteve, но для каждой платформы, переопределив функцию OnLaunched в
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));
}
Эти методы изменения размера все еще не идеальны, так как они будут мерцать при изменении размера окна. Это просто из-за времени, которое проходит между запуском OnLaunch и изменением размера окна собственными вызовами API win32. Однако перенос его непосредственно в код, специфичный для платформы, немного более семантичен.
В отличие от другого ответа, мы не можем получить запрошенные размеры с клиентских страниц для использования в качестве размеров нашего окна.
Это сработало для меня:
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);
var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
appWindow.Resize(new Windows.Graphics.SizeInt32(WindowWidth, WindowHeight));
#endif
});
MainPage = new AppShell();
}
[Согласитесь с предыдущим ответом относительно редактирования и комментариев (также требования к репутации для комментариев)]
Для тех, кто предпочитает использовать подход «Платформы/Windows/App.xaml.cs», вы можете легко получить размер экрана, добавив в код обработчик событий «Активированный» (просто расширить, если вам также нужен displayInfo.Density). :
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;
}