Compartilhar via


Usar a Camada visual com Windows Forms

Você pode usar as APIs de Composição do Windows Runtime (também conhecidas como Camada visual) em seus aplicativos Windows Forms para criar experiências modernas que se destaquem para os usuários do Windows.

O código completo para este tutorial está disponível no GitHub: Exemplo do HelloComposition do Windows Forms.

Pré-requisitos

A API de hospedagem UWP tem estes pré-requisitos.

Como usar as APIs de Composição no Windows Forms

Neste tutorial, você criará uma interface do usuário do Windows Forms simples e adicionará elementos de Composição animados a ela. Embora os componentes do Windows Forms e de Composição continuem simples, o código de interoperabilidade mostrado será o mesmo independentemente da complexidade dos componentes. O aplicativo concluído tem esta aparência.

A interface do usuário do aplicativo em execução

Criar um projeto no Windows Forms

Primeiro, você precisará criar o projeto de aplicativo Windows Forms, que inclui a definição do aplicativo e do formulário principal da interface do usuário.

Para criar um projeto de aplicativo Windows Forms no Visual C# chamado HelloComposition:

  1. Abra o Visual Studio e selecione Arquivo>Novo>Projeto.
    A caixa de diálogo Novo projeto é aberta.
  2. Na categoria Instalado, expanda o nó Visual C# e selecione Área de trabalho do Windows.
  3. Selecione o modelo de aplicativo Windows Forms (.NET Framework) .
  4. Nomeie-o como HelloComposition, selecione a estrutura .NET Framework 4.7.2 e clique em OK.

O Visual Studio cria o projeto e abre o designer para a janela de aplicativo padrão chamada Form1.cs.

Configurar o projeto para usar APIs do Windows Runtime

Para usar as APIs do WinRT (Windows Runtime) em seu aplicativo Windows Forms, será preciso configurar seu projeto do Visual Studio para acessar o WinRT. Além disso, os vetores são usados amplamente pelas APIs de composição, portanto, é preciso adicionar as referências necessárias para usar vetores.

Os pacotes NuGet estão disponíveis para atender a essas duas necessidades. Instale as versões mais recentes desses pacotes para adicionar as referências necessárias ao projeto.

Observação

Apesar de recomendarmos usar pacotes NuGet para configurar seu projeto, você pode adicionar as referências necessárias manualmente. Para saber mais, veja Aprimorar o aplicativo de área de trabalho para o Windows. A tabela a seguir mostra os arquivos aos quais você deve adicionar referências.

Arquivo Local
System.Runtime.WindowsRuntime C:\Windows\Microsoft.NET\Framework\v4.0.30319
Windows.Foundation.UniversalApiContract.winmd C:\Program Files (x86)\Windows Kits\10\References<sdk version>\Windows.Foundation.UniversalApiContract<version>
Windows.Foundation.FoundationContract.winmd C:\Program Files (x86)\Windows Kits\10\References<sdk version>\Windows.Foundation.FoundationContract<version>
System.Numerics.Vectors.dll C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Numerics.Vectors\v4.0_4.0.0.0__b03f5f7f11d50a3a
System.Numerics.dll C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.2

Criar um controle personalizado para gerenciar a interoperabilidade

Para hospedar o conteúdo criado com a camada visual, crie um controle personalizado derivado de Control. Esse controle fornece acesso a uma janela de Handle, necessária para criar o contêiner para o conteúdo da camada visual.

É aqui que a maior parte da configuração para hospedagem de APIs de Composição é feita. Nesse controle, são usados PInvoke (Serviços de Invocação de Plataforma) e Interoperabilidade COM para trazer APIs de Composição para o aplicativo Windows Forms. Para saber mais sobre PInvoke e Interoperabilidade COM, confira Interoperabilidade com código não gerenciado.

Dica

Se necessário, verifique o código completo no final do tutorial para garantir que todo o código esteja nos locais certos enquanto você trabalha no tutorial.

  1. Adicione um novo arquivo de controle personalizado ao seu projeto que derive de Control.

    • No Gerenciador de Soluções, clique com o botão direito do mouse no projeto HelloComposition.
    • No menu de contexto, selecione Adicionar>Novo item... .
    • Na caixa de diálogo Adicionar Novo Item, selecione Controle Personalizado.
    • Nomeie o controle como CompositionHost.cs e clique em Adicionar. O CompositionHost.cs é aberto no modo de exibição de Design.
  2. Alterne para o modo de exibição de código no CompositionHost.cs e adicione o código a seguir à classe.

    // Add
    // using Windows.UI.Composition;
    
    IntPtr hwndHost;
    object dispatcherQueue;
    protected ContainerVisual containerVisual;
    protected Compositor compositor;
    
    private ICompositionTarget compositionTarget;
    
    public Visual Child
    {
        set
        {
            if (compositor == null)
            {
                InitComposition(hwndHost);
            }
            compositionTarget.Root = value;
        }
    }
    
  3. Adicione o código ao construtor.

    No construtor, são chamados os métodos InitializeCoreDispatcher e InitComposition. Você criará esses métodos nas próximas etapas.

    public CompositionHost()
    {
        InitializeComponent();
    
        // Get the window handle.
        hwndHost = Handle;
    
        // Create dispatcher queue.
        dispatcherQueue = InitializeCoreDispatcher();
    
        // Build Composition tree of content.
        InitComposition(hwndHost);
    }
    
  4. Inicialize um thread com um CoreDispatcher. O dispatcher principal é responsável por processar mensagens de janela e expedir eventos para APIs do WinRT. As novas instâncias do Compositor devem ser criadas em um thread contendo um CoreDispatcher.

    • Crie um método chamado InitializeCoreDispatcher e adicione o código para configurar a fila do dispatcher.
    // Add
    // using System.Runtime.InteropServices;
    
    private object InitializeCoreDispatcher()
    {
        DispatcherQueueOptions options = new DispatcherQueueOptions();
        options.apartmentType = DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_STA;
        options.threadType = DISPATCHERQUEUE_THREAD_TYPE.DQTYPE_THREAD_CURRENT;
        options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
    
        object queue = null;
        CreateDispatcherQueueController(options, out queue);
        return queue;
    }
    
    • A fila do dispatcher requer uma declaração PInvoke. Coloque essa declaração no final do código para a classe. (Colocamos esse código dentro de uma região para manter o código da classe organizado.)
    #region PInvoke declarations
    
    //typedef enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE
    //{
    //    DQTAT_COM_NONE,
    //    DQTAT_COM_ASTA,
    //    DQTAT_COM_STA
    //};
    internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE
    {
        DQTAT_COM_NONE = 0,
        DQTAT_COM_ASTA = 1,
        DQTAT_COM_STA = 2
    };
    
    //typedef enum DISPATCHERQUEUE_THREAD_TYPE
    //{
    //    DQTYPE_THREAD_DEDICATED,
    //    DQTYPE_THREAD_CURRENT
    //};
    internal enum DISPATCHERQUEUE_THREAD_TYPE
    {
        DQTYPE_THREAD_DEDICATED = 1,
        DQTYPE_THREAD_CURRENT = 2,
    };
    
    //struct DispatcherQueueOptions
    //{
    //    DWORD dwSize;
    //    DISPATCHERQUEUE_THREAD_TYPE threadType;
    //    DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType;
    //};
    [StructLayout(LayoutKind.Sequential)]
    internal struct DispatcherQueueOptions
    {
        public int dwSize;
    
        [MarshalAs(UnmanagedType.I4)]
        public DISPATCHERQUEUE_THREAD_TYPE threadType;
    
        [MarshalAs(UnmanagedType.I4)]
        public DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType;
    };
    
    //HRESULT CreateDispatcherQueueController(
    //  DispatcherQueueOptions options,
    //  ABI::Windows::System::IDispatcherQueueController** dispatcherQueueController
    //);
    [DllImport("coremessaging.dll", EntryPoint = "CreateDispatcherQueueController", CharSet = CharSet.Unicode)]
    internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options,
                                            [MarshalAs(UnmanagedType.IUnknown)]
                                            out object dispatcherQueueController);
    
    #endregion PInvoke declarations
    

    Agora que a fila do dispatcher está pronta, você pode começar a inicializar e criar o conteúdo de Composição.

  5. Inicialize o Compositor. O Compositor é uma fábrica que cria uma variedade de tipos no namespace Windows.UI.Composition, abrangendo a camada visual, o sistema de efeitos e o sistema de animação. A classe Compositor também gerencia a vida útil dos objetos criados na fábrica.

    private void InitComposition(IntPtr hwndHost)
    {
        ICompositorDesktopInterop interop;
    
        compositor = new Compositor();
        object iunknown = compositor as object;
        interop = (ICompositorDesktopInterop)iunknown;
        IntPtr raw;
        interop.CreateDesktopWindowTarget(hwndHost, true, out raw);
    
        object rawObject = Marshal.GetObjectForIUnknown(raw);
        compositionTarget = (ICompositionTarget)rawObject;
    
        if (raw == null) { throw new Exception("QI Failed"); }
    
        containerVisual = compositor.CreateContainerVisual();
        Child = containerVisual;
    }
    
    • ICompositorDesktopInterop e ICompositionTarget exigem importações COM. Coloque este código após a classe CompositionHost, mas dentro da declaração do namespace.
    #region COM Interop
    
    /*
    #undef INTERFACE
    #define INTERFACE ICompositorDesktopInterop
        DECLARE_INTERFACE_IID_(ICompositorDesktopInterop, IUnknown, "29E691FA-4567-4DCA-B319-D0F207EB6807")
        {
            IFACEMETHOD(CreateDesktopWindowTarget)(
                _In_ HWND hwndTarget,
                _In_ BOOL isTopmost,
                _COM_Outptr_ IDesktopWindowTarget * *result
                ) PURE;
        };
    */
    [ComImport]
    [Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface ICompositorDesktopInterop
    {
        void CreateDesktopWindowTarget(IntPtr hwndTarget, bool isTopmost, out IntPtr test);
    }
    
    //[contract(Windows.Foundation.UniversalApiContract, 2.0)]
    //[exclusiveto(Windows.UI.Composition.CompositionTarget)]
    //[uuid(A1BEA8BA - D726 - 4663 - 8129 - 6B5E7927FFA6)]
    //interface ICompositionTarget : IInspectable
    //{
    //    [propget] HRESULT Root([out] [retval] Windows.UI.Composition.Visual** value);
    //    [propput] HRESULT Root([in] Windows.UI.Composition.Visual* value);
    //}
    
    [ComImport]
    [Guid("A1BEA8BA-D726-4663-8129-6B5E7927FFA6")]
    [InterfaceType(ComInterfaceType.InterfaceIsIInspectable)]
    public interface ICompositionTarget
    {
        Windows.UI.Composition.Visual Root
        {
            get;
            set;
        }
    }
    
    #endregion COM Interop
    

Criar um controle personalizado para hospedar elementos de composição

Recomendamos colocar o código que gera e gerencia seus elementos de composição em um controle separado que derive de CompositionHost. Isso faz com que o código de interoperabilidade criado na classe CompositionHost seja reutilizável.

Aqui, você cria um controle personalizado derivado de CompositionHost. Esse controle é adicionado à caixa de ferramentas do Visual Studio para que você possa adicioná-lo a seu formulário.

  1. Adicione um novo arquivo de controle personalizado a seu projeto que derive de CompositionHost.

    • No Gerenciador de Soluções, clique com o botão direito do mouse no projeto HelloComposition.
    • No menu de contexto, selecione Adicionar>Novo item... .
    • Na caixa de diálogo Adicionar Novo Item, selecione Controle Personalizado.
    • Nomeie o controle como CompositionHostControl.cs e clique em Adicionar. O CompositionHostControl.cs é aberto no modo de exibição de Design.
  2. No painel Propriedades do modo de exibição de Design de CompositionHostControl.cs, defina a propriedade BackColor como ControlLight.

    A configuração da cor de fundo é opcional. Fazemos isso aqui para que você possa ver seu controle personalizado na tela de fundo do formulário.

  3. Alterne para o modo de exibição de código no CompositionHostControl.cs e atualize a declaração de classe para que ela derive de CompositionHost.

    class CompositionHostControl : CompositionHost
    
  4. Atualize o construtor de modo a chamar o construtor base.

    public CompositionHostControl() : base()
    {
    
    }
    

Adicionar elementos de composição

Com a infraestrutura em vigor, agora você pode adicionar o conteúdo de Composição à interface do usuário do aplicativo.

Neste exemplo, o código é adicionado à classe CompositionHostControl, que cria e anima um SpriteVisual simples.

  1. Adicione um elemento de composição.

    No CompositionHostControl.cs, adicione estes métodos à classe CompositionHostControl.

    // Add
    // using Windows.UI.Composition;
    
    public void AddElement(float size, float offsetX, float offsetY)
    {
        var visual = compositor.CreateSpriteVisual();
        visual.Size = new Vector2(size, size); // Requires references
        visual.Brush = compositor.CreateColorBrush(GetRandomColor());
        visual.Offset = new Vector3(offsetX, offsetY, 0);
        containerVisual.Children.InsertAtTop(visual);
    
        AnimateSquare(visual, 3);
    }
    
    private void AnimateSquare(SpriteVisual visual, int delay)
    {
        float offsetX = (float)(visual.Offset.X);
        Vector3KeyFrameAnimation animation = compositor.CreateVector3KeyFrameAnimation();
        float bottom = Height - visual.Size.Y;
        animation.InsertKeyFrame(1f, new Vector3(offsetX, bottom, 0f));
        animation.Duration = TimeSpan.FromSeconds(2);
        animation.DelayTime = TimeSpan.FromSeconds(delay);
        visual.StartAnimation("Offset", animation);
    }
    
    private Windows.UI.Color GetRandomColor()
    {
        Random random = new Random();
        byte r = (byte)random.Next(0, 255);
        byte g = (byte)random.Next(0, 255);
        byte b = (byte)random.Next(0, 255);
        return Windows.UI.Color.FromArgb(255, r, g, b);
    }
    

Adicionar o controle ao formulário

Agora que há um controle personalizado para hospedar o conteúdo de Composição, é possível adicioná-lo à interface do usuário do aplicativo. Aqui, você adiciona uma instância do CompositionHostControl, criado na etapa anterior. O CompositionHostControl é adicionado automaticamente à caixa de ferramentas do Visual Studio em nome do projeto Componentes.

  1. Adicione um botão à interface do usuário no modo de exibição de Design de Form1.CS.

    • Arraste um botão da caixa de ferramentas para o Form1. Coloque-o no canto superior esquerdo do formulário. (Confira a imagem no início do tutorial para verificar o posicionamento dos controles.)
    • No painel Propriedades, altere a propriedade Text de button1 para Adicionar elemento de composição.
    • Redimensione o botão para que todo o texto seja mostrado.

    (Para obter mais informações, confira Como adicionar controles ao Windows Forms.)

  2. Adicione um CompositionHostControl à interface do usuário.

    • Arraste um CompositionHostControl da caixa de ferramentas para o Form1. Coloque-o à direita do botão.
    • Redimensione o CompositionHost para que ele preencha o restante do formulário.
  3. Manipule o evento de clique no botão.

    • No painel Propriedades, clique no ícone de relâmpago a fim de alternar para o modo de exibição de Eventos.
    • Na lista exibida, selecione o evento de Clique, digite Button_Click e pressione Enter.
    • O seguinte código é adicionado ao Form1.cs:
    private void Button_Click(object sender, EventArgs e)
    {
    
    }
    
  4. Adicione código ao manipulador de clique de botão para criar novos elementos.

    • Em Form1.cs, adicione código ao manipulador de eventos Button_Click que você criou anteriormente. Este código chama CompositionHostControl1.AddElement para criar um novo elemento com um tamanho e deslocamento gerados aleatoriamente. (A instância de CompositionHostControl é nomeada automaticamente como compositionHostControl1 quando arrastada para o formulário.)
    // Add
    // using System;
    
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Random random = new Random();
        float size = random.Next(50, 150);
        float offsetX = random.Next(0, (int)(compositionHostControl1.Width - size));
        float offsetY = random.Next(0, (int)(compositionHostControl1.Height/2 - size));
        compositionHostControl1.AddElement(size, offsetX, offsetY);
    }
    

Agora você pode compilar e executar seu aplicativo Windows Forms. Ao clicar no botão, você deverá ver quadrados animados adicionados à interface do usuário.

Próximas etapas

Para ver um exemplo mais completo desenvolvido com a mesma infraestrutura, confira o Exemplo de integração de Camada visual do Windows Forms no GitHub.

Recursos adicionais

Código completo

Este é o código completo deste tutorial.

Form1.cs

using System;
using System.Windows.Forms;

namespace HelloComposition
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, EventArgs e)
        {
            Random random = new Random();
            float size = random.Next(50, 150);
            float offsetX = random.Next(0, (int)(compositionHostControl1.Width - size));
            float offsetY = random.Next(0, (int)(compositionHostControl1.Height/2 - size));
            compositionHostControl1.AddElement(size, offsetX, offsetY);
        }
    }
}

CompositionHostControl.cs

using System;
using System.Numerics;
using Windows.UI.Composition;

namespace HelloComposition
{
    class CompositionHostControl : CompositionHost
    {
        public CompositionHostControl() : base()
        {

        }

        public void AddElement(float size, float offsetX, float offsetY)
        {
            var visual = compositor.CreateSpriteVisual();
            visual.Size = new Vector2(size, size); // Requires references
            visual.Brush = compositor.CreateColorBrush(GetRandomColor());
            visual.Offset = new Vector3(offsetX, offsetY, 0);
            containerVisual.Children.InsertAtTop(visual);

            AnimateSquare(visual, 3);
        }

        private void AnimateSquare(SpriteVisual visual, int delay)
        {
            float offsetX = (float)(visual.Offset.X);
            Vector3KeyFrameAnimation animation = compositor.CreateVector3KeyFrameAnimation();
            float bottom = Height - visual.Size.Y;
            animation.InsertKeyFrame(1f, new Vector3(offsetX, bottom, 0f));
            animation.Duration = TimeSpan.FromSeconds(2);
            animation.DelayTime = TimeSpan.FromSeconds(delay);
            visual.StartAnimation("Offset", animation);
        }

        private Windows.UI.Color GetRandomColor()
        {
            Random random = new Random();
            byte r = (byte)random.Next(0, 255);
            byte g = (byte)random.Next(0, 255);
            byte b = (byte)random.Next(0, 255);
            return Windows.UI.Color.FromArgb(255, r, g, b);
        }
    }
}

CompositionHost.cs

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Windows.UI.Composition;

namespace HelloComposition
{
    public partial class CompositionHost : Control
    {
        IntPtr hwndHost;
        object dispatcherQueue;
        protected ContainerVisual containerVisual;
        protected Compositor compositor;
        private ICompositionTarget compositionTarget;

        public Visual Child
        {
            set
            {
                if (compositor == null)
                {
                    InitComposition(hwndHost);
                }
                compositionTarget.Root = value;
            }
        }

        public CompositionHost()
        {
            // Get the window handle.
            hwndHost = Handle;

            // Create dispatcher queue.
            dispatcherQueue = InitializeCoreDispatcher();

            // Build Composition tree of content.
            InitComposition(hwndHost);
        }

        private object InitializeCoreDispatcher()
        {
            DispatcherQueueOptions options = new DispatcherQueueOptions();
            options.apartmentType = DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_STA;
            options.threadType = DISPATCHERQUEUE_THREAD_TYPE.DQTYPE_THREAD_CURRENT;
            options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));

            object queue = null;
            CreateDispatcherQueueController(options, out queue);
            return queue;
        }

        private void InitComposition(IntPtr hwndHost)
        {
            ICompositorDesktopInterop interop;

            compositor = new Compositor();
            object iunknown = compositor as object;
            interop = (ICompositorDesktopInterop)iunknown;
            IntPtr raw;
            interop.CreateDesktopWindowTarget(hwndHost, true, out raw);

            object rawObject = Marshal.GetObjectForIUnknown(raw);
            compositionTarget = (ICompositionTarget)rawObject;

            if (raw == null) { throw new Exception("QI Failed"); }

            containerVisual = compositor.CreateContainerVisual();
            Child = containerVisual;
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
        }

        #region PInvoke declarations

        //typedef enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE
        //{
        //    DQTAT_COM_NONE,
        //    DQTAT_COM_ASTA,
        //    DQTAT_COM_STA
        //};
        internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE
        {
            DQTAT_COM_NONE = 0,
            DQTAT_COM_ASTA = 1,
            DQTAT_COM_STA = 2
        };

        //typedef enum DISPATCHERQUEUE_THREAD_TYPE
        //{
        //    DQTYPE_THREAD_DEDICATED,
        //    DQTYPE_THREAD_CURRENT
        //};
        internal enum DISPATCHERQUEUE_THREAD_TYPE
        {
            DQTYPE_THREAD_DEDICATED = 1,
            DQTYPE_THREAD_CURRENT = 2,
        };

        //struct DispatcherQueueOptions
        //{
        //    DWORD dwSize;
        //    DISPATCHERQUEUE_THREAD_TYPE threadType;
        //    DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType;
        //};
        [StructLayout(LayoutKind.Sequential)]
        internal struct DispatcherQueueOptions
        {
            public int dwSize;

            [MarshalAs(UnmanagedType.I4)]
            public DISPATCHERQUEUE_THREAD_TYPE threadType;

            [MarshalAs(UnmanagedType.I4)]
            public DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType;
        };

        //HRESULT CreateDispatcherQueueController(
        //  DispatcherQueueOptions options,
        //  ABI::Windows::System::IDispatcherQueueController** dispatcherQueueController
        //);
        [DllImport("coremessaging.dll", EntryPoint = "CreateDispatcherQueueController", CharSet = CharSet.Unicode)]
        internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options,
                                                 [MarshalAs(UnmanagedType.IUnknown)]
                                        out object dispatcherQueueController);

        #endregion PInvoke declarations
    }

    #region COM Interop

    /*
    #undef INTERFACE
    #define INTERFACE ICompositorDesktopInterop
        DECLARE_INTERFACE_IID_(ICompositorDesktopInterop, IUnknown, "29E691FA-4567-4DCA-B319-D0F207EB6807")
        {
            IFACEMETHOD(CreateDesktopWindowTarget)(
                _In_ HWND hwndTarget,
                _In_ BOOL isTopmost,
                _COM_Outptr_ IDesktopWindowTarget * *result
                ) PURE;
        };
    */
    [ComImport]
    [Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface ICompositorDesktopInterop
    {
        void CreateDesktopWindowTarget(IntPtr hwndTarget, bool isTopmost, out IntPtr test);
    }

    //[contract(Windows.Foundation.UniversalApiContract, 2.0)]
    //[exclusiveto(Windows.UI.Composition.CompositionTarget)]
    //[uuid(A1BEA8BA - D726 - 4663 - 8129 - 6B5E7927FFA6)]
    //interface ICompositionTarget : IInspectable
    //{
    //    [propget] HRESULT Root([out] [retval] Windows.UI.Composition.Visual** value);
    //    [propput] HRESULT Root([in] Windows.UI.Composition.Visual* value);
    //}

    [ComImport]
    [Guid("A1BEA8BA-D726-4663-8129-6B5E7927FFA6")]
    [InterfaceType(ComInterfaceType.InterfaceIsIInspectable)]
    public interface ICompositionTarget
    {
        Windows.UI.Composition.Visual Root
        {
            get;
            set;
        }
    }
    #endregion COM Interop
}