Използване на XNA в WPF приложения
резюме
Описва как да използвате XNA Framework в WPF приложения.
Работна среда
Предпоставки
Поддържани версии на XNA |
|
Поддържани платформи |
|
Необходима версия на Vertex Shader за Windows | 1.1 |
Необходима версия на пикселния шейдър за Windows | 1.1 |
Работна среда
платформа |
вещество
За да рендирате на определена контрола с помощта на DirectX, трябва да получите дръжката на прозореца за тази контрола. Въпреки това, за разлика от контролите на Windows Form, WPF контролите нямат дръжки на прозорци (в WPF те просто "рисуват" контролата).
WPF обаче предоставя контрола, наречена "WindowsFormsHost", която ви позволява да използвате контроли на Windows Forms.
В тази статия ще създадем извадка за рисуване на многоъгълник, докато се върти, както е показано по-горе, но ще пропусна подробностите за самия XNA, защото би било твърде дълго да го обяснявам. Ще говоря само за връзката между WPF и XNA.
Първо отворете WPF прозорец (в този случай Window1.xaml) и поставете контрола WindowsFormHost от лентата с инструменти. Плъзгачът вдясно е бонус.
Наистина трябва да свърша малко повече работа по XAML, но ще го оставя за по-късно, защото първо трябва да създам контролите, за да използвам XNA.
Добавете "Windows Forms" "Custom Control" към вашия проект. Оставете името GraphicsDeviceControl.
Не забравяйте да добавите препратката "Microsoft.Xna.Framework" предварително. Има и "Microsoft.Xna.Framework.Game", но той се използва в проект само за игра, така че няма нужда да го включвате.
За да бъде примерният код кратък, всички програми, свързани с XNA, са обобщени в GraphicsDeviceControl.cs. Това не е много универсален стил на писане, така че, моля, приложете го и го пренапишете.
Пълният код за GraphicsDeviceControl е показан по-долу (с изключение на дизайнерската част). Ако някога сте използвали XNA, ще знаете, че той не прави нищо необичайно. Използвам компонент на таймера, за да направя многоъгълника да изглежда да се върти през цялото време.
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();
}
}
}
Сега, след като създадохте контролата, нека разгледаме XAML. Тъй като ще поставим контролата, която създадохме, ще добавим пространство от имена към основния таг. Тук се определя като "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>
След това разгънете етикета за контролата WindowsFormsHost, която току-що поставихте, и добавете GraphicsDeviceControl, както е показано по-долу.
<my:WindowsFormsHost Name="windowsFormsHostManagedDirectX" Width="300" Height="300"
HorizontalAlignment="Left" VerticalAlignment="Top">
<xw:GraphicsDeviceControl x:Name="GraphicsDeviceControl" />
</my:WindowsFormsHost>
Не е необходимо да имате "x:Name", но примерът го използва за достъп до върхови данни с плъзгач.
Ако направите това, можете да стартирате сцена в WPF, където полигоните са начертани с въртящ се многоъгълник, както е показано в примера. Достъпът чрез плъзгач е бонус, така че, моля, изтеглете примерните данни и ги проверете.
Програмата изисква .NET Framework 3.0, най-новата среда за изпълнение на DirectX и Microsoft XNA Framework Redistributable 2.0. Освен това, като хардуерно изискване, е необходима "графична карта, която поддържа Pixel Shader 1.1 или по-нова версия".
В допълнение, проектът е създаден в "Visual Studio 2008 Professional Edition". Подгответе среда за Visual Studio 2008.