Använda XNA i WPF-applikationer
sammanfattning
Beskriver hur du använder XNA Framework i WPF-applikationer.
Operativ miljö
Förutsättningar
XNA-versioner som stöds |
|
Plattformar som stöds |
|
Windows Nödvändig version av Vertex Shader | 1.1 |
Windows Pixel Shader-version som krävs | 1.1 |
Operativ miljö
plattform |
substans
Om du vill rendera på en viss kontroll med DirectX måste du hämta fönsterhandtaget för den kontrollen. Till skillnad från Windows formulärkontroller har WPF-kontroller dock inga fönsterhandtag (i WPF "ritar" de helt enkelt kontrollen).
WPF tillhandahåller dock en kontroll med namnet "WindowsFormsHost" som gör att du kan använda Windows Forms kontroller.
I den här artikeln kommer vi att skapa ett prov på att rita en polygon när den roteras som visas ovan, men jag kommer att utelämna detaljerna i själva XNA eftersom det skulle ta för lång tid att förklara det. Jag ska bara prata om förhållandet mellan WPF och XNA.
Öppna först ett WPF-fönster (i det här fallet Window1.xaml) och placera en WindowsFormHost-kontroll från verktygsfältet. Reglaget till höger är en bonus.
Jag behöver verkligen göra lite mer arbete på XAML, men jag lämnar det till senare eftersom jag måste skapa kontrollerna för att använda XNA först.
Lägg till en "Windows Forms" "Anpassad kontroll" i projektet. Lämna namnet GraphicsDeviceControl.
Glöm inte att lägga till referensen "Microsoft.Xna.Framework" i förväg. Det finns också "Microsoft.Xna.Framework.Game", men detta används i ett projekt som endast är spel, så det finns inget behov av att inkludera det.
För att hålla exempelkoden kort sammanfattas alla XNA-relaterade program i GraphicsDeviceControl.cs. Det är inte en särskilt mångsidig skrivstil, så använd den och skriv om den.
Den fullständiga koden för GraphicsDeviceControl visas nedan (förutom designerdelen). Om du någonsin har använt XNA vet du att det inte gör något utöver det vanliga. Jag använder en timerkomponent för att få polygonen att se ut att rotera hela tiden.
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();
}
}
}
Nu när du har skapat kontrollen ska vi titta på XAML. Eftersom vi ska placera kontrollen som vi skapade kommer vi att lägga till ett namnområde i rottaggen. Här definieras det som "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>
Expandera sedan taggen för WindowsFormsHost-kontrollen som du nyss placerade och lägg till en GraphicsDeviceControl, som du ser nedan.
<my:WindowsFormsHost Name="windowsFormsHostManagedDirectX" Width="300" Height="300"
HorizontalAlignment="Left" VerticalAlignment="Top">
<xw:GraphicsDeviceControl x:Name="GraphicsDeviceControl" />
</my:WindowsFormsHost>
Du behöver inte ha ett "x:Name", men exemplet använder det för att komma åt hörndata med ett skjutreglage.
Om du gör detta kan du köra en scen på WPF där polygoner ritas med en roterande polygon, som du ser i exemplet. Åtkomst via skjutreglage är en bonus, så ladda ner provdata och kontrollera den.
Programmet kräver .NET Framework 3.0, den senaste DirectX-körningen och Microsoft XNA Framework Redistributable 2.0. Dessutom, som ett hårdvarukrav, krävs "ett grafikkort som stöder Pixel Shader 1.1 eller högre".
Dessutom skapades projektet i "Visual Studio 2008 Professional Edition". Förbered en miljö för Visual Studio 2008.