แสดงมุมมอง XNA โดยตรงบนหน้าต่าง WPF
สรุป
อธิบายวิธีการแสดงผลโดยตรงในหน้าต่าง WPF ด้วย XNA
สภาพแวดล้อมในการทํางาน
ข้อกําหนดเบื้องต้น
รุ่น XNA ที่รองรับ |
|
แพลตฟอร์มที่รองรับ |
|
Windows ต้องใช้เวอร์ชัน Vertex Shader | 1.1 |
เวอร์ชัน Pixel Shader ที่จําเป็นของ Windows | 1.1 |
สภาพแวดล้อมในการทํางาน
แท่น |
สาร
ใน การใช้ XNA ในโปรแกรมประยุกต์ WPF ผมใช้ตัวควบคุม WindowsFormsHost เพื่อแสดงมุมมอง แต่ตอนนี้ผมต้องการใช้เฉพาะหน้าต่าง WPF เพื่อแสดงรูปหลายเหลี่ยม "การใช้ XNA ในแอปพลิเคชัน WPF" เป็นตัวแทนเล็กน้อย ดังนั้นฉันจะอธิบายความแตกต่าง
นามแฝงเนมสเปซ
// 名前空間エイリアス
using Xna = Microsoft.Xna.Framework;
using XnaGraphics = Microsoft.Xna.Framework.Graphics;
เนื่องจากโครงสร้างสีและเมทริกซ์ถูกครอบคลุมโดย XNA Framework และ namespaces WPF คุณต้องระบุชื่อของโครงสร้างจากเนมสเปซเพื่อใช้งาน อย่างไรก็ตามดูเหมือนว่าจะยาวทุกครั้งดังนั้นฉันจึงสร้างนามแฝงเนมสเปซ ตัวอย่างเช่น "Microsoft.Xna.Framework.Rectangle" สามารถระบุเป็น "Xna.Rectangle" ได้
เครื่องจับเวลา
ตั้งแต่ .NET Framework 3.0 คลาสตัวจับเวลาที่เรียกว่า "System.Windows.Threading.DispatcherTimer" พร้อมใช้งาน และคลาสตัวจับเวลานี้ใช้เพื่อแสดงผลทุกเฟรม WPF ใช้ DispatcherTimer เพื่ออนุญาตให้ประมวลผลบนเธรดเดียวกันกับ UI
<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" เป็น interop สําหรับรหัส Win32 (นี่คือคลาส Window)
// ウィンドウハンドルを取得する
IntPtr handle = new WindowInteropHelper(this).Handle;
ใช้แฮนเดิลนี้เมื่อสร้างอุปกรณ์ Direct3D อย่างไรก็ตาม ถ้าคุณพยายามรับตัวจัดการหน้าต่างในเมธอด OnInitialized จะส่งกลับ 0 อาจเป็นเพราะหน้าต่างยังไม่ได้ถูกสร้างขึ้น ในตัวอย่างนี้ อุปกรณ์ถูกสร้างขึ้นในเมธอด OnSourceInitialized
เรนเดอร์ไปยังพื้นที่ที่ระบุ
คุณสามารถระบุพื้นที่ปลายทางเป็นอาร์กิวเมนต์ที่สองของ GraphicsDevice.Present ในตัวอย่างฉันพยายามวาดที่ตําแหน่ง (50, 50) เป็นออฟเซ็ต ขนาดเท่ากับขนาดของแบ็คบัฟเฟอร์ (300, 300) อาร์กิวเมนต์แรกคือพื้นที่ที่จะวาด และถ้าระบุ null จะใช้บัฟเฟอร์เดิม
// 描画先を指定する
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