Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
È possibile usare le API di composizione Windows Runtime (denominate anche layer Visual) nelle app Windows Forms per creare esperienze moderne che si illuminano per gli utenti di Windows.
Il codice completo per questa esercitazione è disponibile su GitHub: Windows Forms HelloComposition sample.
Prerequisiti
L'API di hosting UWP presenta questi prerequisiti.
- Si supponga di avere familiarità con lo sviluppo di app usando Windows Forms e UWP. Per altre informazioni, vedere:
- .NET Framework 4.7.2 o versione successiva
- Windows 10 versione 1803 o successive
- Windows 10 SDK 17134 o versioni successive
Come usare le API di composizione in Windows Forms
In questa esercitazione si crea una semplice interfaccia utente Windows Forms e si aggiungono elementi Composition animati. Entrambi i componenti Windows Forms e Composition vengono mantenuti semplici, ma il codice di interoperabilità mostrato è lo stesso indipendentemente dalla complessità dei componenti. L'app completata ha un aspetto simile al seguente.
Creare un progetto Windows Forms
Il primo passaggio consiste nel creare il progetto di app Windows Forms, che include una definizione dell'applicazione e il modulo principale per l'interfaccia utente.
Per creare un nuovo progetto applicazione di Windows Forms in Visual C# denominato HelloComposition:
- Apri Visual Studio e seleziona File>Nuovo>Progetto.
Verrà visualizzata la finestra di dialogo Nuovo progetto. - Nella categoria Installed espandere il nodo Visual C# e quindi selezionare Windows Desktop.
- Selezionare il modello Windows Forms App (.NET Framework).
- Immettere il nome HelloComposition, selezionare Framework .NET Framework 4.7.2, quindi fare clic su OK.
Visual Studio crea il progetto e apre la finestra di progettazione per la finestra dell'applicazione predefinita denominata Form1.cs.
Configurare il progetto per l'uso delle API di Windows Runtime
Per usare le API Windows Runtime (WinRT) nell'app Windows Forms, è necessario configurare il progetto di Visual Studio per accedere al Windows Runtime. Inoltre, i vettori vengono usati ampiamente dalle API di composizione, quindi è necessario aggiungere i riferimenti necessari per usare i vettori.
I pacchetti NuGet sono disponibili per soddisfare entrambe queste esigenze. Installare le versioni più recenti di questi pacchetti per aggiungere i riferimenti necessari al progetto.
- Microsoft.Windows. SDK. Contracts (richiede il formato di gestione dei pacchetti predefinito impostato su PackageReference).
- System.Numerics.Vectors
Note
Anche se è consigliabile usare i pacchetti NuGet per configurare il progetto, è possibile aggiungere manualmente i riferimenti necessari. Per ulteriori informazioni, vedi Migliora l'applicazione desktop per Windows. La tabella seguente illustra i file a cui è necessario aggiungere riferimenti.
| File | Location |
|---|---|
| System.Runtime.WindowsRuntime | C:\Windows\Microsoft.NET\Framework\v4.0.30319 |
| Windows.Foundation.UniversalApiContract.winmd | C:\Programmi (x86)\Windows Kits\10\References<sdk version>\Windows.Foundation.UniversalApiContract<version> |
| Windows.Foundation.FoundationContract.winmd | C:\Programmi (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:\Programmi (x86)\Assembly di riferimento\Microsoft\Framework.NETFramework\v4.7.2 |
Creare un controllo personalizzato per gestire l'interoperabilità
Per ospitare il contenuto creato con il livello visivo, creare un controllo personalizzato derivato da Control. Questo controllo consente di accedere a un handle di finestra, necessario per creare il contenitore per il contenuto del livello visivo.
Questa è la posizione in cui si esegue la maggior parte della configurazione per l'hosting delle API di composizione. In questo controllo si usano Platform Invocation Services (PInvoke) e COM Interop per inserire le API composition nell'app Windows Forms. Per altre info su PInvoke e interoperabilità COM, vedi Interoperabilità con codice non gestito.
Suggerimento
Se necessario, controlla il codice completo alla fine dell'esercitazione per assicurarti che tutto il codice sia nelle posizioni corrette man mano che procedi con l'esercitazione.
Aggiungere un nuovo file di controllo personalizzato al progetto che deriva da Control.
- In Esplora soluzioni fai clic con il pulsante destro del mouse sul progetto HelloComposition.
- Nel menu di scelta rapida selezionare Aggiungi>nuovo elemento....
- Nella finestra di dialogo Aggiungi nuovo elemento selezionare Controllo personalizzato.
- Assegnare al controllo il nome CompositionHost.cs, quindi fare clic su Aggiungi. CompositionHost.cs si apre nella visualizzazione Struttura.
Passare alla visualizzazione codice per CompositionHost.cs e aggiungere il codice seguente alla 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; } }Aggiungere codice al costruttore.
Nel costruttore si chiamano i metodi InitializeCoreDispatcher e InitComposition . Questi metodi vengono creati nei passaggi successivi.
public CompositionHost() { InitializeComponent(); // Get the window handle. hwndHost = Handle; // Create dispatcher queue. dispatcherQueue = InitializeCoreDispatcher(); // Build Composition tree of content. InitComposition(hwndHost); }Inizializzare un thread con CoreDispatcher. Il dispatcher principale è responsabile dell'elaborazione dei messaggi della finestra e dell'invio di eventi per le API WinRT. È necessario creare nuove istanze di Compositor in un thread con CoreDispatcher.
- Creare un metodo denominato InitializeCoreDispatcher e aggiungere il codice per configurare la coda del 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; }- La coda del dispatcher richiede una dichiarazione PInvoke. Inserire questa dichiarazione alla fine del codice per la classe . Questo codice viene inserito all'interno di un'area per mantenere ordinato il codice della classe.
#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 declarationsA questo punto la coda dispatcher è pronta e puoi iniziare a inizializzare e creare il contenuto di composizione.
Inizializzare il Compositor. Il Compositor è una factory che crea una varietà di tipi nel namespace Windows.UI.Composition, comprendente il livello visivo, il sistema di effetti e il sistema di animazione. La classe Compositor gestisce anche la durata degli oggetti creati dalla factory.
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 richiedono importazioni COM. Inserire questo codice dopo la classe CompositionHost , ma all'interno della dichiarazione dello spazio dei nomi.
#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
Creare un controllo personalizzato per ospitare elementi di composizione
È consigliabile inserire il codice che genera e gestisce gli elementi di composizione in un controllo separato che deriva da CompositionHost. In questo modo viene mantenuto riutilizzabile il codice di interoperabilità creato nella classe CompositionHost.
Qui si crea un controllo personalizzato derivato da CompositionHost. Questo controllo viene aggiunto alla casella degli strumenti Visual Studio in modo da poterlo aggiungere al modulo.
Aggiungere un nuovo file di controllo personalizzato al progetto che deriva da CompositionHost.
- In Esplora soluzioni fai clic con il pulsante destro del mouse sul progetto HelloComposition.
- Nel menu di scelta rapida selezionare Aggiungi>nuovo elemento....
- Nella finestra di dialogo Aggiungi nuovo elemento selezionare Controllo personalizzato.
- Assegnare al controllo il nome CompositionHostControl.cs, quindi fare clic su Aggiungi. CompositionHostControl.cs si apre nella visualizzazione Struttura.
Nel riquadro Proprietà per CompositionHostControl.cs, in visualizzazione struttura, impostare la proprietà BackColor su ControlLight.
L'impostazione del colore di sfondo è facoltativa. Questa operazione viene eseguita in modo da poter visualizzare il controllo personalizzato sullo sfondo del modulo.
Passare alla visualizzazione codice per CompositionHostControl.cs e aggiornare la dichiarazione di classe per derivare da CompositionHost.
class CompositionHostControl : CompositionHostAggiornare il costruttore al fine di chiamare il costruttore di base.
public CompositionHostControl() : base() { }
Aggiungere elementi di composizione
Con l'infrastruttura sul posto, è ora possibile aggiungere contenuto di composizione all'interfaccia utente dell'app.
Per questo esempio, si aggiunge codice alla classe CompositionHostControl che crea e anima un semplice SpriteVisual.
Aggiungi un elemento di composizione.
In CompositionHostControl.cs aggiungere questi metodi alla 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); }
Aggiungere il controllo al modulo
Ora che hai un controllo personalizzato per ospitare il contenuto di Composizione, puoi aggiungerlo all'interfaccia utente dell'app. In questo caso si aggiunge un'istanza di CompositionHostControl creata nel passaggio precedente. CompositionHostControl viene aggiunto automaticamente alla casella degli strumenti Visual Studio in nome progetto Components.
Nella visualizzazione struttura di Form1.CS, aggiungi un pulsante all'interfaccia utente.
- Trascinare un pulsante dalla casella degli strumenti in Form1. Posizionarlo nell'angolo superiore sinistro del form. Vedere l'immagine all'inizio dell'esercitazione per controllare il posizionamento dei controlli.
- Nel riquadro Proprietà modificare la proprietà Text da button1 a Aggiungi elemento di composizione.
- Ridimensionare il pulsante in modo che tutto il testo venga visualizzato.
Per altre info, vedi Come: Aggiungere controlli a Windows Forms.
Aggiungere compositionHostControl all'interfaccia utente.
- Trascinare compositionHostControl dalla casella degli strumenti in Form1. Posizionarlo a destra del pulsante.
- Ridimensionare CompositionHost in modo che riempia il resto del modulo.
Gestire l'evento clic del pulsante.
- Nel riquadro Proprietà fare clic sul fulmine per passare alla visualizzazione Eventi.
- Nell'elenco degli eventi selezionare l'evento Click , digitare Button_Click e premere INVIO.
- Questo codice viene aggiunto in Form1.cs:
private void Button_Click(object sender, EventArgs e) { }Aggiungere il codice al gestore di clic del pulsante per creare nuovi elementi.
- In Form1.cs aggiungere codice al gestore eventi Button_Click creato in precedenza. Questo codice chiama CompositionHostControl1.AddElement per creare un nuovo elemento con dimensioni e offset generati in modo casuale. L'istanza di CompositionHostControl è stata denominata automaticamente compositionHostControl1 quando è stata trascinata nel form.
// 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); }
È ora possibile compilare ed eseguire l'app Windows Forms. Quando si fa clic sul pulsante, vengono visualizzati quadrati animati aggiunti all'interfaccia utente.
Passaggi successivi
Per un esempio più completo basato sulla stessa infrastruttura, vedere l'esempio di integrazione del livello visivo Windows Forms su GitHub.
Risorse aggiuntive
- Introduzione a Windows Forms (.NET)
- Interoperabilità con codice non gestito (.NET)
- Iniziare a usare le app di Windows (piattaforma UWP)
- Migliorare un'applicazione desktop per Windows (piattaforma UWP)
- Namespace Windows.UI.Composition (UWP)
Codice completo
Ecco il codice completo per questa esercitazione.
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
}