Použití XNA v aplikacích WPF
shrnutí
Popisuje, jak používat XNA Framework v aplikacích WPF.
Provozní prostředí
Požadavky
Podporované verze XNA |
|
Podporované platformy |
|
Požadovaná verze Vertex Shader systému Windows | 1.1 |
Windows Požadovaná verze pixel shaderu | 1.1 |
Provozní prostředí
nástupiště |
hmota
Chcete-li vykreslit konkrétní ovládací prvek pomocí rozhraní DirectX, musíte pro tento ovládací prvek získat popisovač okna. Na rozdíl od ovládacích prvků Windows Form však ovládací prvky WPF nemají popisovače oken (ve WPF jednoduše "vykreslí" ovládací prvek).
WPF však poskytuje ovládací prvek s názvem "WindowsFormsHost", který umožňuje používat ovládací prvky model Windows Forms.
V tomto článku vytvoříme ukázku kreslení mnohoúhelníku při jeho otáčení, jak je znázorněno výše, ale vynechám podrobnosti samotné XNA, protože by bylo příliš dlouhé to vysvětlit. Budu mluvit jen o vztahu mezi WPF a XNA.
Nejprve otevřete okno WPF (v tomto případě Window1.xaml) a umístěte ovládací prvek WindowsFormHost z panelu nástrojů. Posuvník vpravo je bonus.
Opravdu potřebuji udělat trochu více práce na XAML, ale to nechám na později, protože nejprve musím vytvořit ovládací prvky pro použití XNA.
Přidejte do projektu "model Windows Forms" "vlastní ovládací prvek". Ponechte název GraphicsDeviceControl.
Nezapomeňte předem přidat odkaz na "Microsoft.Xna.Framework". Existuje také "Microsoft.Xna.Framework.Game", ale ten se používá v čistě herním projektu, takže není potřeba jej zahrnovat.
Aby byl ukázkový kód krátký, jsou všechny programy související s XNA shrnuty v GraphicsDeviceControl.cs. Není to příliš univerzální styl psaní, takže jej prosím použijte a přepište.
Úplný kód pro GraphicsDeviceControl je uveden níže (s výjimkou části pro návrháře). Pokud jste někdy používali XNA, budete vědět, že nedělá nic neobvyklého. Používám komponentu Časovač, aby se zdálo, že se mnohoúhelník neustále otáčí.
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();
}
}
}
Teď, když jste vytvořili ovládací prvek, se podívejme na kód XAML. Protože se chystáme umístit ovládací prvek, který jsme vytvořili, přidáme do kořenového tagu jmenný prostor. Zde je definován jako "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>
Dále rozbalte značku ovládacího prvku WindowsFormsHost, který jste právě umístili, a přidejte GraphicsDeviceControl, jak je znázorněno níže.
<my:WindowsFormsHost Name="windowsFormsHostManagedDirectX" Width="300" Height="300"
HorizontalAlignment="Left" VerticalAlignment="Top">
<xw:GraphicsDeviceControl x:Name="GraphicsDeviceControl" />
</my:WindowsFormsHost>
Nemusíte mít "x:Name", ale ukázka ho používá pro přístup k datům vrcholů pomocí posuvníku.
Pokud to uděláte, můžete spustit scénu ve WPF, kde jsou polygony vykresleny pomocí rotujícího mnohoúhelníku, jak je znázorněno v ukázce. Přístup pomocí posuvníku je bonus, proto si prosím stáhněte ukázková data a zkontrolujte je.
Program vyžaduje rozhraní .NET Framework 3.0, nejnovější běhové prostředí DirectX a Microsoft XNA Framework Redistributable 2.0. Kromě toho je jako hardwarový požadavek vyžadována "grafická karta, která podporuje Pixel Shader 1.1 nebo vyšší".
Projekt byl navíc vytvořen v "Visual Studio 2008 Professional Edition". Připravte prostředí pro Visual Studio 2008.