Partilhar via


Usando a camada visual com o Windows Forms

Você pode usar as APIs de composição do Tempo de Execução do Windows (também chamadas de camada Visual) nas suas aplicações Windows Forms para criar experiências modernas que proporcionam experiências inovadoras aos utilizadores do Windows.

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

Pré-requisitos

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

Como usar APIs de composição no Windows Forms

Neste tutorial, você cria uma interface do usuário simples do Windows Forms e adiciona elementos de composição animados a ela. Os componentes Windows Forms e Composition são mantidos simples, mas o código de interoperabilidade mostrado é 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 do Windows Forms

A primeira etapa é criar o projeto de aplicativo Windows Forms, que inclui uma definição de aplicativo e o formulário principal para a interface do usuário.

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

  1. Abra o Visual Studio e selecione Arquivo>Novo Projeto>.
    Abre-se a caixa de diálogo New Project.
  2. Na categoria Instalado, expanda o nó Visual C# e, em seguida, selecione Windows Desktop.
  3. Selecione o modelo Windows Forms App (.NET Framework).
  4. Digite o nome HelloComposition, selecione Framework .NET Framework 4.7.2e, em seguida, clique em OK.

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 Tempo de Execução do Windows

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

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

Observação

Embora seja recomendável usar os pacotes NuGet para configurar seu projeto, você pode adicionar as referências necessárias manualmente. Para mais informações, consulte Melhorar a sua aplicação de ambiente de trabalho para Windows. A tabela a seguir mostra os arquivos aos quais você precisa adicionar referências.

Ficheiro Localização
System.Runtime.WindowsRuntime C:\Windows\Microsoft.NET\Framework\v4.0.30319
Windows.Foundation.UniversalApiContract.winmd C:\Program Files (x86)\Windows Kits\10\References<versão do SDK>\Windows.Foundation.UniversalApiContract<versão>
Windows.Foundation.FoundationContract.winmd C:\Program Files (x86)\Windows Kits\10\References<versão do SDK>\Windows.Foundation.FoundationContract<versão>
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:\Arquivos de Programas (x86)\Assemblies de Referência\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 do Control. Esse controle lhe dá acesso a uma janela Handle, que você precisa para criar o contêiner para o conteúdo da camada visual.

É aqui que você faz a maior parte da configuração para hospedar APIs de composição. Nesse controle, você usa de Serviços de Invocação de Plataforma (PInvoke) e de Interoperabilidade COM para trazer APIs de Composição para seu aplicativo Windows Forms. Para obter mais informações sobre PInvoke e Interop COM, consulte Interoperar com código não gerido.

Sugestão

Se você precisar, verifique o código completo no final do tutorial para se certificar de que todo o código está nos lugares certos enquanto você trabalha no tutorial.

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

    • No Explorador 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 Controlo Personalizado.
    • Nomeie o controle CompositionHost.cse, em seguida, clique em Adicionar. CompositionHost.cs é aberto na visualização Design.
  2. Alterne para a visualização de código para CompositionHost.cs e adicione o seguinte código à 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 código ao construtor.

    No construtor, você chama os métodos InitializeCoreDispatcher e InitComposition. Você cria 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 gestor principal é responsável pelo processamento de mensagens de janela e pelo envio de eventos para as APIs do WinRT. Novas instâncias de Compositor devem ser criadas num thread que tenha um CoreDispatcher.

    • Crie um método chamado InitializeCoreDispatcher e adicione 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 esta declaração no final do código da classe. (Colocamos esse código dentro de uma região para manter o código de 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 você tem a fila do dispatcher pronta e pode começar a inicializar e criar 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 o tempo de vida dos objetos criados de 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 esse código após a classe CompositionHost, mas dentro da declaração de 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

É uma boa ideia colocar o código que gera e gerencia seus elementos de composição em um controle separado que deriva de CompositionHost. Isso mantém o código de interoperabilidade criado na classe CompositionHost 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 ao formulário.

  1. Adicione um novo arquivo de controle personalizado ao seu projeto que deriva de CompositionHost.

    • No Explorador 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 Controlo Personalizado.
    • Nomeie o controle CompositionHostControl.cse, em seguida, clique em Adicionar. CompositionHostControl.cs é aberto na visualização Design.
  2. No painel Propriedades para a vista de design de CompositionHostControl.cs, defina a propriedade BackColor como ControlLight.

    Definir a cor de fundo é opcional. Fazemos isso aqui para que você possa ver seu controle personalizado no plano de fundo do formulário.

  3. Mude para a vista de código de CompositionHostControl.cs e atualize a declaração de classe para derivar de CompositionHost.

    class CompositionHostControl : CompositionHost
    
  4. Atualize o construtor para chamar o construtor base.

    public CompositionHostControl() : base()
    {
    
    }
    

Adicionar elementos de composição

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

Neste exemplo, você adiciona código à classe CompositionHostControl que cria e anima umSpriteVisual simples.

  1. Adicione um elemento de composição.

    No CompositionHostControl.cs, adicione esses 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 você tem um controle personalizado para hospedar o conteúdo de Composition, pode adicioná-lo à interface do utilizador da aplicação. Aqui, você adiciona uma instância do CompositionHostControl que você criou na etapa anterior. CompositionHostControl é adicionado automaticamente à caixa de ferramentas do Visual Studio sob o nome do projeto Components.

  1. Na visualização Form1.CS design, adicione um Button à interface do usuário.

    • Arraste um botão da caixa de ferramentas para o Form1. Coloque-o no canto superior esquerdo do formulário. (Veja 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 exibido.

    (Para obter mais informações, consulte 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 do botão.

    • No painel Propriedades, clique no ícone de raio para alternar para a vista de Eventos.
    • Na lista de eventos, selecione o evento Clique, digite Button_Clicke pressione a tecla Enter.
    • Este código é aditado em 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.

    • No Form1.cs, adicione código ao manipulador de eventos Button_Click criado anteriormente. Esse código chama CompositionHostControl1.AddElement para criar um novo elemento com um tamanho e deslocamento gerados aleatoriamente. (A instância de CompositionHostControl foi nomeada automaticamente compositionHostControl1 quando você a arrastou 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 criar e executar seu aplicativo Windows Forms. Ao clicar no botão, você verá quadrados animados adicionados à interface do usuário.

Próximos passos

Para obter um exemplo mais completo que se baseia na mesma infraestrutura, consulte o Exemplo de integração de camada Visual do Windows Forms no GitHub.

Recursos adicionais

Código completo

Aqui está o código completo para este 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
}