הצגת תצוגת XNA ישירות בחלון WPF

עודכן דף :
תאריך יצירת דף :

תקציר

מתאר כיצד לעבד ישירות בחלון WPF באמצעות XNA.

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

סביבת הפעלה

דרישות מוקדמות

גרסאות XNA נתמכות
  • 2.0
  • 3.0
פלטפורמות נתמכות
  • Windows (XP SP2 ואילך, Vista)
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 ו- 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 אין את הרעיון של ידית אחיזה לחלון, כך שאין דרך להשיג אותה ישירות ממחלקת החלונות.

עם זאת, מאז יש פעמים כאשר אחיזה חלון נדרש, כמו במקרה זה, ידית החלון ניתן להשיג באמצעות "System.Windows.Interop.WindowInteropHelper" בכיתה כמו interop עבור קוד Win32. (זוהי מחלקת החלון)

// ウィンドウハンドルを取得する
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);

השמדת מכשיר

אתה הורס את המכשיר שלך כשאתה סוגר את החלון. במקור, רציתי לטפל בזה עם שיטת Dispos, אבל מכיוון שמחלקת 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.