Thursday, March 17, 2005

Rendering DirectX as part of a Window, using a Panel placed in the Form

Sometimes we don't want DirectX to render to the entire window. We'd rather have it render to a smaller subsection of the window and then we can use the form and prebuilt controls to interact with it.

This is especially true for map editors. Usually you will want to leverage the power of a rapid development app like C# to create an easy to use, flashy map editor.

It's actually really really easy to create a map editor style interface. Or to put it another way to render to a panel of your form.

Let's Start A New Project



As nearly always I'm using C#. I create a new project and choose a new Windows Application. First stop is the form designer.



Select panel from the tool bar and then draw this onto your form. Easy! This is where we will be displaying our DirectX scene.

Giving the form a standard game loop



Forms as I'm sure we all know are event based. We want some more control. So we change the code and introduce a function that will be called each frame.


static void Main()
{

Form1 form = new Form1();

form.Show();

while (form.Created)
{
form.Process(device);

//Let the OS handle what it needs to
Application.DoEvents();
}
}


That's how the game loop works. All our stuff goes in Process. Before we look into process though, I've added some code to the Form1 constructor. This code sets up the DirectX device! Let's take a quick look.


public Form1()
{
InitializeComponent();
InitializeGraphics(); //Sets DX up for the panel
}


Okay so we make a call to InitializeGraphics(). We have a global in our class called device.

 public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel panel1;
static public Device device;


We set this device up in InitializeGraphics(). It's very straight forward and minimalist. Infact similar to how we set up directX for the entire window, before now. This time though we pass in the panel rather then the entire form.


public void InitializeGraphics()
{
try
{
// Now let's setup our D3D stuff
PresentParameters presentParams =
new PresentParameters();
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.Windowed = true;

device = new Device(0,
DeviceType.Hardware,
panel1,
CreateFlags.MixedVertexProcessing,
presentParams);
device.DeviceReset += new System.EventHandler(this.OnResetDevice);
}
catch (DirectXException e)
{

MessageBox.Show(null, "Error intializing graphics: "
+ e.Message, "Error");
Close();
}
}


All pretty standard. Now let's write our process code so we can actually prove this works. We'll just clear the DirectX background and then present the results.


private void Process(Device device)
{
device.Clear(ClearFlags.Target,
System.Drawing.Color.Magenta,
1.0f,
0);
device.Present();
}





There we go beautiful. (Why can I never get the boxes to align nicely in the center - bah!)

No comments: