Afișarea unei vizualizări XNA direct pe o fereastră WPF

Pagina actualizată :
Data creării paginii :

rezumat

Descrie cum să redați direct într-o fereastră WPF cu XNA.

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

Mediul de operare

Cerințe preliminare

Versiuni XNA acceptate
  • 2.0
  • 3.0
Platforme acceptate
  • Windows (XP SP2 sau o versiune ulterioară, Vista)
Versiunea Vertex Shader necesară pentru Windows 1.1
Versiunea Pixel Shader necesară pentru Windows 1.1

Mediul de operare

peron

substanță

În Utilizarea XNA în aplicațiile WPF, am folosit controlul WindowsFormsHost pentru a afișa vizualizarea, dar acum vreau să folosesc doar fereastra WPF pentru a afișa poligonul. "Utilizarea XNA în aplicațiile WPF" este un pic o reprezentare, așa că voi explica diferențele.

Aliasuri de spațiu de nume

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

Deoarece structurile Color și Matrix sunt acoperite de spațiile de nume XNA Framework și WPF, trebuie să specificați numele structurii din spațiul de nume pentru a o utiliza. Cu toate acestea, pare să fie lung de fiecare dată, așa că creez un alias de spațiu de nume. De exemplu, "Microsoft.Xna.Framework.Rectangle" poate fi acum specificat ca "Xna.Rectangle".

cronometru

De la .NET Framework 3.0, a fost disponibilă o clasă de temporizator numită "System.Windows.Threading.DispatcherTimer", iar această clasă de temporizator este utilizată pentru a reda fiecare cadru. WPF utilizează un DispatcherTimer pentru a permite procesarea pe același fir ca și interfața de utilizare.

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

, declarând un DispatcherTimer.

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

Definește o metodă pe care DispatcherTimer o apelează la intervale regulate.

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

Acesta este procesul de setare a temporizatorului. După crearea unei instanțe de DispatcherTimer și setarea metodei de apelare și a intervalului de timp, metoda DispatcherTimer.Start pornește temporizatorul.

Obținerea unui mâner de fereastră

Pentru a crea un dispozitiv Direct3D, aveți nevoie de un mâner de fereastră. Cu toate acestea, WPF nu are conceptul de mâner de fereastră, deci nu există nicio modalitate de a-l obține direct din clasa Window.

Cu toate acestea, deoarece există momente în care este necesar un mâner de fereastră, ca în acest caz, mânerul de fereastră poate fi obținut prin clasa "System.Windows.Interop.WindowInteropHelper" ca interoperabilitate pentru codul Win32. (aceasta este clasa Window)

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

Utilizați acest ghidaj atunci când creați un dispozitiv Direct3D. Cu toate acestea, dacă încercați să obțineți mânerul ferestrei în metoda OnInitialized, acesta va returna 0, probabil pentru că fereastra nu a fost încă creată. În acest eșantion, dispozitivul este creat în metoda OnSourceInitialized.

Randare în zona specificată

Puteți specifica zona de destinație ca al doilea argument al GraphicsDevice.Present. În eșantion, încerc să-l desenez în poziția (50, 50) ca un offset. Dimensiunea este aceeași cu dimensiunea backbuffer-ului (300, 300). Primul argument este zona din care se desenează, iar dacă se specifică null, se folosește bufferul original.

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

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

Distrugerea unui dispozitiv

Distrugeți dispozitivul când închideți fereastra. Inițial, am vrut să o gestionez cu metoda Dispose, dar din moment ce clasa WPF Window nu moștenește IDisposable în mod implicit, am scris-o aici.

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

execuție

Dacă rulați programul eșantion, îl puteți rula cu o imagine de ecran precum cea de la începutul articolului.

La prima vedere, se redă bine, dar când redimensionez fereastra trăgând-o cu mouse-ul, vizualizarea pâlpâie sau dispare în timpul redimensionării. Se pare că este în conflict cu randarea WPF și am încercat o mulțime de lucruri, dar nu am reușit să o rezolv.

Dacă utilizați XNA, pare mai sigur să utilizați controlul WindowsFormsHost.

Programul necesită .NET Framework 3.0, cel mai recent runtime DirectX și Microsoft XNA Framework Redistributable 2.0. În plus, ca cerință hardware, este necesară "o placă grafică care acceptă Pixel Shader 1.1 sau o versiune ulterioară".

În plus, proiectul a fost creat în "Visual Studio 2008 Professional Edition". Pregătiți un mediu pentru Visual Studio 2008.