Visualizzare una visualizzazione XNA direttamente in una finestra WPF
sommario
Viene descritto come eseguire il rendering direttamente in una finestra WPF con XNA.
Ambiente operativo
Prerequisiti
Versioni XNA supportate |
|
Piattaforme supportate |
|
Versione Vertex Shader richiesta da Windows | 1.1 |
Versione Pixel Shader richiesta da Windows | 1.1 |
Ambiente operativo
piattaforma |
sostanza
In Utilizzo di XNA nelle applicazioni WPF, ho utilizzato il controllo WindowsFormsHost per visualizzare la visualizzazione, ma ora desidero utilizzare solo la finestra WPF per visualizzare il poligono. "Utilizzo di XNA nelle applicazioni WPF" è un po' una rappresentazione, quindi spiegherò le differenze.
Alias dello spazio dei nomi
// 名前空間エイリアス
using Xna = Microsoft.Xna.Framework;
using XnaGraphics = Microsoft.Xna.Framework.Graphics;
Poiché le strutture Color e Matrix sono coperte dagli spazi dei nomi XNA Framework e WPF, è necessario specificare il nome della struttura dallo spazio dei nomi per poterla utilizzare. Tuttavia, sembra essere lungo ogni volta, quindi sto creando un alias del namespace. Ad esempio, "Microsoft.Xna.Framework.Rectangle" può ora essere specificato come "Xna.Rectangle".
temporizzatore
A partire da .NET Framework 3.0, è disponibile una classe timer denominata "System.Windows.Threading.DispatcherTimer" e questa classe timer viene utilizzata per eseguire il rendering di ogni fotogramma. WPF utilizza un DispatcherTimer per consentire l'elaborazione sullo stesso thread dell'interfaccia utente.
<summary>
タイマー
</summary>
private DispatcherTimer timer = null;
, dichiarando un DispatcherTimer.
<summary>
タイマーイベント
</summary>
<param name="sender"></param>
<param name="e"></param>
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
this.Draw();
}
Definisce un metodo che DispatcherTimer chiama a intervalli regolari.
// タイマー
this.timer = new DispatcherTimer();
this.timer.Tick += new EventHandler(dispatcherTimer_Tick);
this.timer.Interval = new TimeSpan(0, 0, 0, 0, 16);
this.timer.Start();
Questo è il processo di impostazione del timer. Dopo aver creato un'istanza di DispatcherTimer e aver impostato il metodo da chiamare e l'intervallo di tempo, il metodo DispatcherTimer.Start avvia il timer.
Ottenere una maniglia per finestra
Per creare un dispositivo Direct3D, è necessaria una maniglia della finestra. Tuttavia, WPF non ha il concetto di handle di finestra, quindi non è possibile ottenerlo direttamente dalla classe Window.
Tuttavia, poiché in alcuni casi è necessario un handle di finestra, come in questo caso, l'handle di finestra può essere ottenuto tramite la classe "System.Windows.Interop.WindowInteropHelper" come interoperabilità per il codice Win32. (questa è la classe Window)
// ウィンドウハンドルを取得する
IntPtr handle = new WindowInteropHelper(this).Handle;
Usare questo handle quando si crea un dispositivo Direct3D. Tuttavia, se si tenta di ottenere l'handle della finestra nel metodo OnInitialized, restituirà 0, probabilmente perché la finestra non è stata ancora creata. In questo esempio il dispositivo viene creato nel metodo OnSourceInitialized.
Rendering in un'area specificata
È possibile specificare l'area di destinazione come secondo argomento di GraphicsDevice.Present. Nell'esempio, provo a disegnarlo nella posizione (50, 50) come offset. La dimensione è uguale alla dimensione del backbuffer (300, 300). Il primo argomento è l'area da cui attingere e, se viene specificato null, viene utilizzato il buffer originale.
// 描画先を指定する
Xna.Rectangle rect = new Xna.Rectangle(
50, 50,
(int)this.viewSize.Width, (int)this.viewSize.Height);
this.device.Present(null, rect, this.windowHandle);
Eliminazione di un dispositivo
Stai distruggendo il tuo dispositivo quando chiudi la finestra. Originariamente, volevo gestirlo con il metodo Dispose, ma poiché la classe WPF Window non eredita IDisposable per impostazione predefinita, l'ho scritta qui.
<summary>
ウインドウが閉じたとき
</summary>
<param name="e"></param>
protected override void OnClosed(EventArgs e)
{
if (this.device != null)
{
this.device.Dispose();
this.device = null;
}
base.OnClosed(e);
}
esecuzione
Se si esegue il programma di esempio, è possibile eseguirlo con un'immagine dello schermo come quella all'inizio dell'articolo.
A prima vista, il rendering è buono, ma quando ridimensiono la finestra trascinandola con il mouse, la vista sfarfalla o scompare durante il ridimensionamento. Sembra essere in conflitto con il rendering WPF e ho provato molte cose ma non sono riuscito a risolverlo.
Se si utilizza XNA, sembra più sicuro utilizzare il controllo WindowsFormsHost.
Il programma richiede .NET Framework 3.0, l'ultimo runtime DirectX e Microsoft XNA Framework Redistributable 2.0. Inoltre, come requisito hardware, è necessaria "una scheda grafica che supporti Pixel Shader 1.1 o superiore".
Inoltre, il progetto è stato creato in "Visual Studio 2008 Professional Edition". Preparare un ambiente per Visual Studio 2008.