我正在尝试使用Windows窗体主机控件在WPF窗口中托管XNA游戏。我有一个奇怪的问题,当我运行游戏时会创建一个“幻影”窗口。它是在第一次调用游戏的Update
方法退出时创建的。
这是更新代码,是新XNA项目的默认代码:
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);
}
在之后创建窗口我从最底部的最后一个花括号开始。 (是的,奇怪的是它不在base.Update
但在}
之后。)
我已经说过了Windows Forms主机,代码如下:
相关的XAML就在这里(我显然已经设置了Forms命名空间等,因此无需在此处粘贴):
<WindowsFormsHost Margin="12" Name="windowsFormsHost1">
<forms:Panel x:Name="p"></forms:Panel>
</WindowsFormsHost>
和代码隐藏:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Viewer v = new Viewer(p.Handle);
v.Run();
}
其中Viewer是我的Game类(来自XNA),其中包含:
public Viewer(IntPtr handle)
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
panelHandle = handle;
graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
}
void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
{
e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = panelHandle;
}
这项技术来自我几天前发现的一篇博文(现在我再也找不到它了,它完全是一样的 - 除了帖子很旧而且没有问题我有。)
问题在于,我构建并运行,但是与我的“普通”窗口一起,创建了一个幻像窗口。在我的主窗口中,XNA正确呈现。但是幻像窗口(Window标题是我的程序集的名称),其中没有任何内容,不可调整大小,光标不会在其中呈现,并且当我最小化此窗口时,它就像主窗口一样,我的主窗口停止呈现XNA内容,直到我取消最小化幻像窗口。在关闭两个窗口之前,我的程序不会退出。 (如果我只关闭幻像,我的主窗口,你猜测,停止渲染我的XNA内容)。我尝试使用'App.Current.Windows'迭代我的应用程序窗口,我所有的都是我的主窗口,这就是为什么我把那个半响应窗口称为“幻影”窗口。它在我的WPF对象模型中不可见。
当我写“XNA WPF幻像窗口”时,我得到的第一个是:WPF: How to determine the origin of a phantom window?
所以我去尝试了Snoop。但是Snoop可能还依赖于Windows
迭代,并且它也没有看到任何额外的窗口。我使用十字准线拖动功能(你将光标拖动到屏幕上,Snoop告诉它属于哪个进程和窗口),Snoop告诉Phantom Window实际上是我的MainWindow。但根据Snoop的说法,我的MainWindow也是同一个窗口。所以这个幻像与我的MainWindow实例有点密切相关(或者可能是“孩子”?),但是我需要一种方法来关闭它(或者至少隐藏它)。
有什么想法吗?
答案 0 :(得分:1)
我知道在WPF中嵌入XNA的两种好方法是在这篇文章中(一篇在帖子中描述,另一篇在帖子的第一个链接中描述):
http://blogs.msdn.com/b/nicgrave/archive/2011/03/25/wpf-hosting-for-xna-game-studio-4-0.aspx
两者都有代码示例,之前我使用过WriteableBitmap版本,结果很好。 (我正在创建一个开发工具,不需要显示大于384x384的任何东西,所以FPS是可以接受的;如果你需要带有大背部缓冲区的高FPS(例如800x600,720p等),你肯定会想要使用HwndHost方法)。
我建议您尝试最符合您需求的两个中的哪一个。当您尝试使用XNA创建的窗口时,XNA的WinForms窗口应该是一个顶级窗口。我已经尝试过搞乱解决方案,例如您过去发布的内容,但从未超出幻像窗口问题。
答案 1 :(得分:1)
我写了这个并且刚刚完成它,也许这可以帮到你。我是为了XNA&lt; - &gt;的明确目的而写的。 WPF兼容性;也就是说,让XNA能够在WPF上的特定控件内部进行渲染。试一试:
答案 2 :(得分:0)
除了仅仅是一种解决方法之外,我认为我们仍然坚持这是最好的,直到新的东西出现..
经过进一步调查,我发现幻像窗口是Game实例的“窗口句柄”,游戏需要继续运行。它可以作为游戏的窗口句柄访问,并从中创建(实际上是对现有的引用)表单。游戏还阻止了WPF TextBox等对象的输入机制,我通过派生TextBox类并手动覆盖OnKeyDown得到了一个非常不方便(但现在适用于我)的解决方法(它抓住了偶数但奇怪的是没有放在文本输入中。)并手动引发TextInput事件。有点hacky,但有效。使用表单,我可以将不透明度设置为零并将其移动到不在中间的位置,它将保留在那里。
但是我的解决方案只是一个hacky解决方案,Mike的解决方案肯定更好,所以如果你正在阅读这个并且即将开始这样的新项目,请按照他的回答。