Використання 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". Залиште назву GraphicsDeviceControl.
Не забудьте заздалегідь додати посилання "Microsoft.Xna.Framework". Існує також "Microsoft.Xna.Framework.Game", але він використовується в проекті тільки з іграми, тому немає необхідності включати його.
Щоб зразок коду був коротким, усі програми, пов'язані з XNA, узагальнені в GraphicsDeviceControl.cs. Це не дуже універсальний стиль письма, тому, будь ласка, застосуйте його та перепишіть.
Повний код для GraphicsDeviceControl наведено нижче (за винятком дизайнерської частини). Якщо ви коли-небудь користувалися XNA, ви знаєте, що він не робить нічого незвичайного. Я використовую компонент Timer, щоб зробити так, щоб полігон виглядав так, що обертається весь час.
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.