Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #region File Description
- //-----------------------------------------------------------------------------
- // GraphicsDeviceControl.cs
- //
- // Microsoft XNA Community Game Platform
- // Copyright (C) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- #endregion
- #region Using Statements
- using System;
- using System.Drawing;
- using System.Windows.Forms;
- using Microsoft.Xna.Framework.Graphics;
- #endregion
- namespace MGControl
- {
- // System.Drawing and the XNA Framework both define Color and Rectangle
- // types. To avoid conflicts, we specify exactly which ones to use.
- using Color = System.Drawing.Color;
- using Rectangle = Microsoft.Xna.Framework.Rectangle;
- using Microsoft.Xna.Framework;
- using System.Diagnostics;
- /// <summary>
- /// Custom control uses the XNA Framework GraphicsDevice to render onto
- /// a Windows Form. Derived classes can override the Initialize and Draw
- /// methods to add their own drawing code.
- /// </summary>
- abstract public class GraphicsDeviceControl : Control
- {
- #region Fields
- // However many GraphicsDeviceControl instances you have, they all share
- // the same underlying GraphicsDevice, managed by this helper service.
- GraphicsDeviceService graphicsDeviceService;
- SwapChainRenderTarget _renderTarget;
- #endregion
- #region Properties
- /// <summary>
- /// Gets a GraphicsDevice that can be used to draw onto this control.
- /// </summary>
- public GraphicsDevice GraphicsDevice
- {
- get { return graphicsDeviceService.GraphicsDevice; }
- }
- public RenderTarget2D DefaultRenderTarget { get { return _renderTarget; } }
- /// <summary>
- /// Gets an IServiceProvider containing our IGraphicsDeviceService.
- /// This can be used with components such as the ContentManager,
- /// which use this service to look up the GraphicsDevice.
- /// </summary>
- public ServiceContainer Services
- {
- get { return services; }
- }
- ServiceContainer services = new ServiceContainer();
- #endregion
- #region Initialization
- public GraphicsDeviceControl() : base()
- {
- }
- /// <summary>
- /// Initializes the control.
- /// </summary>
- protected override void OnCreateControl()
- {
- // Don't initialize the graphics device if we are running in the designer.
- if (!DesignMode)
- {
- graphicsDeviceService = GraphicsDeviceService.AddRef(Handle,
- ClientSize.Width,
- ClientSize.Height);
- _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, ClientSize.Width, ClientSize.Height);
- // Register the service, so components like ContentManager can find it.
- //services.AddService<IGraphicsDeviceService>(graphicsDeviceService);
- // Give derived classes a chance to initialize themselves.
- Initialize();
- //Set the XNA mouse handing to use this window
- //Mouse.WindowHandle = Handle;
- return;
- }
- base.OnCreateControl();
- }
- /// <summary>
- /// Disposes the control.
- /// </summary>
- protected override void Dispose(bool disposing)
- {
- if (graphicsDeviceService != null)
- {
- graphicsDeviceService.Release(disposing);
- graphicsDeviceService = null;
- }
- if (_renderTarget != null)
- {
- _renderTarget.Dispose();
- _renderTarget = null;
- }
- base.Dispose(disposing);
- }
- #endregion
- #region Paint
- /// <summary>
- /// Redraws the control in response to a WinForms paint message.
- /// </summary>
- protected override void OnPaint(PaintEventArgs e)
- {
- try
- {
- //call drawing
- string beginDrawError = BeginDraw();
- if (string.IsNullOrEmpty(beginDrawError))
- {
- // Draw the control using the GraphicsDevice.
- Draw();
- OnAfterDraw(EventArgs.Empty);
- EndDraw();
- }
- else
- {
- // If BeginDraw failed, show an error message using System.Drawing.
- PaintUsingSystemDrawing(e.Graphics, beginDrawError);
- }
- }
- catch (Exception ex)
- {
- //MessageBox.Show(ex.StackTrace, ex.Message,MessageBoxButtons.OK,MessageBoxIcon.Error);
- Debug.WriteLine("EXCEPTION: " + ex.Message);
- }
- return;
- }
- /// <summary>
- /// Attempts to begin drawing the control. Returns an error message string
- /// if this was not possible, which can happen if the graphics device is
- /// lost, or if we are running inside the Form designer.
- /// </summary>
- internal string BeginDraw()
- {
- // If we have no graphics device, we must be running in the designer.
- if (graphicsDeviceService == null)
- {
- return Text + "\n\n" + GetType();
- }
- // Make sure the graphics device is big enough, and is not lost.
- string deviceResetError = HandleDeviceReset();
- if (!string.IsNullOrEmpty(deviceResetError))
- {
- return deviceResetError;
- }
- GraphicsDevice.SetRenderTarget(_renderTarget);
- // Many GraphicsDeviceControl instances can be sharing the same
- // GraphicsDevice. The device backbuffer will be resized to fit the
- // largest of these controls. But what if we are currently drawing
- // a smaller control? To avoid unwanted stretching, we set the
- // viewport to only use the top left portion of the full backbuffer.
- GraphicsDevice.Viewport = this.Viewport;
- return null;
- }
- public Viewport Viewport { get { return new Viewport(0, 0, ClientSize.Width, ClientSize.Height); } }
- /// <summary>
- /// Ends drawing the control. This is called after derived classes
- /// have finished their Draw method, and is responsible for presenting
- /// the finished image onto the screen, using the appropriate WinForms
- /// control handle to make sure it shows up in the right place.
- /// </summary>
- internal void EndDraw()
- {
- try
- {
- Rectangle sourceRectangle = new Rectangle(0, 0, ClientSize.Width,
- ClientSize.Height);
- _renderTarget.Present();
- }
- catch
- {
- // Present might throw if the device became lost while we were
- // drawing. The lost device will be handled by the next BeginDraw,
- // so we just swallow the exception.
- }
- }
- /// <summary>
- /// Helper used by BeginDraw. This checks the graphics device status,
- /// making sure it is big enough for drawing the current control, and
- /// that the device is not lost. Returns an error string if the device
- /// could not be reset.
- /// </summary>
- string HandleDeviceReset()
- {
- bool deviceNeedsReset = false;
- switch (GraphicsDevice.GraphicsDeviceStatus)
- {
- case GraphicsDeviceStatus.Lost:
- // If the graphics device is lost, we cannot use it at all.
- return "Graphics device lost";
- case GraphicsDeviceStatus.NotReset:
- // If device is in the not-reset state, we should try to reset it.
- deviceNeedsReset = true;
- break;
- default:
- // If the device state is ok, check whether it is big enough.
- PresentationParameters pp = GraphicsDevice.PresentationParameters;
- deviceNeedsReset = (ClientSize.Width != pp.BackBufferWidth) ||
- (ClientSize.Height != pp.BackBufferHeight);
- break;
- }
- // Do we need to reset the device?
- if (deviceNeedsReset)
- {
- try
- {
- graphicsDeviceService.ResetDevice(_renderTarget.Width,
- _renderTarget.Height);
- //recreate window swapchain
- _renderTarget.Dispose();
- _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, ClientSize.Width, ClientSize.Height);
- }
- catch (Exception e)
- {
- return "Graphics device reset failed\n\n" + e;
- }
- }
- return null;
- }
- /// <summary>
- /// If we do not have a valid graphics device (for instance if the device
- /// is lost, or if we are running inside the Form designer), we must use
- /// regular System.Drawing method to display a status message.
- /// </summary>
- protected virtual void PaintUsingSystemDrawing(Graphics graphics, string text)
- {
- graphics.Clear(Color.CornflowerBlue);
- using (Brush brush = new SolidBrush(Color.Black))
- {
- using (StringFormat format = new StringFormat())
- {
- format.Alignment = StringAlignment.Center;
- format.LineAlignment = StringAlignment.Center;
- graphics.DrawString(text, Font, brush, ClientRectangle, format);
- }
- }
- }
- /// <summary>
- /// Ignores WinForms paint-background messages. The default implementation
- /// would clear the control to the current background color, causing
- /// flickering when our OnPaint implementation then immediately draws some
- /// other color over the top using the XNA Framework GraphicsDevice.
- /// </summary>
- protected override void OnPaintBackground(PaintEventArgs pevent)
- {
- }
- #endregion
- #region Abstract Methods
- /// <summary>
- /// Derived classes override this to initialize their drawing code.
- /// </summary>
- abstract protected void Initialize();
- /// <summary>
- /// Derived classes override this to draw themselves using the GraphicsDevice.
- /// </summary>
- abstract internal void Draw();
- #endregion
- private readonly object AfterDrawEventLock = new object();
- private EventHandler AfterDrawEvent;
- public event EventHandler AfterDraw
- {
- add { lock (AfterDrawEventLock) { AfterDrawEvent += value; } }
- remove { lock (AfterDrawEventLock) { AfterDrawEvent -= value; } }
- }
- protected virtual void OnAfterDraw(EventArgs e)
- {
- EventHandler handler = null;
- lock (AfterDrawEventLock)
- {
- handler = AfterDrawEvent;
- if (handler == null) return;
- }
- handler(this, e);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement