在WPF中托管XNA - 奇怪的“幻影”窗口问题

时间:2011-11-05 08:12:48

标签: c# wpf xna xna-4.0

我正在尝试使用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实例有点密切相关(或者可能是“孩子”?),但是我需要一种方法来关闭它(或者至少隐藏它)。

有什么想法吗?

3 个答案:

答案 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上的特定控件内部进行渲染。试一试:

https://xnaml.codeplex.com/

答案 2 :(得分:0)

除了仅仅是一种解决方法之外,我认为我们仍然坚持这是最好的,直到新的东西出现..

经过进一步调查,我发现幻像窗口是Game实例的“窗口句柄”,游戏需要继续运行。它可以作为游戏的窗口句柄访问,并从中创建(实际上是对现有的引用)表单。游戏还阻止了WPF TextBox等对象的输入机制,我通过派生TextBox类并手动覆盖OnKeyDown得到了一个非常不方便(但现在适用于我)的解决方法(它抓住了偶数但奇怪的是没有放在文本输入中。)并手动引发TextInput事件。有点hacky,但有效。使用表单,我可以将不透明度设置为零并将其移动到不在中间的位置,它将保留在那里。

但是我的解决方案只是一个hacky解决方案,Mike的解决方案肯定更好,所以如果你正在阅读这个并且即将开始这样的新项目,请按照他的回答。