Az XNA használata WPF alkalmazásokban

Oldal frissítve :
Oldal létrehozásának dátuma :

összefoglalás

Ismerteti az XNA keretrendszer használatát WPF alkalmazásokban.

WPF アプリケーションで XNA を使用する

Működési környezet

Előfeltételek

Támogatott XNA verziók
  • 2.0
  • 3.0
Támogatott platformok
  • Windows (XP SP2 vagy újabb, Vista)
Windows Szükséges Vertex Shader verzió 1.1
Windows Szükséges Pixel Shader verzió 1.1

Működési környezet

peron

lényeg

Ha egy adott vezérlőn a DirectX használatával szeretne renderelni, be kell szereznie a vezérlő ablakfogóját. A Windows űrlapvezérlőivel ellentétben azonban a WPF vezérlők nem rendelkeznek ablakfogókkal (a WPF-ben egyszerűen "rajzolják" a vezérlőt).

A WPF azonban tartalmaz egy "WindowsFormsHost" nevű vezérlőt, amely lehetővé teszi a Windows Forms-vezérlők használatát.

Ebben a cikkben létrehozunk egy mintát egy sokszög rajzolására, ahogy a fentiek szerint elforgatják, de kihagyom magának az XNA-nak a részleteit, mert túl hosszú lenne elmagyarázni. Csak a WPF és az XNA kapcsolatáról fogok beszélni.

Először nyisson meg egy WPF-ablakot (ebben az esetben Window1.xaml), és helyezzen el egy WindowsFormHost vezérlőt az eszköztáron. A jobb oldali csúszka bónusz.

WPF ウインドウデザイン

Tényleg egy kicsit többet kell dolgoznom az XAML-en, de későbbre hagyom, mert először létre kell hoznom az XNA használatához szükséges vezérlőket.

Adjon hozzá egy "Windows Forms" "Egyéni vezérlőt" a projekthez. Hagyja meg a GraphicsDeviceControl nevet.

Windows Forms のカスタムコントロールを追加

Ne felejtse el előzetesen hozzáadni a "Microsoft.Xna.Framework" hivatkozást. Van még "Microsoft.Xna.Framework.Game" is, de ezt csak játékprojektben használják, így nincs szükség rá.

Managed DirectX の参照

A mintakód rövidsége érdekében az összes XNA-val kapcsolatos programot GraphicsDeviceControl.cs összegezzük. Ez nem túl sokoldalú írási stílus, ezért kérjük, alkalmazza és írja át.

A GraphicsDeviceControl teljes kódja az alábbiakban látható (kivéve a tervező részt). Ha valaha is használta az XNA-t, akkor tudni fogja, hogy nem csinál semmi rendkívülit. Időzítő komponenst használok, hogy a sokszög folyamatosan forogjon.

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();
        }
    }
}

Most, hogy létrehozta a vezérlőt, nézzük meg az XAML-kódot. Mivel az általunk létrehozott vezérlőt helyezzük el, hozzáadunk egy névteret a gyökércímkéhez. Itt "xw" -ként definiálják.

<Window&nbsp;x:Class="ManagedDirectXOnWPF.Window1"
&nbsp;&nbsp;&nbsp;&nbsp;xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
&nbsp;&nbsp;&nbsp;&nbsp;xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
&nbsp;&nbsp;&nbsp;&nbsp;Title="WPFウインドウ上でManaged DirectXを使用してポリゴン描画"
&nbsp;&nbsp;&nbsp;&nbsp;Height="338"&nbsp;Width="422"
&nbsp;&nbsp;&nbsp;&nbsp;xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xw="clr-namespace:ManagedDirectXOnWPF">
    <!-- 省略 -->
</Window>

Ezután bontsa ki az imént elhelyezett WindowsFormsHost vezérlő címkéjét, és adjon hozzá egy GraphicsDeviceControl vezérlőt az alább látható módon.

<my:WindowsFormsHost&nbsp;Name="windowsFormsHostManagedDirectX"&nbsp;Width="300"&nbsp;Height="300"
                    HorizontalAlignment="Left"&nbsp;VerticalAlignment="Top">
  <xw:GraphicsDeviceControl&nbsp;x:Name="GraphicsDeviceControl"&nbsp;/>
</my:WindowsFormsHost>

Nem kell "x:Name" értékkel rendelkeznie, de a minta ezt használja a csúcspontadatok csúszkával való eléréséhez.

Ha ezt teszi, futtathat egy jelenetet WPF-en, ahol a sokszögek forgó sokszöggel vannak rajzolva, ahogy a mintában látható. A csúszkával való hozzáférés bónusz, ezért kérjük, töltse le a mintaadatokat és ellenőrizze azokat.

A programhoz szükség van a .NET-keretrendszer 3.0-s verziójára, a legújabb DirectX futtatókörnyezetre és a Microsoft XNA Framework Redistributable 2.0-ra. Ezenkívül hardverkövetelményként "a Pixel Shader 1.1-es vagy újabb verzióját támogató grafikus kártya" szükséges.

Ezenkívül a projektet a "Visual Studio 2008 Professional Edition" -ben hozták létre. Környezet előkészítése a Visual Studio 2008 alkalmazáshoz.