65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Windows Form 中轻松进行 XNA 渲染

2007年11月16日

CPOL

4分钟阅读

viewsIcon

121202

downloadIcon

7425

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

Screenshot - Article.gif

引言

我在 Bob Bradley 的这篇 文章 中读到,使用 XNA 可以轻松处理难事,而简单的事情却很难。到目前为止,这绝对是正确的,XNA 与 Windows Forms 的集成就是其中一个例子。

注意:本示例基于 ZiggyWare 教程,并增加了几项功能,如:

  • 可继承的、可用于渲染 XNA 的 WinForm
  • RefreshMode 允许选择“始终”刷新选项(请参阅program.cs了解详情)或 OnPanelPaint 选项,该选项将在每次绘制面板时刷新渲染。您始终可以手动调用 public Render() 方法。
  • 将视口背景色清除为面板控件的背景色。
  • 以 DirectX Framework 的方式实现了 OnFrameMoveOnFrameRenderOnDeviceResetting OnDeviceReset 事件。

注意 2:我刚刚意识到,关于这个主题还有另一篇文章,位于 此处。这是一种很好的方法,并且处理了我们稍后讨论的两种方式。请查看!

背景

由于 XNA 是一个跨平台游戏开发框架,可同时支持 PC-Windows 和 XBox360,因此其核心无法像 DirectX 多年来一直做的那样依赖 Windows Forms。

因此,当我们创建第一个 XNA 游戏项目时,我们根本找不到窗口。项目中甚至没有引用 System.Windows.Forms.dll。当应用程序启动时,窗口只是神奇地弹出。

事实上,所有这些都是由 XNA 框架在内部完成的,它作为我们的一层抽象,为应用程序运行的平台构建了适当的环境。

这很棒,但是,如果我不需要 XBox 支持怎么办?如果我想添加一个简单的 TextBox 让用户输入他的名字怎么办?当然,所有这些问题将在 XNA 的未来版本中得到解答,包括对仅限 Windows 项目的原生支持,可能通过新的项目模板,但现在,我们只能自己解决。那么我们如何解决呢?

基本上,有两种不同的方法:

  1. 构建一个 Windows 应用程序项目,该项目使用 XNA 对象来处理控件中的渲染,保留所有 WinForms 设计器功能,但缺少 Visual Studio 的所有 XNA 扩展。
  2. 构建一个“面向 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)。

稍后您会看到,我们将不得不处理视口面板的 ResizePaint 事件,因此请通过在设计器中双击事件来添加处理程序。

之后,将需要进行一些编码。

  1. 添加 using 语句,以方便使用。
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
  2. 创建一个 GraphicsDeviceObject 类型的局部变量。
     private GraphicsDevice mDevice;
  3. 重写 Form 的 OnLoad 方法,将所有 XNA 初始化放在那里(基本上调用两个方法,用于设备创建和重置)。
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        CreateGraphicsDevice();
        ResetGraphicsDevice();
    }
  4. 在创建的 Resize 事件处理程序中,调用 ResetGraphicsDevice
    private void OnViewportResize(object sender, EventArgs e)
    {
        ResetGraphicsDevice();
    }
  5. Paint 事件处理程序中包含您想要的典型渲染代码。
    private void OnVieweportPaint(object sender, PaintEventArgs e)
    {
        mDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.SteelBlue);
    
        // Do your rendering stuff here...
    
        mDevice.Present();
    }
  6. 现在,我们将创建前面提到的用于处理设备创建和重置的方法。以下方法创建一个 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);
    }
  7. 以下方法将在每次 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 日
© . All rights reserved.