Partilhar via


Gerenciar janelas de aplicativos

O SDK do Aplicativo Windows fornece a classe Microsoft.UI.Windowing.AppWindow , que representa uma abstração de alto nível do HWND. Há um mapeamento 1:1 entre um AppWindow e um HWND de nível superior no seu aplicativo. AppWindow e suas classes relacionadas fornecem APIs que permitem gerenciar muitos aspetos das janelas de nível superior do seu aplicativo sem a necessidade de acessar o HWND diretamente.

Observação

Este artigo demonstra como usar AppWindow APIs em seu aplicativo. Como pré-requisito, recomendamos que você leia e compreenda as AppWindow informações em Visão geral de janelas para WinUI e Windows App SDK, que é aplicável se você usar WinUI ou outra estrutura de interface do usuário.

O aplicativo WinUI 3 Gallery inclui exemplos interativos da maioria dos controles, recursos e funcionalidades do WinUI 3. Obtenha o aplicativo no da Microsoft Store ou obtenha o código-fonte em do GitHub

Você pode usar AppWindow APIs com qualquer estrutura de interface do usuário suportada pelo SDK de aplicativos do Windows - WinUI 3, WPF, WinForms ou Win32. AppWindow As APIs funcionam em conjunto com as APIs de janelas específicas da estrutura:

Normalmente, você usa AppWindow APIs para:

  • Gerencie o tamanho e a posição da janela do seu aplicativo.

  • Gerenciar o título da janela, ícone e cor da barra de título; ou crie uma barra de título totalmente personalizada com APIs AppWindowTitleBar .

    Consulte Personalização da barra de título para obter mais informações e exemplos.

  • Gerencie a aparência e o comportamento da janela com APIs derivadas do AppWindowPresenter.

Responder às AppWindow alterações

Você responde às alterações do AppWindow manipulando o único evento Changed e, depois, verificando os argumentos do evento (AppWindowChangedEventArgs) para determinar que tipo de alteração aconteceu. Se a mudança em que você está interessado aconteceu, você pode responder a ela. As possíveis alterações incluem posição, tamanho, apresentador, visibilidade e ordem z.

Aqui está um exemplo de um AppWindow manipulador 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();
    }
}

Window tamanho e posicionamento

A AppWindow classe tem várias propriedades e métodos que você pode usar para gerenciar o tamanho e o posicionamento da janela.

Categoria Propriedades
Propriedades somente leitura Posição, Tamanho, ClientSize
Events Alterado (DidPositionChange, DidSizeChange)
Métodos de manipulação de tamanho e posição Mover, Redimensionar, RedimensionarClient, MoveAndResize
Métodos de ordem Z MoveEmZOrderAbaixo, MoveEmZOrderAoTopo, MoveEmZOrderAbaixoDe

Chame Redimensionamento para especificar um novo tamanho de janela.

Neste exemplo, o código está em MainWindow.xaml.cs, portanto, você pode usar a Windowpropriedade .AppWindow para obter a AppWindow instância.

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

Chame o método Move para alterar a posição de uma janela.

Este exemplo move a janela para ser centralizada na tela quando o usuário clica em um botão.

Isso ocorre no arquivo de código de uma classe Page , portanto, você não tem acesso automaticamente aos Window objetos ou AppWindow . Você tem algumas opções para obter o AppWindow.

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

A classe AppWindowPresenter e subclasses

Cada AppWindow tem um AppWindowPresenter (apresentador) aplicado. Um apresentador é criado pelo sistema e aplicado a um AppWindow no momento da criação. Cada subclasse de AppWindowPresenter fornece uma configuração predefinida apropriada para a finalidade da janela. Esses apresentadores derivados do AppWindowPresenter são fornecidos e estão disponíveis em todas as versões do sistema operacional suportadas.

  • CompactOverlayPresenter

    Configura uma janela sempre visível de um tamanho fixo, com uma proporção de 16:9 para permitir experiências semelhantes ao picture-in-picture. Por padrão, o InitialSize é CompactOverlaySize.Small, mas você pode alterá-lo para Medium ou Large. Você também pode chamar AppWindow.Redimensionar para substituir a proporção 16:9 e tornar a janela do tamanho desejado.

  • FullScreenPresenter

    Configura uma janela para fornecer uma experiência de tela cheia adequada para assistir a vídeos. A janela não tem uma borda ou barra de título e oculta a barra de tarefas do sistema.

  • OverlappedPresenter

    A configuração de janela padrão, que, por padrão, fornece uma borda com alças de redimensionamento e uma barra de título com botões minimizar/maximizar/restaurar.

Observação

Como um novo conceito para o modelo de aplicação Win32, um presenter é semelhante (mas não idêntico) a uma combinação de estado de janela e estilos. Alguns apresentadores também têm comportamentos definidos em si que não podem ser inspecionados a partir do estado clássico da janela e das propriedades de estilo (como uma barra de título com ocultação automática).

O apresentador padrão

O apresentador padrão aplicado quando um AppWindow é criado é uma instância de OverlappedPresenter com configurações de propriedade padrão. Não há necessidade de manter uma referência a ele para voltar ao apresentador padrão para uma janela depois de ter aplicado outro apresentador. Isso porque o sistema mantém a mesma instância desse apresentador durante o tempo de vida para o qual foi criado o AppWindow, e pode-se reaplicá-lo chamando o método AppWindow.SetPresenter com AppWindowPresenterKind.Default como parâmetro.

Importante

A chamada SetPresenter(AppWindowPresenterKind.Default) sempre reaplica a instância padrão do apresentador que é criada com o AppWindow. Se criar e aplicar um novo apresentador e quiser reaplicá-lo mais tarde, precisará manter uma referência ao seu apresentador.

Você também pode obter uma referência à instância padrão do apresentador e modificá-la. Se você aplicou um novo apresentador, primeiro verifique se o apresentador padrão está aplicado, conforme mostrado aqui:

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

Modificar um OverlappedPresenter

O OverlappedPresenter é um apresentador flexível que você pode configurar de várias maneiras.

Os Createmétodos * permitem criar um apresentador sobreposto com configurações de propriedade padrão ou um com configurações de propriedade pré-configuradas para um uso específico.

Esta tabela mostra como as propriedades de configuração são definidas quando você cria um objeto OverlappedPresenter a partir de cada método.

Propriedade 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
IsResizável true false false true

O apresentador aplicado é um objeto dinâmico. Uma alteração em qualquer propriedade do objeto AppWindow.Presenter entra em vigor imediatamente. Não há eventos para notificá-lo dessas alterações, mas você pode verificar as propriedades para os valores atuais a qualquer momento.

As propriedades HasBorder e HasTitleBar são somente leitura. Você pode definir esses valores chamando o método SetBorderAndTitleBar (SetBorderAndTitleBar(bool hasBorder, bool hasTitleBar)). Um OverlappedPresenter não pode ter uma barra de título sem uma borda. Ou seja, se o hasTitleBar parâmetro é true, então o hasBorder parâmetro também deve ser true. Caso contrário, uma exceção será lançada com esta mensagem:

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

Defina IsMaximizable para false ocultar o botão maximizar na barra de ferramentas. Recomendamos que faça isto se definir as propriedades PreferredMaximumHeight ou PreferredMaximumWidth, pois estas propriedades limitam o tamanho da janela mesmo quando está maximizada. Isso não afeta as chamadas para o método Maximiz .

Defina IsMinimizable para false ocultar o botão minimizar na barra de ferramentas. Isso não afeta as chamadas para o método Minimizar .

Defina IsResizable para false ocultar os controles de redimensionamento e impedir que o usuário redimensione a janela. Isso não afeta as chamadas para o AppWindow.Resize método.

Defina IsAlwaysOnTop como true para manter esta janela sobre outras janelas. Se você chamar qualquer um dos AppWindow.MoveInZOrder* métodos, eles ainda terão efeito para alterar a ordem z da janela, mesmo que essa propriedade seja true.

Defina PreferredMaximumHeight e PreferredMaximumWidth para restringir o tamanho máximo para o qual o usuário pode esticar a janela. Recomendamos que você defina IsMaximizable como false se você definir as propriedades de tamanho máximo, pois essas propriedades restringem o tamanho da janela mesmo no estado maximizado. Essas propriedades também afetam as chamadas para AppWindow. Redimensionamento; A janela não será redimensionada maior do que a altura e largura máximas especificadas.

Defina PreferredMinimumHeight e PreferredMinimumWidth para definir o tamanho mínimo para o qual o usuário pode reduzir a janela. Essas propriedades também afetam as chamadas para AppWindow. Redimensionamento; A janela não será redimensionada menor do que a altura e largura mínimas especificadas.

Você pode definir IsModal como true para criar uma janela modal. Uma janela modal é uma janela separada que bloqueia a interação com a janela do proprietário até que ela seja fechada. No entanto, para criar uma janela modal, você também deve definir a janela do proprietário; caso contrário, uma exceção será lançada com esta mensagem:

The parameter is incorrect.

The window should have an owner when IsModal=true.

Para definir a janela do proprietário numa aplicação WinUI, é necessário recorrer à interoperabilidade Win32. Para obter mais informações e código de exemplo, consulte a AppWindow página no aplicativo de exemplo WinUI Gallery.

Atribuir um apresentador

Um apresentador pode ser aplicado a apenas uma janela de cada vez. Tentar aplicar o mesmo apresentador a uma segunda janela gera uma exceção. Isso significa que, se você tiver várias janelas e quiser alternar cada uma para um modo de apresentação específico, precisará criar vários apresentadores do mesmo tipo e, em seguida, aplicar cada um à sua própria janela.

Quando um novo apresentador é definido (a propriedade AppWindow.Presenter muda), o seu aplicativo é notificado por um evento AppWindow.Changed no AppWindow afetado, com a propriedade AppWindowChangedEventArgs.DidPresenterChange definida como true.

Sugestão

Se aplicar um apresentador modificado e permitir a mudança entre apresentadores, assegure-se de manter uma referência ao apresentador modificado para que ele possa ser reaplicado ao AppWindow.

Este exemplo mostra como fazer o seguinte:

Aqui, um apresentador é criado, modificado e aplicado no construtor da janela.

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

Na Página que é o conteúdo da janela, pode-se obter uma referência ao AppWindow e ao apresentador 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);
    }
}

Estrutura de interface do usuário e interoperabilidade HWND

A AppWindow classe está disponível para qualquer HWND de nível superior na sua aplicação. Isso significa que, ao trabalhar com uma estrutura de interface do usuário da área de trabalho (incluindo a WinUI 3), você pode continuar a usar o ponto de entrada dessa estrutura para criar uma janela e anexar seu conteúdo. E depois de criar uma janela com essa estrutura de interface do usuário, você pode usar as funções de interoperabilidade de janelas (veja abaixo) fornecidas no SDK do Aplicativo Windows para acessar os métodos, propriedades e eventos correspondentes AppWindow e seus métodos.

Alguns dos benefícios de usar AppWindow (mesmo quando se trabalha com uma estrutura de interface do usuário) são:

  • Fácil personalização da barra de título; que, por padrão, mantém a interface do usuário do Windows 11 (cantos arredondados, submenu de grupo de ajustes).
  • Experiências de ecrã inteiro e imagem-em-imagem compacta fornecidas pelo sistema.
  • Superfície da API do Tempo de Execução do Windows (WinRT) para alguns dos principais conceitos de janela do Win32.

Obtenha o AppWindow para versões do Windows App SDK anteriores à 1.3 (ou outros frameworks de aplicativos de desktop)

A Windowpropriedade .AppWindow está disponível no SDK de aplicativos Windows versão 1.3 e posterior. Para versões anteriores, você pode usar o exemplo de código funcionalmente equivalente nesta seção.

C#. Os wrappers .NET para as funções de interoperabilidade de janelas são implementados como métodos da classe Microsoft.UI.Win32Interop . Consulte também Chamar APIs de interoperabilidade a partir de uma aplicação .NET.

C++. As funções de interoperabilidade são definidas no ficheiro de cabeçalho winrt/Microsoft.ui.interop.h.

A seção de exemplo de código abaixo mostra o código-fonte real; Mas aqui está a receita para recuperar um AppWindow objeto dada uma janela existente:

  1. Recupere o HWND para seu objeto de janela existente (para sua estrutura de interface do usuário), se ainda não o tiver.
  2. Passe esse HWND para a função de interoperabilidade GetWindowIdFromWindow para recuperar um WindowId.
  3. Passe esse WindowId para o método estático AppWindow.GetFromWindowId para recuperar o AppWindow.
// MainWindow.xaml.cs
private void myButton_Click(object sender, RoutedEventArgs e)
{
    // Retrieve the window handle (HWND) of the current (XAML) WinUI 3 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 3 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 3 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 3 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 obter mais exemplos de como trabalhar com AppWindow, consulte o exemplo da galeria de janela.

Limitações

Atualmente, o SDK de aplicativos Windows não fornece métodos para anexar conteúdo da estrutura da interface do usuário a um AppWindowarquivo .