Visa en XNA-vy direkt i ett WPF-fönster

Sidan uppdaterad :
Datum för skapande av sida :

sammanfattning

Beskriver hur du renderar direkt i ett WPF-fönster med XNA.

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

Operativ miljö

Förutsättningar

XNA-versioner som stöds
  • 2.0
  • 3.0
Plattformar som stöds
  • Windows (XP SP2 eller senare, Vista)
Windows Nödvändig version av Vertex Shader 1.1
Windows Pixel Shader-version som krävs 1.1

Operativ miljö

plattform

substans

När jag använde XNA i WPF-program använde jag kontrollen WindowsFormsHost för att visa vyn, men nu vill jag bara använda WPF-fönstret för att visa polygonen. "Använda XNA i WPF-applikationer" är lite av en representation, så jag ska förklara skillnaderna.

Alias för namnrymd

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

Eftersom färg- och matrisstrukturerna omfattas av namnrymderna XNA Framework och WPF måste du ange namnet på strukturen från namnområdet för att kunna använda det. Det verkar dock vara långt varje gång, så jag skapar ett namnrymdsalias. Till exempel kan "Microsoft.Xna.Framework.Rectangle" nu anges som "Xna.Rectangle".

timer

Sedan .NET Framework 3.0 har en timerklass med namnet "System.Windows.Threading.DispatcherTimer" varit tillgänglig, och den här timerklassen används för att återge varje bildruta. WPF använder en DispatcherTimer för att tillåta bearbetning på samma tråd som användargränssnittet.

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

deklarera en DispatcherTimer.

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

Definierar en metod som DispatcherTimer anropar med jämna mellanrum.

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

Detta är processen att ställa in timern. När du har skapat en instans av DispatcherTimer och ställt in anropsmetoden och tidsintervallet, startar metoden DispatcherTimer.Start timern.

Skaffa ett fönsterhandtag

För att skapa en Direct3D-enhet behöver du ett fönsterhandtag. WPF har dock inte begreppet fönsterhandtag, så det finns inget sätt att hämta det direkt från Window klassen.

Men eftersom det finns tillfällen då ett fönsterhandtag krävs, som i det här fallet, kan fönsterhandtaget hämtas via klassen "System.Windows.Interop.WindowInteropHelper" som en interop för Win32-kod. (det här är klassen Window)

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

Använd det här handtaget när du skapar en Direct3D-enhet. Men om du försöker hämta fönsterhandtaget i OnInitialized metoden returneras 0, förmodligen på grund av att fönstret inte har skapats ännu. I det här exemplet skapas enheten i OnSourceInitialized metoden .

Rendera till angivet område

Du kan ange målområdet som det andra argumentet för GraphicsDevice.Present. I provet försöker jag rita den vid positionen (50, 50) som en förskjutning. Storleken är densamma som storleken på backbuffern (300, 300). Det första argumentet är det område som ska hämtas, och om null anges används den ursprungliga bufferten.

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

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

Förstöra en enhet

Du förstör din enhet när du stänger fönstret. Ursprungligen ville jag hantera det med Dispose-metoden, men eftersom WPF Window-klassen inte ärver IDisposable som standard skrev jag det här istället.

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

avrättning

Om du kör exempelprogrammet kan du köra det med en skärmbild som den i början av artikeln.

Vid första anblicken renderas det bra, men när jag ändrar storlek på fönstret genom att dra det med musen flimrar vyn eller försvinner under storleksändringen. Det verkar vara i konflikt med WPF-rendering, och jag försökte många saker men kunde inte lösa det.

Om du använder XNA verkar det säkrare att använda WindowsFormsHost-kontrollen.

Programmet kräver .NET Framework 3.0, den senaste DirectX-körningen och Microsoft XNA Framework Redistributable 2.0. Dessutom, som ett hårdvarukrav, krävs "ett grafikkort som stöder Pixel Shader 1.1 eller högre".

Dessutom skapades projektet i "Visual Studio 2008 Professional Edition". Förbered en miljö för Visual Studio 2008.