XNA gebruiken in WPF-toepassingen
samenvatting
Hierin wordt beschreven hoe u het XNA Framework kunt gebruiken in WPF-toepassingen.
Werkomgeving
Voorwaarden
Ondersteunde XNA-versies |
|
Ondersteunde platforms |
|
Windows vereist Vertex Shader-versie | 1.1 |
Windows Vereiste Pixel Shader-versie | 1.1 |
Werkomgeving
perron |
stof
Als u met DirectX op een bepaald besturingselement wilt renderen, moet u de venstergreep voor dat besturingselement aanschaffen. In tegenstelling tot Windows Form-besturingselementen hebben WPF-besturingselementen echter geen venstergrepen (in WPF "tekenen" ze gewoon het besturingselement).
WPF biedt echter een besturingselement met de naam "WindowsFormsHost" waarmee u Windows Forms-besturingselementen kunt gebruiken.
In dit artikel zullen we een voorbeeld maken van het tekenen van een veelhoek zoals deze wordt geroteerd zoals hierboven weergegeven, maar ik zal de details van XNA zelf weglaten omdat het te lang zou zijn om het uit te leggen. Ik zal het alleen hebben over de relatie tussen WPF en XNA.
Open eerst een WPF-venster (in dit geval Window1.xaml) en plaats een WindowsFormHost-besturingselement vanuit de werkbalk. De schuifregelaar aan de rechterkant is een bonus.
Ik moet echt nog wat meer werk aan de XAML doen, maar ik laat het voor later omdat ik eerst de besturing moet maken om XNA te gebruiken.
Voeg een "Windows Forms" "Custom Control" toe aan uw project. Laat de naam GraphicsDeviceControl staan.
Vergeet niet om vooraf de referentie "Microsoft.Xna.Framework" toe te voegen. Er is ook "Microsoft.Xna.Framework.Game", maar dit wordt gebruikt in een game-only project, dus het is niet nodig om het op te nemen.
Om de voorbeeldcode kort te houden, zijn alle XNA-gerelateerde programma's samengevat in GraphicsDeviceControl.cs. Het is geen erg veelzijdige schrijfstijl, dus pas het toe en herschrijf het.
De volledige code voor de GraphicsDeviceControl wordt hieronder weergegeven (met uitzondering van het ontwerpgedeelte). Als je XNA ooit hebt gebruikt, weet je dat het niets ongewoons doet. Ik gebruik een Timer-component om de polygoon de hele tijd te laten draaien.
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 je het besturingselement hebt gemaakt, gaan we eens kijken naar de XAML. Aangezien we het besturingselement dat we hebben gemaakt gaan plaatsen, zullen we een naamruimte toevoegen aan de root-tag. Hier wordt het gedefinieerd als "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>
Vouw vervolgens de tag uit voor het WindowsFormsHost-besturingselement dat u zojuist hebt geplaatst en voeg een GraphicsDeviceControl toe, zoals hieronder wordt weergegeven.
<my:WindowsFormsHost Name="windowsFormsHostManagedDirectX" Width="300" Height="300"
HorizontalAlignment="Left" VerticalAlignment="Top">
<xw:GraphicsDeviceControl x:Name="GraphicsDeviceControl" />
</my:WindowsFormsHost>
U hoeft geen "x:Name" te hebben, maar het voorbeeld gebruikt het om toegang te krijgen tot hoekpuntgegevens met een schuifregelaar.
Als u dit doet, kunt u een scène op WPF uitvoeren waarin polygonen worden getekend met een roterende veelhoek, zoals weergegeven in het voorbeeld. Toegang via de schuifregelaar is een bonus, dus download de voorbeeldgegevens en controleer deze.
Het programma vereist .NET Framework 3.0, de nieuwste DirectX-runtime en het Microsoft XNA Framework Redistributable 2.0. Bovendien is als hardwarevereiste "een grafische kaart die Pixel Shader 1.1 of hoger ondersteunt" vereist.
Bovendien is het project gemaakt in "Visual Studio 2008 Professional Edition". Bereid een omgeving voor Visual Studio 2008 voor.