Compartir a través de


Administración de ventanas de aplicaciones

El SDK de Aplicaciones para Windows proporciona la clase Microsoft.UI.Windowing.AppWindow, que representa una abstracción de alto nivel del HWND. Hay una asignación de 1:1 entre un y un HWND de nivel superior en su aplicación. y sus clases relacionadas proporcionan las API que le permiten administrar muchos aspectos de las ventanas de nivel superior de la aplicación sin necesidad de acceder al HWND directamente.

Nota:

En este artículo se muestra cómo usar las API en la aplicación. Como requisito previo, se recomienda leer y comprender la información en AppWindow, en la Visión general de Windowing para WinUI 3 y el SDK de aplicaciones de Windows, que es aplicable tanto si se utiliza WinUI como otro framework de interfaz de usuario.

  • APIs importantes: clase, clase OverlappedPresenter

Abra la aplicación Galería de WinUI 3 y vea en acción.

Icono de la galería de WinUI 3 La aplicación Galería de WinUI 3 incluye ejemplos interactivos de características y controles winUI. Obtenga la aplicación del Microsoft Store o examine el código fuente en GitHub.

Puede usar AppWindow API con cualquier marco de interfaz de usuario que admita el SDK de Aplicaciones para Windows: WinUI, WPF, WinForms o Win32. Las API funcionan junto con las API de ventanas específicas del marco:

Normalmente, se usan API para:

  • Administre el tamaño y la posición de la ventana de la aplicación.

  • Administrar el título de la ventana, el icono y el color de la barra de título; o cree una barra de título totalmente personalizada con las API de AppWindowTitleBar.

    Consulta Personalización de la barra de título para obtener más información y ejemplos.

  • Administre la apariencia y el comportamiento de la ventana con las API derivadas de AppWindowPresenter.

Responder a los cambios de

Puede responder a los cambios en mediante el control del único evento Changed y, a continuación, comprobar los argumentos del evento (AppWindowChangedEventArgs) para determinar qué tipo de cambio ha ocurrido. Si se ha producido el cambio que le interesa, puede responder a él. Entre los posibles cambios se incluyen la posición, el tamaño, el moderador, la visibilidad y el orden z.

Este es un ejemplo de un controlador de eventos .Changed.

private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
{
    // ConfigText and SizeText are TextBox controls defined in XAML for the page.
    if (args.DidPresenterChange == true)
    {
        ConfigText.Text = sender.Presenter.Kind.ToString();
    }

    if (args.DidSizeChange == true)
    {
        SizeText.Text = sender.Size.Width.ToString() + ", " + sender.Size.Height.ToString();
    }
}

tamaño y colocación

La clase tiene varias propiedades y métodos que puede usar para administrar el tamaño y la ubicación de la ventana.

Categoría Propiedades
Propiedades de solo lectura Posición, Tamaño, Tamaño del Cliente
Eventos Modificado (DidPositionChange, DidSizeChange)
Métodos de tamaño y posición Mover, Redimensionar, RedimensionarCliente, MoverYRedimensionar
Métodos de orden Z MoveInzOrderAtBottom, MoveInzOrderAtTop, MoveInzOrderBelow

Llame a Resize para especificar un nuevo tamaño de ventana.

En este ejemplo, el código está en , por lo que puede usar la propiedad . para obtener la instancia.

public MainWindow()
{
    InitializeComponent();
    AppWindow.Resize(new Windows.Graphics.SizeInt32(1200, 800));
}

Llame al método Move para cambiar la posición de una ventana.

En este ejemplo se mueve la ventana para centrarse en la pantalla cuando el usuario hace clic en un botón.

Esto ocurre en el archivo de código de una clase Page, por lo que no tienes automáticamente acceso a los objetos o . Tienes algunas opciones para obtener el .

  • Si mantiene una referencia al como se describe en Seguimiento de la ventana actual o Seguimiento de instancias de , puede obtener el y luego obtener de la propiedad .
  • O bien, puede llamar al método estático .GetFromWindowId para obtener la instancia , como se muestra aquí. (Vea Determinar la ventana que hospeda un elemento visual).
private void MoveWindowButton_Click(object sender, RoutedEventArgs e)
{
    AppWindow appWindow = AppWindow.GetFromWindowId(XamlRoot.ContentIslandEnvironment.AppWindowId);
    RectInt32? area = DisplayArea.GetFromWindowId(appWindow.Id, DisplayAreaFallback.Nearest)?.WorkArea;
    if (area == null) return;
    appWindow.Move(new PointInt32((area.Value.Width - appWindow.Size.Width) / 2, (area.Value.Height - appWindow.Size.Height) / 2));
}

La clase AppWindowPresenter y las subclases

Cada tiene un AppWindowPresenter (moderador) aplicada. El sistema crea un moderador y se aplica a una en el momento de la creación. Cada subclase de AppWindowPresenter proporciona una configuración predefinida adecuada para el propósito de la ventana. Se proporcionan estos presentadores derivados de AppWindowPresenter y están disponibles en todas las versiones del sistema operativo compatibles.

  • CompactOverlayPresenter

    Configura una ventana siempre visible de un tamaño fijo, con una relación de aspecto de 16:9 para permitir experiencias de imagen en imagen. De forma predeterminada, InitialSize es CompactOverlaySize.Small, pero puede cambiarlo a o . También puede llamar a .Resize para anular la relación de aspecto 16:9 y establecer la ventana en cualquier tamaño deseado.

  • FullScreenPresenter

    Configura una ventana para proporcionar una experiencia de pantalla completa adecuada para ver vídeo. La ventana no tiene un borde ni una barra de título y oculta la barra de tareas del sistema.

  • OverlappedPresenter

    La configuración de ventana estándar, que, de forma predeterminada, proporciona un borde con identificadores de cambio de tamaño y una barra de título con botones de minimización, maximización y restauración.

Nota:

Como nuevo concepto para el modelo de aplicación Win32, un presentador es similar a (pero no igual a) una combinación de estado de ventana y estilos. Algunos presentadores también tienen comportamientos que están definidos y que no se pueden inspeccionar a partir de las propiedades de estado y estilo de ventana clásico (como una barra de título que se oculta automáticamente).

El presentador predeterminado

El presentador predeterminado aplicado cuando se crea un es una instancia de OverlappedPresenter con la configuración de propiedad predeterminada. No es necesario mantener una referencia para volver al presentador predeterminado de una ventana después de haber aplicado otro presentador. Esto se debe a que el sistema mantiene la misma instancia de este presentador durante toda la vida útil del para el cual se creó; y puede volver a aplicarlo llamando al .método SetPresenter con AppWindowPresenterKind.Default como parámetro.

Importante

Al llamar a , siempre se vuelve a aplicar la instancia predeterminada del presentador que se crea con . Si crea y aplica otro moderador y desea volver a utilizarlo más adelante, debe mantener una referencia al moderador.

También puede obtener una referencia a la instancia predeterminada del presentador y modificarla. Si ha aplicado un nuevo moderador, asegúrese primero de que se aplique el moderador predeterminado, como se muestra aquí:

appWindow.SetPresenter(AppWindowPresenterKind.Default);
OverlappedPresenter defaultPresenter = (OverlappedPresenter)appWindow.Presenter;
defaultPresenter.IsMaximizable = false;
defaultPresenter.IsMinimizable = false;

Modificar un OverlappedPresenter

OverlappedPresenter es un presentador flexible que se puede configurar de diversas maneras.

Los métodos permiten crear un presentador de superposición con valores de propiedad predeterminados, o uno con valores de propiedad preconfigurados para un uso específico.

En esta tabla se muestra cómo se establecen las propiedades de configuración al crear un objeto OverlappedPresenter a partir de cada método.

Propiedad Create CreateForContextMenu CreateForDialog CreateForToolWindow
HasBorder true true true true
HasTitleBar true false true true
IsAlwaysOnTop false false false false
IsMaximizable true false false true
IsMinimizable true false false true
IsModal false false false false
IsResizable true false false true

El moderador aplicado es un objeto activo. Un cambio en cualquier propiedad del objeto .Presenter surte efecto inmediatamente. No hay ningún evento para notificarle estos cambios, pero puede comprobar las propiedades de los valores actuales en cualquier momento.

Las propiedades HasBorder y HasTitleBar son de solo lectura. Puede establecer estos valores llamando al método SetBorderAndTitleBar (). Un OverlappedPresenter no puede tener una barra de título sin borde. Es decir, si el parámetro es , el parámetro también debe ser . De lo contrario, se produce una excepción con este mensaje:

The parameter is incorrect.
Invalid combination: Border=false, TitleBar=true.

Establezca IsMaximizable a para ocultar el botón de maximizar de la barra de herramientas. Se recomienda hacerlo si establece las propiedades o , ya que estas propiedades restringen el tamaño de la ventana incluso en el estado maximizado. Esto no afecta a las llamadas al método Maximize .

Establezca IsMinimizable en para ocultar el botón minimizar de la barra de herramientas. Esto no afecta a las llamadas al método Minimize .

Establezca IsResizable en para ocultar los controles de cambio de tamaño y evitar que el usuario vuelva a cambiar el tamaño de la ventana. Esto no afecta a las llamadas al método .Resize.

Establezca IsAlwaysOnTop en para mantener esta ventana encima de otras ventanas. Si llama a cualquiera de los métodos, siguen surtindo efecto para cambiar el orden z de la ventana aunque esta propiedad sea .

Establezca PreferredMaximumHeight y PreferredMaximumWidth para restringir el tamaño máximo al que el usuario puede ajustar la ventana. Se recomienda establecer en si establece las propiedades de tamaño máximo, ya que estas propiedades restringen el tamaño de la ventana incluso en el estado maximizado. Estas propiedades también afectan a las llamadas a . Cambio de tamaño; la ventana no se cambiará de tamaño mayor que el alto y ancho máximo especificados.

Establezca PreferredMinimumHeight y PreferredMinimumWidth para establecer el tamaño mínimo en el que el usuario puede reducir la ventana. Estas propiedades también afectan a las llamadas a . Cambio de tamaño; la ventana no se cambiará de tamaño menor que el alto y el ancho mínimos especificados.

Puede establecer IsModal en para crear una ventana modal. Una ventana modal es una ventana independiente que bloquea la interacción con su ventana de propietario hasta que se cierra. Sin embargo, para crear una ventana modal, también debe establecer la ventana de propietario; De lo contrario, se produce una excepción con este mensaje:

The parameter is incorrect.

The window should have an owner when IsModal=true.

Para establecer la ventana del propietario en una aplicación WinUI, es necesario la interoperabilidad de Win32. Para obtener más información y código de ejemplo, consulte la página de la aplicación de ejemplo galería de WinUI 3.

Asignar un presentador

Un moderador solo se puede aplicar a una sola ventana a la vez. Al intentar aplicar el mismo moderador a una segunda ventana, se produce una excepción. Esto significa que si tienes varias ventanas y deseas cambiar cada una a un modo de presentación específico, debes crear varios moderadores del mismo tipo y, a continuación, aplicar cada uno a su propia ventana.

Cuando se aplica un nuevo presentador (la propiedad .Presenter cambia), la aplicación recibe una notificación por un evento .Changed en el afectado, con la propiedad AppWindowChangedEventArgs.DidPresenterChange establecida en .

Sugerencia

Si aplica un moderador modificado y permite cambiar entre moderadores, asegúrese de mantener una referencia al moderador modificado de modo que pueda volver a aplicarse a .

En este ejemplo se muestra cómo hacer lo siguiente:

  • Use la propiedad .Presentador para obtener el presentador actual.
  • Use la propiedad AppWindowPresenter.Kind para comprobar qué tipo de configuración se aplica actualmente.
  • Llame a .SetPresenter para cambiar la configuración actual.

Aquí, se crea, modifica y aplica un presentador en el constructor de la ventana.

OverlappedPresenter presenter = OverlappedPresenter.Create();
presenter.PreferredMinimumWidth = 420;
presenter.PreferredMinimumHeight = 550;
AppWindow.SetPresenter(presenter);

En la página que es el contenido de la ventana, puede obtener una referencia a y al moderador aplicado.

AppWindow appWindow;
OverlappedPresenter modifiedPresenter;

private void AppWindowPage_Loaded(object sender, RoutedEventArgs e)
{
    appWindow = AppWindow.GetFromWindowId(XamlRoot.ContentIslandEnvironment.AppWindowId);
    modifiedPresenter = (OverlappedPresenter)appWindow.Presenter;

    appWindow.Changed += AppWindow_Changed;
}

private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
{
    if (args.DidPresenterChange)
    {
        // ConfigText is a TextBox control defined in XAML for the page.
        ConfigText.Text = appWindow.Presenter.Kind.ToString();
    }
}

private void CompactOverlayButton_Click(object sender, RoutedEventArgs e)
{
    if (appWindow.Presenter.Kind != AppWindowPresenterKind.CompactOverlay)
    {
        appWindow.SetPresenter(CompactOverlayPresenter.Create());
        fullScreenButton.IsChecked = false;
    }
    else
    {
        appWindow.SetPresenter(modifiedPresenter);
    }
}

private void FullScreenButton_Click(object sender, RoutedEventArgs e)
{
    if (appWindow.Presenter.Kind != AppWindowPresenterKind.FullScreen)
    {
        appWindow.SetPresenter(FullScreenPresenter.Create());
        compactOverlayButton.IsChecked = false;
    }
    else
    {
        appWindow.SetPresenter(modifiedPresenter);
    }
}

Marco de interfaz de usuario e interoperabilidad de HWND

La clase está disponible para cualquier HWND de nivel superior en su aplicación. Esto significa que, cuando se trabaja con un marco de interfaz de usuario de escritorio (incluido WinUI), puede seguir usando el punto de entrada de ese marco para crear una ventana y adjuntar su contenido. Y una vez que haya creado una ventana con ese marco de interfaz de usuario, puede usar las funciones de interoperabilidad de ventanas (consulte a continuación) proporcionadas en el SDK de Aplicaciones para Windows para acceder al AppWindow correspondiente y sus métodos, propiedades y eventos.

Algunas de las ventajas de usar (incluso cuando se trabaja con un marco de interfaz de usuario) son:

  • Personalización sencilla de la barra de título; que, de forma predeterminada, mantiene el diseño de interfaz de usuario de Windows 11 (esquinas redondeadas, grupo flotante de ajuste).
  • Experiencias de pantalla completa y superposición compacta (imagen en imagen) proporcionadas por el sistema.
  • Interfaz del API de Windows Runtime (WinRT) para algunos de los conceptos básicos de gestión de ventanas de Win32.

Obtenga el AppWindow para las versiones de SDK de Aplicaciones para Windows anteriores a la 1.3 (u otros marcos de aplicaciones de escritorio).

La propiedad Window.AppWindow está disponible en SDK de Aplicaciones para Windows versión 1.3 y posteriores. Para versiones anteriores, puedes usar el ejemplo de código funcionalmente equivalente en esta sección.

C#. .NET contenedores para las funciones de interoperabilidad de ventanas se implementan como métodos de la clase Microsoft.UI.Win32Interop. Véase también Llamar a las APIs de interoperabilidad desde una aplicación de .NET.

C++. Las funciones de interoperabilidad se definen en el archivo de encabezado winrt/Microsoft.ui.interop.h.

En la sección de ejemplo de código siguiente se muestra el código fuente real; pero aquí está el procedimiento para obtener un objeto dada una ventana existente.

  1. Obtén el HWND de tu objeto de ventana existente (para el framework de la interfaz de usuario), si aún no lo tienes.
  2. Pase ese HWND a la función de interoperabilidad GetWindowIdFromWindow para recuperar un WindowId.
  3. Pase ese WindowId al método estático .GetFromWindowId para recuperar el .
// MainWindow.xaml.cs
private void myButton_Click(object sender, RoutedEventArgs e)
{
    // Retrieve the window handle (HWND) of the current (XAML) WinUI window.
    var hWnd =
        WinRT.Interop.WindowNative.GetWindowHandle(this);

    // Retrieve the WindowId that corresponds to hWnd.
    Microsoft.UI.WindowId windowId =
        Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);

    // Lastly, retrieve the AppWindow for the current (XAML) WinUI window.
    Microsoft.UI.Windowing.AppWindow appWindow =
        Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);

    if (appWindow != null)
    {
        // You now have an AppWindow object, and you can call its methods to manipulate the window.
        // As an example, let's change the title text of the window.
        appWindow.Title = "Title text updated via AppWindow!";
    }
}
// pch.h
#include "microsoft.ui.xaml.window.h" // For the IWindowNative interface.
#include <winrt/Microsoft.UI.Interop.h> // For the WindowId struct and the GetWindowIdFromWindow function.
#include <winrt/Microsoft.UI.Windowing.h> // For the AppWindow class.

// mainwindow.xaml.cpp
void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&)
{
    // Retrieve the window handle (HWND) of the current (XAML) WinUI window.
    auto windowNative{ this->m_inner.as<::IWindowNative>() };
    HWND hWnd{ 0 };
    windowNative->get_WindowHandle(&hWnd);

    // Retrieve the WindowId that corresponds to hWnd.
    Microsoft::UI::WindowId windowId = 
        Microsoft::UI::GetWindowIdFromWindow(hWnd);

    // Lastly, retrieve the AppWindow for the current (XAML) WinUI window.
    Microsoft::UI::Windowing::AppWindow appWindow = 
        Microsoft::UI::Windowing::AppWindow::GetFromWindowId(windowId);

    if (appWindow)
    {
        // You now have an AppWindow object, and you can call its methods to manipulate the window.
        // As an example, let's change the title text of the window.
        appWindow.Title(L"Title text updated via AppWindow!");
    }
}

Para obtener más ejemplos de cómo trabajar con , consulte el ejemplo de la galería Windowing.

Limitaciones

Actualmente, el SDK de Aplicaciones para Windows no proporciona métodos para adjuntar contenido del marco de interfaz de usuario a un AppWindow.