Een XNA-weergave direct op een WPF-venster weergeven

Pagina bijgewerkt :
Aanmaakdatum van pagina :

samenvatting

Hierin wordt beschreven hoe u rechtstreeks in een WPF-venster kunt renderen met XNA.

WPF ウインドウ上に直接 XNA のビューを表示する

Werkomgeving

Voorwaarden

Ondersteunde XNA-versies
  • 2.0
  • 3.0
Ondersteunde platforms
  • Windows (XP SP2 of hoger, Vista)
Windows vereist Vertex Shader-versie 1.1
Windows Vereiste Pixel Shader-versie 1.1

Werkomgeving

perron

stof

Bij het gebruik van XNA in WPF-toepassingen heb ik het besturingselement WindowsFormsHost gebruikt om de weergave weer te geven, maar nu wil ik alleen het WPF-venster gebruiken om de polygoon weer te geven. "XNA gebruiken in WPF-toepassingen" is een beetje een weergave, dus ik zal de verschillen uitleggen.

Aliassen in naamruimten

// 名前空間エイリアス
using Xna = Microsoft.Xna.Framework;
using XnaGraphics = Microsoft.Xna.Framework.Graphics;

Omdat de kleur- en matrixstructuren worden gedekt door de XNA Framework- en WPF-naamruimten, moet u de naam van de structuur uit de naamruimte opgeven om deze te kunnen gebruiken. Het lijkt echter elke keer lang te zijn, dus ik maak een naamruimte-alias aan. Bijvoorbeeld, "Microsoft.Xna.Framework.Rectangle" kan nu worden opgegeven als "Xna.Rectangle".

timer

Sinds .NET Framework 3.0 is er een timerklasse met de naam "System.Windows.Threading.DispatcherTimer" beschikbaar, en deze timerklasse wordt gebruikt om elk frame weer te geven. WPF gebruikt een DispatcherTimer om verwerking op dezelfde thread als de gebruikersinterface mogelijk te maken.

/// <summary>
/// タイマー
/// </summary>
private DispatcherTimer timer = null;

veld, waarbij een DispatcherTimer wordt aangegeven.

/// <summary>
/// タイマーイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    this.Draw();
}

Definieert een methode die de DispatcherTimer met regelmatige tussenpozen aanroept.

// タイマー
this.timer = new DispatcherTimer();
this.timer.Tick += new EventHandler(dispatcherTimer_Tick);
this.timer.Interval = new TimeSpan(0, 0, 0, 0, 16);
this.timer.Start();

Dit is het proces van het instellen van de timer. Na het maken van een exemplaar van DispatcherTimer en het instellen van de methode om aan te roepen en het tijdsinterval, start de DispatcherTimer.Start-methode de timer.

Het verkrijgen van een raamkruk

Om een Direct3D-apparaat te maken, hebt u een raamklink nodig. WPF heeft echter niet het concept van een raamklink, dus er is geen manier om het rechtstreeks uit de Windows-klasse te halen.

Omdat er echter momenten zijn waarop een raamgreep vereist is, zoals in dit geval, kan de raamgreep worden verkregen via de klasse "System.Windows.Interop.WindowInteropHelper" als interopop voor Win32-code. (dit is de Window klasse)

// ウィンドウハンドルを取得する
IntPtr handle = new WindowInteropHelper(this).Handle;

Gebruik deze handgreep bij het maken van een Direct3D-apparaat. Als u echter probeert de venstergreep in de methode OnInitialized te krijgen, retourneert deze 0, waarschijnlijk omdat het venster nog niet is gemaakt. In dit voorbeeld wordt het apparaat gemaakt in de methode OnSourceInitialized.

Renderen naar gespecificeerd gebied

U kunt het doelgebied opgeven als het tweede argument van GraphicsDevice.Present. In de steekproef probeer ik het op de positie (50, 50) als een offset te tekenen. De grootte is gelijk aan de grootte van de backbuffer (300, 300). Het eerste argument is het gebied waaruit moet worden getrokken, en als null is opgegeven, wordt de oorspronkelijke buffer gebruikt.

// 描画先を指定する
Xna.Rectangle rect = new Xna.Rectangle(
    50, 50,
    (int)this.viewSize.Width, (int)this.viewSize.Height);

this.device.Present(null, rect, this.windowHandle);

Een apparaat vernietigen

Je vernietigt je apparaat als je het venster sluit. Oorspronkelijk wilde ik het afhandelen met de Dispose methode, maar aangezien de WPF Window class niet standaard IDisposable erft, heb ik het hier geschreven.

/// <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);
}

uitvoering

Als u het voorbeeldprogramma uitvoert, kunt u het uitvoeren met een schermafbeelding zoals aan het begin van het artikel.

Op het eerste gezicht wordt het goed weergegeven, maar wanneer ik het formaat van het venster wijzig door het met de muis te slepen, flikkert of verdwijnt het beeld tijdens het wijzigen van het formaat. Het lijkt in strijd te zijn met WPF-rendering, en ik heb veel dingen geprobeerd, maar kon het niet oplossen.

Als u XNA gebruikt, lijkt het veiliger om het besturingselement WindowsFormsHost te gebruiken.

Het programma vereist .NET Framework 3.0, de nieuwste DirectX-runtime en het Microsoft XNA Framework Redistributable 2.0. Bovendien is als hardwarevereiste "een grafische kaart die Pixel Shader 1.1 of hoger ondersteunt" vereist.

Bovendien is het project gemaakt in "Visual Studio 2008 Professional Edition". Bereid een omgeving voor Visual Studio 2008 voor.