Εμφάνιση προβολής XNA απευθείας σε παράθυρο WPF

Σελίδα ενημέρωση :
Ημερομηνία δημιουργίας σελίδας :

περίληψη

Περιγράφει τον τρόπο απόδοσης απευθείας σε ένα παράθυρο WPF με XNA.

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

Περιβάλλον λειτουργίας

Προϋποθέσεις

Υποστηριζόμενες εκδόσεις XNA
  • 2.0
  • 3.0
Υποστηριζόμενες πλατφόρμες
  • Windows (XP SP2 ή νεότερη έκδοση, Vista)
Windows Απαιτούμενη έκδοση σκίασης Vertex 1.1
Απαιτούμενη έκδοση Pixel Shader των Windows 1.1

Περιβάλλον λειτουργίας

πλατφόρμα

ουσία

Στην ενότητα Χρήση XNA σε εφαρμογές WPF, χρησιμοποίησα το στοιχείο ελέγχου WindowsFormsHost για να εμφανίσω την προβολή, αλλά τώρα θέλω να χρησιμοποιήσω μόνο το παράθυρο WPF για να εμφανίσω το πολύγωνο. Η "χρήση XNA σε εφαρμογές WPF" είναι λίγο αναπαράσταση, οπότε θα εξηγήσω τις διαφορές.

Ψευδώνυμα χώρου ονομάτων

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

Επειδή οι δομές Color και Matrix καλύπτονται από τους χώρους ονομάτων XNA Framework και WPF, πρέπει να καθορίσετε το όνομα της δομής από το χώρο ονομάτων για να το χρησιμοποιήσετε. Ωστόσο, φαίνεται να είναι μεγάλο κάθε φορά, γι 'αυτό δημιουργώ ένα ψευδώνυμο χώρου ονομάτων. Για παράδειγμα, το "Microsoft.Xna.Framework.Rectangle" μπορεί τώρα να καθοριστεί ως "Xna.Rectangle".

χρονόμετρο

Από το .NET Framework 3.0, μια κλάση χρονοδιακόπτη που ονομάζεται "System.Windows.Threading.DispatcherTimer" είναι διαθέσιμη και αυτή η κλάση χρονοδιακόπτη χρησιμοποιείται για την απόδοση κάθε πλαισίου. Το WPF χρησιμοποιεί ένα DispatcherTimer για να επιτρέψει την επεξεργασία στο ίδιο νήμα με το περιβάλλον εργασίας χρήστη.

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

, δηλώνοντας ένα DispatcherTimer.

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

Ορίζει μια μέθοδο που καλεί το DispatcherTimer σε τακτά χρονικά διαστήματα.

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

Αυτή είναι η διαδικασία ρύθμισης του χρονοδιακόπτη. Αφού δημιουργήσετε μια παρουσία του DispatcherTimer και ορίσετε τη μέθοδο κλήσης και το χρονικό διάστημα, η μέθοδος DispatcherTimer.Start ξεκινά το χρονόμετρο.

Απόκτηση λαβής παραθύρου

Για να δημιουργήσετε μια συσκευή Direct3D, χρειάζεστε μια λαβή παραθύρου. Ωστόσο, το WPF δεν έχει την έννοια της λαβής παραθύρου, επομένως δεν υπάρχει τρόπος να το αποκτήσετε απευθείας από την κλάση Window.

Ωστόσο, επειδή υπάρχουν φορές που απαιτείται λαβή παραθύρου, όπως σε αυτήν την περίπτωση, η λαβή παραθύρου μπορεί να ληφθεί μέσω της κλάσης "System.Windows.Interop.WindowInteropHelper" ως διαλειτουργικότητα για κώδικα Win32. (αυτή είναι η κλάση Window)

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

Χρησιμοποιήστε αυτήν τη λαβή κατά τη δημιουργία μιας συσκευής Direct3D. Ωστόσο, εάν προσπαθήσετε να λάβετε τη λαβή παραθύρου στη μέθοδο OnInitialized, θα επιστρέψει 0, πιθανώς επειδή το παράθυρο δεν έχει δημιουργηθεί ακόμα. Σε αυτό το δείγμα, η συσκευή δημιουργείται με τη μέθοδο OnSourceInitialized.

Απόδοση σε καθορισμένη περιοχή

Μπορείτε να καθορίσετε την περιοχή προορισμού ως το δεύτερο όρισμα του GraphicsDevice.Present. Στο δείγμα, προσπαθώ να το σχεδιάσω στη θέση (50, 50) ως μετατόπιση. Το μέγεθος είναι το ίδιο με το μέγεθος του backbuffer (300, 300). Το πρώτο όρισμα είναι η περιοχή από την οποία θα αντληθεί και, εάν έχει καθοριστεί null, χρησιμοποιείται το αρχικό buffer.

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

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

Καταστροφή συσκευής

Καταστρέφετε τη συσκευή σας όταν κλείνετε το παράθυρο. Αρχικά, ήθελα να το χειριστώ με τη μέθοδο Dispose, αλλά επειδή η κλάση WPF Window δεν κληρονομεί το IDisposable από προεπιλογή, το έγραψα εδώ.

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

εκτέλεση

Εάν εκτελέσετε το δείγμα προγράμματος, μπορείτε να το εκτελέσετε με μια εικόνα οθόνης όπως αυτή στην αρχή του άρθρου.

Με την πρώτη ματιά, αποδίδει καλά, αλλά όταν αλλάζω το μέγεθος του παραθύρου σύροντάς το με το ποντίκι, η προβολή τρεμοπαίζει ή εξαφανίζεται κατά την αλλαγή μεγέθους. Φαίνεται να έρχεται σε σύγκρουση με την απόδοση WPF και δοκίμασα πολλά πράγματα, αλλά δεν μπόρεσα να το λύσω.

Εάν χρησιμοποιείτε XNA, φαίνεται ασφαλέστερο να χρησιμοποιήσετε το στοιχείο ελέγχου WindowsFormsHost.

Το πρόγραμμα απαιτεί το .NET Framework 3.0, τον πιο πρόσφατο χρόνο εκτέλεσης του DirectX και το Microsoft XNA Framework Redistributable 2.0. Επιπλέον, ως απαίτηση υλικού, απαιτείται "μια κάρτα γραφικών που υποστηρίζει Pixel Shader 1.1 ή νεότερη έκδοση".

Επιπλέον, το έργο δημιουργήθηκε στο "Visual Studio 2008 Professional Edition". Προετοιμάστε ένα περιβάλλον για το Visual Studio 2008.