在 Windows Form 中轻松进行 XNA 渲染






4.90/5 (15投票s)
本文介绍了一种在 Windows 窗体中使用 XNA 渲染 2D 或 3D 图形 的简便方法,同时保留所有 Windows 功能和控件。

引言
我在 Bob Bradley 的这篇 文章 中读到,使用 XNA 可以轻松处理难事,而简单的事情却很难。到目前为止,这绝对是正确的,XNA 与 Windows Forms 的集成就是其中一个例子。
注意:本示例基于 此 ZiggyWare 教程,并增加了几项功能,如:
- 可继承的、可用于渲染 XNA 的 WinForm
RefreshMode
允许选择“始终”刷新选项(请参阅program.cs了解详情)或OnPanelPaint
选项,该选项将在每次绘制面板时刷新渲染。您始终可以手动调用public Render()
方法。- 将视口背景色清除为面板控件的背景色。
- 以 DirectX Framework 的方式实现了
OnFrameMove
、OnFrameRender
、OnDeviceResetting
和OnDeviceReset
事件。
注意 2:我刚刚意识到,关于这个主题还有另一篇文章,位于 此处。这是一种很好的方法,并且处理了我们稍后讨论的两种方式。请查看!
背景
由于 XNA 是一个跨平台游戏开发框架,可同时支持 PC-Windows 和 XBox360,因此其核心无法像 DirectX 多年来一直做的那样依赖 Windows Forms。
因此,当我们创建第一个 XNA 游戏项目时,我们根本找不到窗口。项目中甚至没有引用 System.Windows.Forms.dll。当应用程序启动时,窗口只是神奇地弹出。
事实上,所有这些都是由 XNA 框架在内部完成的,它作为我们的一层抽象,为应用程序运行的平台构建了适当的环境。
这很棒,但是,如果我不需要 XBox 支持怎么办?如果我想添加一个简单的 TextBox 让用户输入他的名字怎么办?当然,所有这些问题将在 XNA 的未来版本中得到解答,包括对仅限 Windows 项目的原生支持,可能通过新的项目模板,但现在,我们只能自己解决。那么我们如何解决呢?
基本上,有两种不同的方法:
- 构建一个 Windows 应用程序项目,该项目使用 XNA 对象来处理控件中的渲染,保留所有 WinForms 设计器功能,但缺少 Visual Studio 的所有 XNA 扩展。
- 构建一个“面向 Windows 的游戏”项目,该项目使用 Windows 控件来制作 UI。这保留了所有 XNA 和扩展功能,但会迫使您“手动”设计控件。
在本文中,我们将采用第一种方法,并将第二种方法留到下一篇文章。
Using the Code
我在 ZIP 文件中提供了一个完整的 Visual Studio Express 项目,您可以将其用作自己应用程序的空模板。它包括 XNAWinForm
:一个您可以继承的基础 Form,或者您可以对其进行修改,以包含您需要的任意数量的元素。在示例代码中,您还将找到 Form1
:以及使用 XNAWinForm
的示例。
因此,对于那些熟悉 DirectX 或 MDX 的人来说,XNA 提供了几个有用的事件,如果您不想将所有渲染逻辑都包含在 Form 中。
OnFrameMove
:在渲染之前调用,允许您更新任何需要更新的内容。OnFrameRender
:在其处理程序中包含任何您可能想要的渲染代码。DeviceResetting
:当设备即将重置时调用此事件,因此您可以释放对象或其他内容。DeviceReset
:在设备重置后调用,允许您更新与设备相关的元素。
要编写自己的 XNA 就绪窗体,您需要做的第一件事是创建一个新的 WindowsApplication
项目,添加对 XNA DLL 的引用,然后将您想要渲染的控件添加到空白窗体中(在示例中为 panelViewport
)。
稍后您会看到,我们将不得不处理视口面板的 Resize
和 Paint
事件,因此请通过在设计器中双击事件来添加处理程序。
之后,将需要进行一些编码。
- 添加
using
语句,以方便使用。
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics;
- 创建一个
GraphicsDeviceObject
类型的局部变量。
private GraphicsDevice mDevice;
- 重写 Form 的
OnLoad
方法,将所有 XNA 初始化放在那里(基本上调用两个方法,用于设备创建和重置)。
protected override void OnLoad(EventArgs e) { base.OnLoad(e); CreateGraphicsDevice(); ResetGraphicsDevice(); }
- 在创建的
Resize
事件处理程序中,调用ResetGraphicsDevice
。
private void OnViewportResize(object sender, EventArgs e) { ResetGraphicsDevice(); }
- 在
Paint
事件处理程序中包含您想要的典型渲染代码。
private void OnVieweportPaint(object sender, PaintEventArgs e) { mDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.SteelBlue); // Do your rendering stuff here... mDevice.Present(); }
- 现在,我们将创建前面提到的用于处理设备创建和重置的方法。以下方法创建一个
GraphicsDevice
对象,并带有一些创建参数。
private void CreateGraphicsDevice() { // Create Presentation Parameters PresentationParameters pp = new PresentationParameters(); pp.BackBufferCount = 1; pp.IsFullScreen = false; pp.SwapEffect = SwapEffect.Discard; pp.BackBufferWidth = panelViewport.Width; pp.BackBufferHeight = panelViewport.Height; pp.AutoDepthStencilFormat = DepthFormat.Depth24Stencil8; pp.EnableAutoDepthStencil = true; pp.PresentationInterval = PresentInterval.Default; pp.BackBufferFormat = SurfaceFormat.Unknown; pp.MultiSampleType = MultiSampleType.None; // Create device mDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, this.panelViewport.Handle, CreateOptions.HardwareVertexProcessing, pp); }
- 以下方法将在每次
panelViewport
调整大小时调用,以使用新的视口大小重新创建GraphicsDevice
。
private void ResetGraphicsDevice() { // Avoid entering until panelViewport is setup and device created if (mDevice == null || panelViewport.Width == 0 || panelViewport.Height == 0) return; // Reset device mDevice.PresentationParameters.BackBufferWidth = panelViewport.Width; mDevice.PresentationParameters.BackBufferHeight = panelViewport.Height; mDevice.Reset(); }
就是这样,您已经拥有了一个可以使用 XNA 渲染图形的 Windows 窗体。
关注点
注意:本示例基于 此 ZiggyWare 教程。
对于任何 XNA 或通用开发人员来说,ZiggyWare 都应该是必看的。他们有很棒的教程。
我刚刚意识到,关于这个主题还有另一篇文章,位于 此处。这是一种很好的方法,并且处理了我们之前讨论过的两种方式。请查看!
历史
- 初版:2007 年 11 月 16 日