Plan1:
Step1:Creat a new winform
public class Form1 : Form
{
public Form1()
{
System.Windows.Forms.
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint |
ControlStyles.Opaque, true);
UpdateStyles();
// handle the resize here because the XNA one is totally busted:
this.ClientSizeChanged += Form1_ClientSizeChanged;
game.FpsUpdated += new FpsDelegate(game_FpsUpdated);
Form form = Form.FromHandle(game.Window.Handle) as Form;
bool wannaGoSlow = true;
if (wannaGoSlow)
{
form.FormBorderStyle = FormBorderStyle.None;
form.Dock = DockStyle.Fill;
form.TopLevel = false;
form.Parent = this;
Controls.Add(form);
}
form.Visible = true;
Application.Idle += Application_Idle;
}
void Form1_ClientSizeChanged(object sender, EventArgs e)
{
if (game != null)
game.SetAspectRatio(Width, Height);
}
void game_FpsUpdated(Game sender, int fps)
{
Text = "FPS: " + fps.ToString();
}
void Application_Idle(object sender, EventArgs e)
//void Application_Idle()
{
while (AppStillIdle())
{
game.Tick();
}
}
private bool AppStillIdle()
{
NativeMethods.Message msg;
return !NativeMethods.PeekMessage(out msg, Handle, 0, 0, 0);
// not sure if that should be IntPtr.Zero or Handle or game.Window.Handle
}
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise,
false.</param>
protected override void Dispose(bool disposing)
{
Application.Idle -= Application_Idle;
this.ClientSizeChanged -= Form1_ClientSizeChanged;
game.Dispose();
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
}
public delegate void FpsDelegate(Microsoft.Xna.Framework.Game sender, int fps);
step2:
override base game class
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
public Game1()
: base()
{
IsMouseVisible = true;
graphics = new GraphicsDeviceManager(this);
graphics.SynchronizeWithVerticalRetrace = false;
graphics.ApplyChanges();
content = new ContentManager(Services);
// we're going to cut all the init from the run code and put it here:
IGraphicsDeviceManager graphicsDeviceManager = this.Services.GetService(typeof
(IGraphicsDeviceManager)) as IGraphicsDeviceManager;
if (graphicsDeviceManager != null) // should have been added by new
GraphicsDeviceManager
{
graphicsDeviceManager.CreateDevice();
// base BeginDraw relies on this next line; see MS Feedback item 277959
this.GetType().BaseType.GetField("graphicsDeviceManager",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue
(this, graphicsDeviceManager);
}
Initialize();
}
/// <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()
{
base.Initialize();
this.BeginRun();
// gameTime should be protected, not private: see MS Feedback item 277969
GameTime gt = this.GetType().BaseType.GetField("gameTime",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue
(this) as GameTime;
this.Update(gt);
// doneFirstUpdate should be set in base.Update(): see MS Feedback item 277975
this.GetType().BaseType.GetField("doneFirstUpdate",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue
(this, true);
}
protected override void Dispose(bool disposing)
{
this.EndRun();
base.Dispose(disposing);
}
//3d model to draw
//Model myModel;
/// <summary>
/// Load your graphics content. If loadAllContent is true, you should
/// load content from both ResourceManagementMode pools. Otherwise, just
/// load ResourceManagementMode.Manual content.
/// </summary>
/// <param name="loadAllContent">Which type of content to load.</param>
protected override void LoadGraphicsContent(bool loadAllContent)
{
base.LoadGraphicsContent(loadAllContent);
//if (loadAllContent)
// myModel = content.Load<Model>("Content//Models//p1_wedge");
}
/// <summary>
/// Unload your graphics content. If unloadAllContent is true, you should
/// unload content from both ResourceManagementMode pools. Otherwise, just
/// unload ResourceManagementMode.Manual content. Manual content will get
/// Disposed by the GraphicsDevice during a Reset.
/// </summary>
/// <param name="unloadAllContent">Which type of content to unload.</param>
protected override void UnloadGraphicsContent(bool unloadAllContent)
{
if (unloadAllContent == true)
content.Unload();
}
//time since last FPS update in seconds
double deltaFPSTime = 0;
int fps = 0;
/// <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)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back ==
Microsoft.Xna.Framework.Input.ButtonState.Pressed)
this.Exit();
// The time since Update was called last
double elapsed = gameTime.ElapsedGameTime.TotalSeconds;
deltaFPSTime += elapsed;
if (deltaFPSTime > 1)
{
if (FpsUpdated != null)
FpsUpdated(this, fps);
deltaFPSTime -= 1;
fps = 0;
}
modelRotation += (float)gameTime.ElapsedGameTime.TotalMilliseconds *
MathHelper.ToRadians(0.1f);
base.Update(gameTime);
if (System.Windows.Forms.Control.FromHandle
(graphics.GraphicsDevice.PresentationParameters.DeviceWindowHandle) == null)
{
this.Exit();
}
}
public event FpsDelegate FpsUpdated;
//Position of the model in world space, and rotation
Vector3 modelPosition = Vector3.Zero;
float modelRotation = 0.0f;
//Position of the Camera in world space, for our view matrix
Vector3 cameraPosition = new Vector3(0.0f, 50.0f, 5000.0f);
private float aspectRatio = 1;
public void SetAspectRatio(int width, int height)
{
graphics.PreferredBackBufferWidth = width;
graphics.PreferredBackBufferHeight = height;
aspectRatio = (float)width / (float)height;
graphics.GraphicsDevice.Reset();
}
/// <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)
{
fps++;
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
//Copy any parent transforms
//Matrix[] transforms = new Matrix[myModel.Bones.Count];
//myModel.CopyAbsoluteBoneTransformsTo(transforms);
////Draw the model, a model can have multiple meshes, so loop
//foreach (ModelMesh mesh in myModel.Meshes)
//{
// //This is where the mesh orientation is set, as well as our camera and
projection
// foreach (BasicEffect effect in mesh.Effects)
// {
// effect.EnableDefaultLighting();
// effect.World = transforms[mesh.ParentBone.Index] *
Matrix.CreateRotationY(modelRotation)
// * Matrix.CreateTranslation(modelPosition);
// effect.View = Matrix.CreateLookAt(cameraPosition, Vector3.Zero,
Vector3.Up);
// effect.Projection = Matrix.CreatePerspectiveFieldOfView
(MathHelper.ToRadians(45.0f),
// aspectRatio, 1.0f, 10000.0f);
// }
// //Draw the mesh, will use the effects set above.
// mesh.Draw();
//}
base.Draw(gameTime);
}
}
public 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);
}
}
Step3:
Type follow Code In Program.cs
static void Main(string[] args)
{
Application.EnableVisualStyles(); // must be done before creating any forms
Application.SetCompatibleTextRenderingDefault(false); // must be done before
creating any forms
Application.Run(new Form1());
}
簡述:
優點 分步啓動XNA 完全模擬XNA的啓動過程,包括加載資源,初始化==
缺點 加載過程過於複雜(相對於Game.Run()來說),運行後FPS不高,正常XNA在windows Mode 下FPS爲60,而現
在只有40-43左右
Plan2:
Step1: Create a Normal Winform
namespace StarterGame
{
public class WinFrom : Form
{
private testTextBox testTextBox1;
private Panel panel1;
private Panel panel2;
private TextBox textBox1;
Microsoft.Xna.Framework.Game1 game;
public WinFrom(Microsoft.Xna.Framework.Game1 _game)
{
CheckForIllegalCrossThreadCalls = false;
game = _game;
InitializeComponent();
this.Disposed += new EventHandler(WinFrom_Disposed);
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
UpdateStyles();
this.WindowState = FormWindowState.Minimized;
}
void WinFrom_Disposed(object sender, EventArgs e)
{
game.Exit();
}
private void InitializeComponent()
{
//
// WinFrom
//
this.ClientSize = new System.Drawing.Size(1016, 741);
this.Name = "WinFrom";
this.ResumeLayout(false);
}
}
}
Step2:
Override Base Game Class
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
IntPtr _myhander;
public Game1(IntPtr windowsptr)
: base()
{
_myhander = windowsptr;
IsMouseVisible = true;
graphics = new GraphicsDeviceManager(this);
graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
}
void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
{
e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = _myhander;
}
protected override bool BeginDraw()
{
System.Windows.Forms.Control xnaWindow = System.Windows.Forms.Control.FromHandle((this.Window.Handle));
((System.Windows.Forms.Form)xnaWindow).Visible = false;
return base.BeginDraw();
}
}
Step3:
Type follow Code In Pragram.cs
static void Main(string[] args)
{
Form1 form = new Form1();
form.Show();
using (Game1 game = new Game1(form.Handle))
{
game.Run();
}
}
簡述:
優點:加載簡單,相對於Plan1,基本上使用Run(),不涉及Xna底層,可以保持XNA的FPS
缺點:啓動時有Xna的Form,需要在BeginDraw()中進行處理,會有啓動時閃一下的感覺