I often see many posts on here from people that want to put the game's window inside a form. This is useful for editor applications, and so is the game class, which is why combining these two is a great idea (sometimes).
This is the form load method for one of the forms in my application, it creates the game class:
public RenderWindow()
{
InitializeComponent();
// create the game
game = new PGEGame();
game.IsMouseVisible = true;
// force the game to run in a window
IGraphicsDeviceManager graphicsDeviceManager = game.GetService<IGraphicsDeviceManager>();
graphicsDeviceManager.CreateDevice();
// beginDraw() relies on this
game.GetType().BaseType.GetField("graphicsDeviceManager",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(game, graphicsDeviceManager);
// embed the render window into this form
Form form = game.Form;
form.FormBorderStyle = FormBorderStyle.None;
form.Dock = DockStyle.Fill;
form.TopLevel = false;
form.Parent = this;
form.Visible = true;
Controls.Add(form);
// handle resize event for render window
game.Window.ClientSizeChanged += new EventHandler(Window_ClientSizeChanged);
// handle Application events
System.Windows.Forms.Application.Idle += new EventHandler(Application_Idle);
// NOTE: you could create components here...
// call Initialize and BeginRun
game.GetType().BaseType.GetMethod("Initialize", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(game, null);
game.GetType().BaseType.GetMethod("BeginRun", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(game, null);
// get the gametime and call the first update
GameTime gt = game.GetType().BaseType.GetField("gameTime",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(game) as GameTime;
game.GetType().BaseType.GetMethod("Update", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(game, new Object[] { gt });
// set doneFirstUpdate to true
game.GetType().BaseType.GetField("doneFirstUpdate",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(game, true);
}
PGEGame has the following member that is important here:
#if !(XBOX360)
public Form Form
{
get { return Form.FromHandle(Window.Handle) as Form; }
}
#endif
Which returns the GameWindow as a Form. You also need the following methods in the Form that contains the game:
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
System.Windows.Forms.Application.Idle -= Application_Idle;
}
void Application_Idle(object sender, EventArgs e)
{
while (AppStillIdle())
game.Tick();
}
private bool AppStillIdle()
{
NativeMethods.Message msg;
return !(NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0));
}
void Window_ClientSizeChanged(object sender, EventArgs e)
{
GameWindow window = game.Window;
if (game.Window.ClientBounds.Width != 0 && game.Window.ClientBounds.Height != 0)
game.SetAspectRatio(game.Window.ClientBounds);
}
And you need the following structure to examine messages:
static class NativeMethods
{
[StructLayout(LayoutKind.Sequential)]
public struct Message
{
public IntPtr hWnd;
public UInt32 msg;
public IntPtr wParam;
public IntPtr lParam;
public UInt32 time;
public Point p;
}
[SuppressUnmanagedCodeSecurity] // We won't use this maliciously
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);
}
The form should implement IDisposable so it can release its event handler for Application.Idle. This is essentially creating the game and not calling run, letting the application render the game when it's not busy. It performs good enough for me, I have not tested it for speed and since this is usually for editing applications, speed is not the primary focus. The above sample is primarily based on code posted by not_a_commie @
http://forums.xna.com/post/10166.aspx