I have provided a example project below and code from that project that demonstrates how to add winform controls to your game window in only a few lines of code.
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
private Texture2D img;
Panel pnl = new Panel();
Label lbl = new Label();
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
// allow the mouse to remain visible and allow user resizing ofthe window
this.IsMouseVisible = true;
this.Window.AllowUserResizing = true;
// create and setup the winform controls on the game window
this.CreateControls();
// hook into the client size change event so we can update the win form
// controls and update the viewport on the graphics device
this.Window.ClientSizeChanged += this.Window_ClientSizeChanged;
}
private void CreateControls()
{
// get game window as a win form Form class
Form frm = Control.FromHandle(this.Window.Handle) as Form;
// setup the panel control
this.pnl.Dock = DockStyle.Right;
this.pnl.Width = 250;
// createa exit button and add it to the panel
Button btn = new Button();
btn.Location = new System.Drawing.Point(10, 10);
btn.Text = "Exit";
btn.Click += (sender, e) => { this.Exit(); };
// add the button to the panel and add the panel to the game window form
this.pnl.Controls.Add(btn);
frm.Controls.Add(this.pnl);
// setup the lable control and add it to the panel control
this.lbl.Text = "";
this.lbl.Location = new Point(10, btn.Top + btn.Height + 10);
this.lbl.AutoSize = true;
this.pnl.Controls.Add(this.lbl);
}
void Window_ClientSizeChanged(object sender, EventArgs e)
{
// get the viewport from the graphics device
var vp = this.GraphicsDevice.Viewport;
// change the viewport dimensions so that it is not drawn under any of our winform controls
vp.Width = this.Window.ClientBounds.Width - pnl.Width;
vp.Height = this.Window.ClientBounds.Height;
// set the viewport back onto the graphics device
this.GraphicsDevice.Viewport = vp;
// update the label to display the rectangle info
Rectangle rect = new Rectangle(vp.X, vp.Y, vp.Width, vp.Height);
lbl.Text = "Client: " + this.Window.ClientBounds.ToString() +
"\r\n" +
"Viewport: " + rect.ToString();
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
this.Window_ClientSizeChanged(this, EventArgs.Empty);
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// load a sample image that will be drawn the size of the viewport
this.img = this.Content.Load<Texture2D>("Map2");
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// draw the image the same size of the viewport
this.spriteBatch.Begin();
var vp = this.GraphicsDevice.Viewport;
Rectangle rect = new Rectangle(vp.X, vp.Y, vp.Width, vp.Height);
Rectangle srcrect =new Rectangle(0,0,this.img.Width,this.img.Height);
this.spriteBatch.Draw(this.img, rect, srcrect, Color.White);
this.spriteBatch.End();
base.Draw(gameTime);
}
}