Brug af XNA i WPF-applikationer
resumé
Beskriver, hvordan du bruger XNA Framework i WPF-programmer.
Driftsmiljø
Forudsætninger
Understøttede XNA-versioner |
|
Understøttede platforme |
|
Windows påkrævet Vertex Shader-version | 1.1 |
Windows påkrævet Pixel Shader-version | 1.1 |
Driftsmiljø
perron |
stof
Hvis du vil gengive på et bestemt kontrolelement ved hjælp af DirectX, skal du hente vindueshåndtaget til det pågældende kontrolelement. Men i modsætning til Windows Form-kontrolelementer har WPF-kontrolelementer ikke vindueshåndtag (i WPF "tegner" de blot kontrolelementet).
WPF indeholder dog et kontrolelement kaldet "WindowsFormsHost", der giver dig mulighed for at bruge Windows Forms-kontrolelementer.
I denne artikel vil vi lave et eksempel på tegning af en polygon, mens den roteres som vist ovenfor, men jeg vil udelade detaljerne i selve XNA, fordi det ville være for langt at forklare det. Jeg vil lige tale om forholdet mellem WPF og XNA.
Åbn først et WPF-vindue (i dette tilfælde Window1.xaml), og placer et WindowsFormHost-kontrolelement fra værktøjslinjen. Skyderen til højre er en bonus.
Jeg har virkelig brug for at arbejde lidt mere på XAML, men jeg lader det ligge til senere, fordi jeg skal oprette kontrollerne for at bruge XNA først.
Tilføj en "Windows Forms" "Brugerdefineret kontrol" til dit projekt. Lad navnet GraphicsDeviceControl stå.
Glem ikke at tilføje referencen "Microsoft.Xna.Framework" på forhånd. Der er også "Microsoft.Xna.Framework.Game", men dette bruges i et projekt, der kun er spil, så der er ingen grund til at inkludere det.
For at holde eksempelkoden kort opsummeres alle XNA-relaterede programmer i GraphicsDeviceControl.cs. Det er ikke en særlig alsidig skrivestil, så anvend den og omskriv den.
Den fulde kode til GraphicsDeviceControl er vist nedenfor (undtagen designerdelen). Hvis du nogensinde har brugt XNA, vil du vide, at det ikke gør noget ud over det sædvanlige. Jeg bruger en timerkomponent til at få polygonen til at se ud til at rotere hele 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 hvor du har oprettet kontrolelementet, lad os se på XAML. Da vi skal placere den kontrol, vi oprettede, tilføjer vi et navneområde til rodmærket. Her er det defineret 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>
Udvid derefter mærket for det WindowsFormsHost-kontrolelement, du lige har placeret, og tilføj en GraphicsDeviceControl som vist nedenfor.
<my:WindowsFormsHost Name="windowsFormsHostManagedDirectX" Width="300" Height="300"
HorizontalAlignment="Left" VerticalAlignment="Top">
<xw:GraphicsDeviceControl x:Name="GraphicsDeviceControl" />
</my:WindowsFormsHost>
Du behøver ikke at have et "x:Name", men eksemplet bruger det til at få adgang til toppunktdata med en skyder.
Hvis du gør dette, kan du køre en scene på WPF, hvor polygoner tegnes med en roterende polygon, som vist i eksemplet. Adgang via skyder er en bonus, så download venligst eksempeldataene og tjek dem.
Programmet kræver .NET Framework 3.0, den nyeste DirectX-runtime og Microsoft XNA Framework Redistributable 2.0. Derudover kræves der som et hardwarekrav "et grafikkort, der understøtter Pixel Shader 1.1 eller nyere".
Derudover blev projektet skabt i "Visual Studio 2008 Professional Edition". Forbered et miljø til Visual Studio 2008.