Visualitzar una visualització XNA directament en una finestra de WPF

Pàgina actualitzada :
Data de creació de la pàgina :

resum

Descriu com renderitzar directament en una finestra del WPF amb XNA.

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

Entorn operatiu

Prerequisits

Versions XNA compatibles
  • 2.0
  • 3.0
Plataformes compatibles
  • Windows (XP SP2 o posterior, Vista)
Versió del shader de vèrtex necessària per al Windows 1.1
Versió de Pixel Shader necessària per a Windows 1.1

Entorn operatiu

plataforma

substància

En utilitzar XNA a les aplicacions WPF, he utilitzat el control WindowsFormsHost per mostrar la visualització, però ara vull utilitzar només la finestra WPF per mostrar el polígon. "Ús de XNA en aplicacions WPF" és una mica una representació, així que explicaré les diferències.

Àlies d'espai de noms

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

Com que les estructures Color i Matrix estan cobertes pels espais de noms XNA Framework i WPF, heu d'especificar el nom de l'estructura de l'espai de noms per utilitzar-la. No obstant això, sembla que és llarg cada vegada, així que estic creant un àlies d'espai de noms. Per exemple, ara es pot especificar "Microsoft.Xna.Framework.Rectangle" com a "Xna.Rectangle".

temporitzador

Des del .NET Framework 3.0, hi ha disponible una classe de temporitzador anomenada "System.Windows.Threading.DispatcherTimer", i aquesta classe de temporitzador s'utilitza per representar cada fotograma. El WPF utilitza un DispatcherTimer per permetre el processament en el mateix fil que la interfície d'usuari.

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

, declarant un DispatcherTimer.

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

Defineix un mètode que el DispatcherTimer crida a intervals regulars.

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

Aquest és el procés de configuració del temporitzador. Després de crear una instància de DispatcherTimer i definir el mètode per cridar i l'interval de temps, el mètode DispatcherTimer.Start inicia el temporitzador.

Obtenció d'un mànec de finestra

Per crear un dispositiu Direct3D, necessiteu un identificador de finestra. Tanmateix, WPF no té el concepte d'un identificador de finestra, de manera que no hi ha manera d'obtenir-lo directament de la classe Window.

Tanmateix, com que hi ha moments en què es requereix un identificador de finestra, com en aquest cas, el controlador de finestra es pot obtenir mitjançant la classe "System.Windows.Interop.WindowInteropHelper" com a interoperabilitat per al codi Win32. (aquesta és la classe Window)

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

Utilitzeu aquest identificador quan creeu un dispositiu Direct3D. Tanmateix, si intenteu obtenir l'identificador de la finestra al mètode OnInitialized, retornarà 0, probablement perquè la finestra encara no s'ha creat. En aquest exemple, el dispositiu es crea al mètode OnSourceInitialized.

Renderitza a l'àrea especificada

Podeu especificar l'àrea de destinació com a segon argument de GraphicsDevice.Present. A la mostra, intento dibuixar-lo a la posició (50, 50) com a desplaçament. La mida és la mateixa que la mida del backbuffer (300, 300). El primer argument és l'àrea des de la qual es dibuixa, i si s'especifica null, s'utilitza la memòria intermèdia original.

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

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

Destrucció d'un dispositiu

Estàs destruint el dispositiu quan tanques la finestra. Originalment, volia gestionar-ho amb el mètode Dispose, però com que la classe WPF Window no hereta IDisposable per defecte, l'he escrit aquí.

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

execució

Si executeu el programa d'exemple, podeu executar-lo amb una imatge de pantalla com la del principi de l'article.

A primera vista, es renderitza bé, però quan canvio la mida de la finestra arrossegant-la amb el ratolí, la vista parpelleja o desapareix durant el canvi de mida. Sembla que està en conflicte amb la representació de WPF, i he provat moltes coses però no ho he pogut resoldre.

Si utilitzeu XNA, sembla més segur utilitzar el control WindowsFormsHost.

El programa requereix el .NET Framework 3.0, l'últim temps d'execució de DirectX i el Microsoft XNA Framework Redistributable 2.0. A més, com a requisit de maquinari, es requereix "una targeta gràfica que admeti Pixel Shader 1.1 o superior".

A més, el projecte es va crear a "Visual Studio 2008 Professional Edition". Prepareu un entorn per al Visual Studio 2008.