Introduction
This article shows how to use .NET Windows Form controls with managed DirectX content. Most books/tutorials use a WinForm strictly with MDX content. But people are more interested in using WinForm controls together with MDX. This question is frequently asked and not well answered. Here, I present a small project using .NET 2.0 and Visual Studio 2005.
Technique
The most important part of this project is the DirectX device creation. Normally it's:
device = new Device(0, DeviceType.Hardware, this,
CreateFlags.SoftwareVertexProcessing, presentParams);
'this' is the alias of 'Form' used to represent this winForm.
In order to make .NET controls such as menubar, etc. to co-exist with a DirectX control, I set up a panel to be used by DirectX.
private System.Windows.Forms.Panel panel1;
device = new Device(0, DeviceType.Hardware, panel1,
CreateFlags.SoftwareVertexProcessing, presentParams);
To demonstrate that this works, I have provided a simple managed DirectX project with this project that can be downloaded. Here is the complete source code. Copy/paste and compile with .NET 2.0 managed DirectX.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
namespace Chapter1Code
{
public class Form1 : System.Windows.Forms.Form
{
private Device device = null;
private System.ComponentModel.Container components = null;
private Panel panel1;
private MenuStrip menuStrip1;
private ToolStripMenuItem mDXFormWithMenuToolStripMenuItem;
private ToolStripMenuItem exitToolStripMenuItem;
private float angle = 0.0f;
public Form1()
{
InitializeComponent();
this.Size = new Size(800, 600);
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.Opaque, true);
}
public void InitializeGraphics()
{
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Hardware, panel1,
CreateFlags.SoftwareVertexProcessing,
presentParams);
}
private void SetupCamera()
{
device.RenderState.CullMode = Cull.None;
device.Transform.World = Matrix.RotationAxis(new Vector3(angle /
((float)Math.PI * 2.0f),
angle / ((float)Math.PI * 4.0f),
angle / ((float)Math.PI * 6.0f)),
angle / (float)Math.PI);
angle += 0.1f;
device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4,
this.Width / this.Height, 1.0f, 100.0f);
device.Transform.View = Matrix.LookAtLH(new Vector3(0,0, 5.0f),
new Vector3(), new Vector3(0,1,0));
device.RenderState.Lighting = true;
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
device.Clear(ClearFlags.Target,
System.Drawing.Color.CornflowerBlue, 1.0f, 0);
SetupCamera();
CustomVertex.PositionNormalColored[] verts =
new CustomVertex.PositionNormalColored[3];
verts[0].Position = new Vector3(0.0f, 1.0f, 1.0f);
verts[0].Normal = new Vector3(0.0f, 0.0f, -1.0f);
verts[0].Color = System.Drawing.Color.White.ToArgb();
verts[1].Position = new Vector3(-1.0f, -1.0f, 1.0f);
verts[1].Normal = new Vector3(0.0f, 0.0f, -1.0f);
verts[1].Color = System.Drawing.Color.White.ToArgb();
verts[2].Position = new Vector3(1.0f, -1.0f, 1.0f);
verts[2].Normal = new Vector3(0.0f, 0.0f, -1.0f);
verts[2].Color = System.Drawing.Color.White.ToArgb();
device.Lights[0].Type = LightType.Point;
device.Lights[0].Position = new Vector3();
device.Lights[0].Diffuse = System.Drawing.Color.White;
device.Lights[0].Attenuation0 = 0.2f;
device.Lights[0].Range = 10000.0f;
device.Lights[0].Enabled = true;
device.BeginScene();
device.VertexFormat = CustomVertex.PositionNormalColored.Format;
device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, verts);
device.EndScene();
device.Present();
this.Invalidate();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.mDXFormWithMenuToolStripMenuItem =
new System.Windows.Forms.ToolStripMenuItem();
this.exitToolStripMenuItem =
new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip1.SuspendLayout();
this.SuspendLayout();
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(0, 24);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(307, 275);
this.panel1.TabIndex = 0;
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mDXFormWithMenuToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(307, 24);
this.menuStrip1.TabIndex = 1;
this.menuStrip1.Text = "menuStrip1";
this.mDXFormWithMenuToolStripMenuItem.DropDownItems.AddRange(
new System.Windows.Forms.ToolStripItem[] {
this.exitToolStripMenuItem});
this.mDXFormWithMenuToolStripMenuItem.Name =
"mDXFormWithMenuToolStripMenuItem";
this.mDXFormWithMenuToolStripMenuItem.Size =
new System.Drawing.Size(117, 20);
this.mDXFormWithMenuToolStripMenuItem.Text = "MDX form with Menu";
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
this.exitToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.exitToolStripMenuItem.Text = "Exit";
this.exitToolStripMenuItem.Click +=
new System.EventHandler(this.exitToolStripMenuItem_Click);
this.ClientSize = new System.Drawing.Size(307, 299);
this.Controls.Add(this.panel1);
this.Controls.Add(this.menuStrip1);
this.Name = "Form1";
this.Text = "Form1";
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
static void Main()
{
using (Form1 frm = new Form1())
{
frm.Show();
frm.InitializeGraphics();
Application.Run(frm);
}
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Dispose();
}
}
}
History
- 25th May, 2006: Initial post