XNA rodinio rodymas tiesiai WPF lange

Puslapis atnaujintas :
Puslapio sukūrimo data :

suvestinė

Aprašoma, kaip generuoti tiesiogiai WPF lange naudojant XNA.

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

Darbo aplinka

Būtinosios sąlygos

Palaikomos XNA versijos
  • 2.0
  • 3.0
Palaikomos platformos
  • "Windows" (XP SP2 arba naujesnė versija, "Vista")
"Windows" reikalinga "Vertex Shader" versija 1.1
"Windows" reikalinga "Pixel Shader" versija 1.1

Darbo aplinka

platforma

medžiaga

Naudodamas XNA WPF programose, naudojau "WindowsFormsHost" valdiklį, kad būtų rodomas vaizdas, bet dabar noriu naudoti tik WPF langą, kad būtų rodomas daugiakampis. "XNA naudojimas WPF programose" yra šiek tiek reprezentacinis, todėl paaiškinsiu skirtumus.

Vardų srities pseudonimai

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

Kadangi spalvų ir matricos struktūras apima XNA Framework ir WPF vardų sritys, norėdami ją naudoti, vardų srityje turite nurodyti struktūros pavadinimą. Tačiau atrodo, kad kiekvieną kartą jis yra ilgas, todėl kuriu vardų srities slapyvardį. Pavyzdžiui, "Microsoft.Xna.Framework.Rectangle" dabar galima nurodyti kaip "Xna.Rectangle".

Laikmatis

Nuo .NET Framework 3.0 buvo prieinama laikmačio klasė, vadinama "System.Windows.Threading.DispatcherTimer", ir ši laikmačio klasė naudojama kiekvienam kadrui generuoti. WPF naudoja dispečerio laikmatį, kad leistų apdoroti tą pačią giją kaip ir vartotojo sąsaja.

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

laukas, deklaruojantis Dispečerio laikmatį.

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

Apibrėžia metodą, kurį dispečerisTimeris reguliariai iškviečia.

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

Tai yra laikmačio nustatymo procesas. Sukūrus "DispatcherTimer" egzempliorių ir nustačius skambinimo būdą bei laiko intervalą, "DispatcherTimer.Start" metodas paleidžia laikmatį.

Lango rankenos gavimas

Norėdami sukurti "Direct3D" įrenginį, jums reikia lango rankenos. Tačiau WPF neturi lango rankenos koncepcijos, todėl nėra galimybės jos gauti tiesiai iš "Window" klasės.

Tačiau, kadangi yra atvejų, kai reikalinga lango rankena, kaip ir šiuo atveju, lango rankeną galima gauti per "System.Windows.Interop.WindowInteropHelper" klasę kaip "Win32" kodo interopą. (tai yra "Window" klasė)

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

Naudokite šią rankenėlę kurdami "Direct3D" įrenginį. Tačiau jei bandysite gauti lango rankeną OnInitialized metodu, jis grąžins 0, tikriausiai todėl, kad langas dar nebuvo sukurtas. Šiame pavyzdyje įrenginys sukurtas OnSourceInitialized metodu.

Atvaizduoti į nurodytą sritį

Paskirties sritį galite nurodyti kaip antrąjį GraphicsDevice.Present argumentą. Imtyje bandau jį nupiešti pozicijoje (50, 50) kaip poslinkį. Dydis yra toks pat kaip ir buferio dydis (300, 300). Pirmasis argumentas yra sritis, iš kurios galima piešti, o jei nurodyta null, naudojamas pradinis buferis.

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

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

Įrenginio sunaikinimas

Sunaikinate įrenginį, kai uždarote langą. Iš pradžių norėjau jį tvarkyti su Dispose metodu, bet kadangi WPF Window klasė pagal numatytuosius nustatymus nepaveldi IDisposable, parašiau jį čia.

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

Vykdymo

Jei paleisite pavyzdinę programą, galite ją paleisti naudodami ekrano vaizdą, panašų į tą, kuris yra straipsnio pradžioje.

Iš pirmo žvilgsnio jis gerai atvaizduojamas, bet kai keičiu lango dydį vilkdamas jį pele, keičiant dydį vaizdas mirksi arba dingsta. Atrodo, kad tai prieštarauja WPF atvaizdavimui, ir aš išbandžiau daug dalykų, bet negalėjau to išspręsti.

Jei naudojate XNA, atrodo saugiau naudoti "WindowsFormsHost" valdiklį.

Programai reikalinga ".NET Framework 3.0", naujausia "DirectX" vykdyklė ir "Microsoft XNA Framework Redistributable 2.0". Be to, kaip aparatinės įrangos reikalavimas reikalinga "vaizdo plokštė, palaikanti Pixel Shader 1.1 ar naujesnę versiją".

Be to, projektas buvo sukurtas "Visual Studio 2008 Professional Edition". Paruoškite aplinką "Visual Studio 2008".