Utilizarea XNA în aplicațiile WPF
rezumat
Descrie modul de utilizare a XNA Framework în aplicațiile WPF.
Mediul de operare
Cerințe preliminare
Versiuni XNA acceptate |
|
Platforme acceptate |
|
Versiunea Vertex Shader necesară pentru Windows | 1.1 |
Versiunea Pixel Shader necesară pentru Windows | 1.1 |
Mediul de operare
peron |
substanță
Pentru a reda pe un anumit control utilizând DirectX, trebuie să obțineți mânerul de fereastră pentru acel control. Cu toate acestea, spre deosebire de controalele Windows Form, controalele WPF nu au mânere de fereastră (în WPF pur și simplu "desenează" controlul).
Cu toate acestea, WPF oferă un control numit "WindowsFormsHost" care vă permite să utilizați controale Windows Forms.
În acest articol, vom crea un eșantion de desenare a unui poligon pe măsură ce este rotit așa cum se arată mai sus, dar voi omite detaliile XNA în sine, deoarece ar fi prea lung pentru a-l explica. Voi vorbi doar despre relația dintre WPF și XNA.
Mai întâi, deschideți o fereastră WPF (în acest caz, Window1.xaml) și plasați un control WindowsFormHost din bara de instrumente. Glisorul din dreapta este un bonus.
Chiar trebuie să lucrez puțin mai mult la XAML, dar o voi lăsa pentru mai târziu pentru că trebuie să creez mai întâi controalele pentru a utiliza XNA.
Adăugați un "Control personalizat" "Windows Forms" la proiectul dvs. Lăsați numele GraphicsDeviceControl.
Nu uitați să adăugați în prealabil referința "Microsoft.Xna.Framework". Există, de asemenea, "Microsoft.Xna.Framework.Game", dar acesta este folosit într-un proiect doar pentru jocuri, deci nu este nevoie să-l includeți.
Pentru a păstra codul eșantion scurt, toate programele legate de XNA sunt rezumate în GraphicsDeviceControl.cs. Nu este un stil de scriere foarte versatil, așa că vă rugăm să-l aplicați și să-l rescrieți.
Codul complet pentru GraphicsDeviceControl este afișat mai jos (cu excepția părții de proiectant). Dacă ați folosit vreodată XNA, veți ști că nu face nimic ieșit din comun. Folosesc o componentă Timer pentru a face poligonul să pară că se rotește tot timpul.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace XNAOnWPF
{
<summary>
グラフィックデバイスコントロール
</summary>
public partial class GraphicsDeviceControl : Control
{
<summary>
グラフィックデバイス
</summary>
private GraphicsDevice device = null;
<summary>
エフェクト
</summary>
private BasicEffect effect = null;
<summary>
頂点データ
</summary>
private VertexPositionColor[] vertices = new VertexPositionColor[3];
<summary>
頂点データ
</summary>
public VertexPositionColor[] Vertices
{
get { return this.vertices; }
}
<summary>
コンストラクタ
</summary>
public GraphicsDeviceControl()
{
InitializeComponent();
}
<summary>
コントロールが作成されるとき
</summary>
protected override void OnCreateControl()
{
if (this.DesignMode == false)
{
try
{
// デバイス作成
PresentationParameters pp = new PresentationParameters();
pp.SwapEffect = SwapEffect.Discard;
pp.BackBufferWidth = 300;
pp.BackBufferHeight = 300;
pp.EnableAutoDepthStencil = true;
pp.AutoDepthStencilFormat = DepthFormat.Depth16;
this.device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter,
DeviceType.Hardware, this.Handle, pp);
// 頂点データの設定
this.vertices[0] = new VertexPositionColor(
new Vector3(0.0f, -2.0f + (float)Math.Sqrt(3) * 3.0f, 0.0f),
new Microsoft.Xna.Framework.Graphics.Color(255, 0, 0));
this.vertices[1] = new VertexPositionColor(
new Vector3(3.0f, -2.0f, 0.0f),
new Microsoft.Xna.Framework.Graphics.Color(0, 255, 0));
this.vertices[2] = new VertexPositionColor(
new Vector3(-3.0f, -2.0f, 0.0f),
new Microsoft.Xna.Framework.Graphics.Color(0, 0, 255));
// 頂点定義
this.device.VertexDeclaration =
new VertexDeclaration(this.device, VertexPositionColor.VertexElements);
// エフェクト
this.effect = new BasicEffect(this.device, null);
this.effect.VertexColorEnabled = true;
// ビュー変換行列を設定
this.effect.View = Matrix.CreateLookAt(
new Vector3(0.0f, 0.0f, -10.0f),
new Vector3(0.0f, 0.0f, 0.0f),
Vector3.Up);
// 射影変換を設定
this.effect.Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45.0f), 1.0f, 1.0f, 100.0f);
// レンダリングステート設定
this.device.RenderState.CullMode = CullMode.None;
this.device.RenderState.AlphaBlendEnable = true;
this.device.RenderState.SourceBlend = Blend.SourceAlpha;
this.device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
}
base.OnCreateControl();
}
<summary>
使用中のリソースをすべてクリーンアップします。
</summary>
<param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
if (disposing)
{
if (this.device != null)
{
this.device.Dispose();
}
}
base.Dispose(disposing);
}
<summary>
描画イベント
</summary>
<param name="pe"></param>
protected override void OnPaint(PaintEventArgs pe)
{
this.Draw();
base.OnPaint(pe);
}
<summary>
描画
</summary>
private void Draw()
{
if (this.device == null)
{
return;
}
this.device.Clear(Microsoft.Xna.Framework.Graphics.Color.DarkBlue);
// ポリゴンを描画する
this.effect.Begin();
this.effect.Techniques[0].Passes[0].Begin();
this.effect.World = Matrix.CreateRotationY((float)Environment.TickCount / 1000.0f);
this.device.DrawUserPrimitives<VertexPositionColor>(
PrimitiveType.TriangleList, vertices, 0, 1);
this.effect.Techniques[0].Passes[0].End();
this.effect.End();
this.device.Present();
}
<summary>
タイマーイベント
</summary>
<param name="sender"></param>
<param name="e"></param>
private void timer_Tick(object sender, EventArgs e)
{
this.Draw();
}
}
}
Acum că ați creat controlul, să ne uităm la XAML. Deoarece vom plasa controlul pe care l-am creat, vom adăuga un spațiu de nume la eticheta rădăcină. Aici, este definit ca "xw".
<Window x:Class="ManagedDirectXOnWPF.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPFウインドウ上でManaged DirectXを使用してポリゴン描画"
Height="338" Width="422"
xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:xw="clr-namespace:ManagedDirectXOnWPF">
<!-- 省略 -->
</Window>
Apoi, extindeți eticheta pentru controlul WindowsFormsHost pe care tocmai l-ați plasat și adăugați un GraphicsDeviceControl, așa cum se arată mai jos.
<my:WindowsFormsHost Name="windowsFormsHostManagedDirectX" Width="300" Height="300"
HorizontalAlignment="Left" VerticalAlignment="Top">
<xw:GraphicsDeviceControl x:Name="GraphicsDeviceControl" />
</my:WindowsFormsHost>
Nu trebuie să aveți un "x:Name", dar eșantionul îl folosește pentru a accesa datele nodului cu un glisor.
Dacă faceți acest lucru, puteți rula o scenă pe WPF în care poligoanele sunt desenate cu un poligon rotativ, așa cum se arată în eșantion. Accesul prin glisor este un bonus, așa că vă rugăm să descărcați datele eșantion și să le verificați.
Programul necesită .NET Framework 3.0, cel mai recent runtime DirectX și Microsoft XNA Framework Redistributable 2.0. În plus, ca cerință hardware, este necesară "o placă grafică care acceptă Pixel Shader 1.1 sau o versiune ulterioară".
În plus, proiectul a fost creat în "Visual Studio 2008 Professional Edition". Pregătiți un mediu pentru Visual Studio 2008.