Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / Windows Forms
Article

Easy Rendering with XNA Inside a Windows Form

Rate me:
Please Sign up or sign in to vote.
4.90/5 (17 votes)
16 Nov 2007CPOL4 min read 118.2K   7.4K   55   11
This article shows an easy way to render 2D or 3D graphics in a Windows Form using XNA, keeping all the Windows features and controls
Screenshot - Article.gif

Introduction

I read in this article by Bob Bradley that hard things are easy with XNA, and easy things are quite hard. By now that's absolutely true and XNA integration with Windows Forms is an example of that.

Note: This example is based on this ZiggyWare tutorial, and adds to it several features like:

  • Inheritable WinForm ready to render XNA
  • A RefreshMode allows to select an "always" refresh option (see program.cs for details) or an OnPanelPaint option, which will refresh the render each time the panel is painted. You can always call the public Render() method manually
  • Cleans the viewport's background color to the Panel Control's back color
  • Implements OnFrameMove, OnFrameRender, OnDeviceResetting and OnDeviceReset events, in a DirectX Framework way

Note 2: I've just realized there's another article on this same topic here. It's also a very good approach and handles both roads that we discuss later. Check it out!

Background

As XNA is a cross-platform game development Framework, ready to work both with PC-Windows and XBox360, its core cannot rely on Windows Forms like DirectX has been doing for years.

So, when we create our first XNA Game Project, we'll find no Window at all. Even System.Windows.Forms.dll is not referenced in the project. The window just magically pops up when we launch the application.

In fact, all this stuff is done internally by the XNA Framework, which works as an abstraction layer for us, building the appropriate environment for the platform the application runs in.

That's great but, what if I don't need XBox support? What if I want to add a simple TextBox to let the user enter his name? Of course all these questions will be answered in future versions of XNA, including native support for Windows-only projects, probably through a new Project Template, but for now, we are alone. So how do we fix that?

Basically, there are two different roads:

  1. Build a Windows Application project which uses XNA objects to handle rendering in a control, keeps all the WinForms designer functionality, but lacks all the XNA extensions for Visual Studio.
  2. Build a Game For Windows project, which uses Windows Controls to make the UI. This keeps all the XNA and extensions functionality, but will force you to design your controls "by hand".

In this article, we will follow the first path, and leave the second one for a next post.

Using the Code

What I provide in the ZIP is a full Visual Studio Express project you can use as an empty template for your own applications. It includes XNAWinForm: a base Form you can inherit from, or you can change it, to include as many elements you may need. In the sample code you will also find Form1: and an example of using XNAWinForm.

So, for those of you who are familiar with DirectX or MDX, XNA exposes several useful events if you don't want to include all your rendering logic inside the Form:

  • OnFrameMove: It is called before rendering, to allow you to update anything you may need.
  • OnFrameRender: Include in its handler any rendering code you may want.
  • DeviceResetting: This event is called when the device is going to be reset, so you can dispose objects or whatever.
  • DeviceReset: Called after the device is reset, to allow you to update device-dependent elements.

In order to code your own XNA ready form, the first thing you have to do is to create a New WindowsApplication project, add the references to XNA DLLs, and add to your empty form the control you want to render in (in the example: panelViewport).

As you will see later, we will have to handle the events Resize and Paint of the panel viewport, so add a handler for them by double-clicking on the events in the designer.

After that, a little bit of coding will be necessary:

  1. Add using statements, just for comfort:
    C#
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
  2. Create a local variable of the type GraphicsDeviceObject:
    C#
    private GraphicsDevice mDevice;
    
  3. Override the OnLoad method of the Form to put all the XNA initialization there (basically call two methods, for device creation and reset):
    C#
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        CreateGraphicsDevice();
        ResetGraphicsDevice();
    }
  4. In the Resize event handler created, call ResetGraphicsDevice:
    C#
    private void OnViewportResize(object sender, EventArgs e)
    {
        ResetGraphicsDevice();
    }
  5. Include the typical rendering code that you want in the Paint event handler:
    C#
    private void OnVieweportPaint(object sender, PaintEventArgs e)
    {
        mDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.SteelBlue);
    
        // Do your rendering stuff here...
        mDevice.Present();
    }
  6. Now, we will create the methods called earlier, needed to handle device creation and reset. The following method creates a GraphicsDevice object, with certain creation parameters:
    C#
    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. The following one will be called each time the panelViewport is resized, to re-create the GraphicsDevice with the new viewport size:
    C#
    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();
    }

That's it, you have a Windows Form ready to render graphics with XNA.

Points of Interest

Note: This example is based on this ZiggyWare tutorial.

ZiggyWare should be a must for any XNA or general developer. They have great tutorials.

I've just realized there is another article on this same topic here. It's also a very good approach and handles both ways we discussed previously. Check it out!

History

  • First version: November 16, 2007

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Spain Spain
Inaki Ayucar is a Microsoft MVP in DirectX/XNA, and a software engineer involved in development since his first Spectrum 48k, in the year 1987. He is the founder and chief developer of The Simax Project (www.simaxvirt.com) and is very interested in DirectX/XNA, physics, game development, simulation, C++ and C#.

His blog is: http://graphicdna.blogspot.com

To contact Inaki: iayucar@simax.es

Comments and Discussions

 
GeneralMy vote of 5 Pin
Prasanna17082-May-12 18:29
Prasanna17082-May-12 18:29 
GeneralIs it possible... Pin
umberdupa5-Apr-10 11:30
umberdupa5-Apr-10 11:30 
GeneralI can not find "CreateOptions" in XNA3.0~ Pin
Dragonfly_Lee14-Apr-09 23:21
Dragonfly_Lee14-Apr-09 23:21 
GeneralRe: I can not find "CreateOptions" in XNA3.0~ Pin
SillyG1-Jul-09 18:30
SillyG1-Jul-09 18:30 
GeneralError in Demo Application Pin
Armando Airo'19-Nov-07 21:04
Armando Airo'19-Nov-07 21:04 
GeneralRe: Error in Demo Application Pin
Inaki Ayucar19-Nov-07 22:53
Inaki Ayucar19-Nov-07 22:53 
Well, I haven´t tested it in other computers, but it works fine in mine.

What exact error you get?



Inaki Ayucar
http://graphicdna.blogspot.com

GeneralRe: Error in Demo Application Pin
Armando Airo'19-Nov-07 23:25
Armando Airo'19-Nov-07 23:25 
GeneralRe: Error in Demo Application Pin
Inaki Ayucar20-Nov-07 0:09
Inaki Ayucar20-Nov-07 0:09 
GeneralRe: Error in Demo Application Pin
Armando Airo'20-Nov-07 0:21
Armando Airo'20-Nov-07 0:21 
GeneralRe: Error in Demo Application Pin
CyrusT18-Mar-13 20:51
CyrusT18-Mar-13 20:51 
GeneralRe: Error in Demo Application Pin
Inaki Ayucar18-Mar-13 21:57
Inaki Ayucar18-Mar-13 21:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.