Vis en XNA-visning direkte i et WPF-vindue

Side opdateret :
Dato for oprettelse af side :

resumé

Beskriver, hvordan du gengiver direkte i et WPF-vindue med XNA.

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

Driftsmiljø

Forudsætninger

Understøttede XNA-versioner
  • 2.0
  • 3.0
Understøttede platforme
  • Windows (XP SP2 eller nyere, Vista)
Windows påkrævet Vertex Shader-version 1.1
Windows påkrævet Pixel Shader-version 1.1

Driftsmiljø

perron

stof

I Brug af XNA i WPF-programmer brugte jeg WindowsFormsHost-kontrolelementet til at vise visningen, men nu vil jeg kun bruge WPF-vinduet til at vise polygonen. "Brug af XNA i WPF-applikationer" er lidt af en repræsentation, så jeg vil forklare forskellene.

Aliasser for navnerum

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

Da strukturerne Color og Matrix er dækket af XNA Framework- og WPF-navneområderne, skal du angive navnet på strukturen fra navneområdet for at kunne bruge det. Det ser dog ud til at være langt hver gang, så jeg opretter et navnerumsalias. For eksempel kan "Microsoft.Xna.Framework.Rectangle" nu angives som "Xna.Rectangle".

Timer

Siden .NET Framework 3.0 har der været en timerklasse kaldet "System.Windows.Threading.DispatcherTimer" tilgængelig, og denne timerklasse bruges til at gengive hver ramme. WPF bruger en DispatcherTimer til at tillade behandling på den samme tråd som brugergrænsefladen.

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

og erklærer en DispatcherTimer.

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

Definerer en metode, som DispatcherTimer kalder med jævne mellemrum.

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

Dette er processen med at indstille timeren. Når du har oprettet en forekomst af DispatcherTimer og indstillet metoden til at kalde og tidsintervallet, starter metoden DispatcherTimer.Start timeren.

Anskaffelse af et vindueshåndtag

Hvis du vil oprette en Direct3D-enhed, skal du bruge et vindueshåndtag. WPF har dog ikke konceptet med et vindueshåndtag, så der er ingen måde at få det direkte fra Window-klassen.

Men da der er tidspunkter, hvor et vindueshåndtag er påkrævet, som i dette tilfælde, kan vindueshåndtaget fås via klassen "System.Windows.Interop.WindowInteropHelper" som et interop for Win32-kode. (dette er klassen Window)

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

Brug dette håndtag, når du opretter en Direct3D-enhed. Men hvis du forsøger at få vindueshåndtaget i OnInitialized-metoden, returnerer det 0, sandsynligvis fordi vinduet ikke er oprettet endnu. I dette eksempel oprettes enheden i metoden OnSourceInitialized.

Gengiv til angivet område

Du kan angive destinationsområdet som det andet argument i GraphicsDevice.Present. I prøven forsøger jeg at tegne det på positionen (50, 50) som en forskydning. Størrelsen er den samme som størrelsen på rygbufferen (300, 300). Det første argument er det område, hvorfra der skal tegnes, og hvis null er angivet, bruges den oprindelige buffer.

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

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

Ødelæggelse af en enhed

Du ødelægger din enhed, når du lukker vinduet. Oprindeligt ville jeg håndtere det med Dispose metoden, men da WPF Window-klassen ikke arver IDisposable som standard, skrev jeg det her i stedet.

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

henrettelse

Hvis du kører eksempelprogrammet, kan du køre det med et skærmbillede som det i begyndelsen af artiklen.

Ved første øjekast gengives det godt, men når jeg ændrer størrelsen på vinduet ved at trække det med musen, flimrer eller forsvinder visningen under størrelsesændring. Det ser ud til at være i konflikt med WPF-gengivelse, og jeg prøvede en masse ting, men kunne ikke løse det.

Hvis du bruger XNA, virker det mere sikkert at bruge kontrolelementet WindowsFormsHost.

Programmet kræver .NET Framework 3.0, den nyeste DirectX-runtime og Microsoft XNA Framework Redistributable 2.0. Derudover kræves der som et hardwarekrav "et grafikkort, der understøtter Pixel Shader 1.1 eller nyere".

Derudover blev projektet skabt i "Visual Studio 2008 Professional Edition". Forbered et miljø til Visual Studio 2008.