|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionAfter writing my first article on XNA, my next interest in XNA moved me to figuring out how to host an XNA Window inside a WinForm, so that I can provide additional controls and other UI elements as part of this concept I'm trying to develop. This has proven to be a considerably arduous task. And while I've made a blog post about my research, I felt that it would be of benefit to the Code Project community to actually have a brief article on the topic, even though I did not come up with the actual solution. Instead, this article:
In the end, I found this website, which provides the C# source code for hosting an XNA Window as a user control. I'm not providing the download here as I didn't write it, so please visit Nuclex's website for the download. So, the point of making this a Code Project article is to condense into a single article all the blogs and websites I visited to undestand the problem and find the solution. I certainly didn't come across the solution googling for "XNA WinForm". Hopefully, in a few days, other people will find this Code Project article using those keywords! The First Problem: The Game Class ConstructorThe primary problem is that the
That's problem number one. The Second Problem: The GraphicsDeviceManager CreateDevice MethodProblem number two is the graphics = new GraphicsDeviceManager(this);
The game.Services.AddService(typeof(IGraphicsDeviceManager), this);
game.Services.AddService(typeof(IGraphicsDeviceService), this);
and then, in the GraphicsDevice device = new GraphicsDevice(
newInfo.Adapter,
newInfo.DeviceType,
this.game.Window.Handle, // <=====
newInfo.CreationOptions,
newInfo.PresentationParameters);
So the problem is twofold -- the Silly Solution #1: Adding Controls to the Game WindowThe very first idea I came across cast the A Better Solution, But Not GreatThe second workaround I found was almost right, hooking the public Game1(Form form)
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
this.form = form;
graphics.PreparingDeviceSettings +=
new EventHandler<PreparingDeviceSettingsEventArgs>
(OnPreparingDeviceSettings);
}
void OnPreparingDeviceSettings(object sender,
PreparingDeviceSettingsEventArgs e)
{
e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle =
form.Handle;
}
This (and other solutions I came across) worked fine except that the XNA Window would still appear, requiring a kludge to hide it in the protected override void Draw(GameTime gameTime)
{
if (firstTime)
{
System.Windows.Forms.Control xnaWindow =
System.Windows.Forms.Control.FromHandle((this.Window.Handle));
xnaWindow.Visible = false;
firstTime = false;
}
...
As well as properly disposing of it: static class Program
{
static Game1 game;
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
Form form = new Form();
form.Disposed += new EventHandler(OnDisposed);
form.ClientSize = new System.Drawing.Size(800, 600);
form.Show();
using (game = new Game1(form))
{
game.Run();
}
}
static void OnDisposed(object sender, EventArgs e)
{
game.Exit();
}
}
Other implementations, which are actually very straight forward (see references) typically eliminate the The Nuclex SolutionAfter putting in some billable hours, I revisited this and I came across a link in a reply to one of the references below that I hadn't checked out, and to my amazement, it was exactly what I was looking for. And indeed, the author does use reflector to recreate certain classes so as to gain control over the dual problems mentioned above. The link is here, and the implementation is very nice -- it's a user control, from which you derive your own class and work with the overridable methods just as you would from the I must say though that I'm still not happy with having to rewrite major sections of the framework. Hopefully the XNA framework architects will fix this problem in the future, and second, I still have a nagging feeling that there must be an easier way. ReferencesVarious references (I found a lot of good information reading the comments as well):
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||