Winform controls in XNA

I've looked at the winforms samples at the xna web site and found them to be a little bit of overkill for what essentially can be reduced down to one line of code.

// get game window as a win form Form class
Form frm = Control.FromHandle(this.Window.Handle) as Form;

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.

Downloads

Preview

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);
        }
    }

Created by: X

Just another personal website in this crazy online world

Name of author Dean Lunz (aka Created by: X)
Computer programming nerd, and tech geek.
About Me -- Resume