Anzeigen einer XNA-Ansicht direkt in einem WPF-Fenster
Zusammenfassung
Beschreibt, wie mit XNA direkt in einem WPF-Fenster gerendert wird.
Betriebsumgebung
Voraussetzungen
Unterstützte XNA-Versionen |
|
Unterstützte Plattformen |
|
Erforderliche Vertex-Shader-Version für Windows | 1.1 |
Erforderliche Pixel-Shader-Version für Windows | 1.1 |
Betriebsumgebung
Bahnsteig |
Substanz
In Verwenden von XNA in WPF-Anwendungen habe ich das WindowsFormsHost-Steuerelement verwendet, um die Ansicht anzuzeigen, aber jetzt möchte ich nur das WPF-Fenster verwenden, um das Polygon anzuzeigen. "Verwenden von XNA in WPF-Anwendungen" ist eine Art Darstellung, daher werde ich die Unterschiede erläutern.
Namespace-Aliase
// 名前空間エイリアス
using Xna = Microsoft.Xna.Framework;
using XnaGraphics = Microsoft.Xna.Framework.Graphics;
Da die Color- und Matrix-Strukturen von den XNA Framework- und WPF-Namespaces abgedeckt werden, müssen Sie den Namen der Struktur aus dem Namespace angeben, um sie verwenden zu können. Es scheint jedoch jedes Mal lang zu sein, daher erstelle ich einen Namespace-Alias. Beispielsweise kann "Microsoft.Xna.Framework.Rectangle" jetzt als "Xna.Rectangle" angegeben werden.
Zeitschaltuhr
Seit .NET Framework 3.0 ist eine Timerklasse mit dem Namen "System.Windows.Threading.DispatcherTimer" verfügbar, und diese Timerklasse wird zum Rendern jedes Frames verwendet. WPF verwendet einen DispatcherTimer, um die Verarbeitung im selben Thread wie die Benutzeroberfläche zu ermöglichen.
<summary>
タイマー
</summary>
private DispatcherTimer timer = null;
und deklariert einen DispatcherTimer.
<summary>
タイマーイベント
</summary>
<param name="sender"></param>
<param name="e"></param>
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
this.Draw();
}
Definiert eine Methode, die von DispatcherTimer in regelmäßigen Abständen aufgerufen wird.
// タイマー
this.timer = new DispatcherTimer();
this.timer.Tick += new EventHandler(dispatcherTimer_Tick);
this.timer.Interval = new TimeSpan(0, 0, 0, 0, 16);
this.timer.Start();
Dies ist der Prozess des Einstellens des Timers. Nach dem Erstellen einer Instanz von DispatcherTimer und dem Festlegen der aufgerufenen Methode und des Zeitintervalls startet die DispatcherTimer.Start-Methode den Timer.
Abrufen eines Fenstergriffs
Zum Erstellen eines Direct3D-Geräts benötigen Sie ein Fensterhandle. WPF verfügt jedoch nicht über das Konzept eines Fensterhandles, sodass es keine Möglichkeit gibt, es direkt aus der Window-Klasse abzurufen.
Da es jedoch Zeiten gibt, in denen ein Fensterhandle erforderlich ist, wie in diesem Fall, kann das Fensterhandle über die Klasse "System.Windows.Interop.WindowInteropHelper" als Interop für Win32-Code abgerufen werden. (dies ist die Window-Klasse)
// ウィンドウハンドルを取得する
IntPtr handle = new WindowInteropHelper(this).Handle;
Verwenden Sie dieses Handle, wenn Sie ein Direct3D-Gerät erstellen. Wenn Sie jedoch versuchen, das Fensterhandle in der OnInitialized-Methode abzurufen, wird 0 zurückgegeben, wahrscheinlich weil das Fenster noch nicht erstellt wurde. In diesem Beispiel wird das Gerät in der OnSourceInitialized-Methode erstellt.
In angegebenen Bereich rendern
Sie können den Zielbereich als zweites Argument von GraphicsDevice.Present angeben. Im Beispiel versuche ich, es an der Position (50, 50) als Versatz zu zeichnen. Die Größe entspricht der Größe des Backbuffers (300, 300). Das erste Argument ist der Bereich, aus dem gezeichnet werden soll, und wenn null angegeben ist, wird der ursprüngliche Puffer verwendet.
// 描画先を指定する
Xna.Rectangle rect = new Xna.Rectangle(
50, 50,
(int)this.viewSize.Width, (int)this.viewSize.Height);
this.device.Present(null, rect, this.windowHandle);
Zerstörung eines Geräts
Sie zerstören Ihr Gerät, wenn Sie das Fenster schließen. Ursprünglich wollte ich es mit der Dispose-Methode behandeln, aber da die WPF-Window-Klasse IDisposable nicht standardmäßig erbt, habe ich sie stattdessen hier geschrieben.
<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);
}
Ausführung
Wenn Sie das Beispielprogramm ausführen, können Sie es mit einem Bildschirmbild wie dem am Anfang des Artikels ausführen.
Auf den ersten Blick wird es gut gerendert, aber wenn ich die Größe des Fensters durch Ziehen mit der Maus ändere, flackert die Ansicht oder verschwindet während der Größenänderung. Es scheint mit dem WPF-Rendering in Konflikt zu stehen, und ich habe viele Dinge ausprobiert, konnte es aber nicht lösen.
Wenn Sie XNA verwenden, scheint es sicherer zu sein, das WindowsFormsHost-Steuerelement zu verwenden.
Das Programm erfordert .NET Framework 3.0, die neueste DirectX-Runtime und Microsoft XNA Framework Redistributable 2.0. Darüber hinaus ist als Hardwarevoraussetzung "eine Grafikkarte erforderlich, die Pixel Shader 1.1 oder höher unterstützt".
Darüber hinaus wurde das Projekt in "Visual Studio 2008 Professional Edition" erstellt. Bereiten Sie eine Umgebung für Visual Studio 2008 vor.