同时运行Winform和XNA游戏

本文关键字:XNA 游戏 Winform 运行 | 更新日期: 2023-09-27 18:03:08

注意:这个问题是不是关于嵌入一个到另一个!

我正在考虑一种方法,使XNA游戏窗口停止暂停其执行,而它被拖拽或调整大小,因为它在大多数情况下破坏网络连接,并导致与游戏服务器的不同步。拥有一个无边界的游戏窗口和一个winform作为视觉容器可以做到这一点。问题是,当用户调整假游戏窗口边框(实际上是winform)的大小时,游戏窗口会检查并调整其边界以适应winform的客户端区域。听起来很简单,但我一直在做这件事。

游戏窗口和winform都应该知道对方的存在,所以如果焦点在winform上,它会立即转移到游戏窗口,游戏窗口会调整自己的大小以适应winform,轮询大小变化,或者等待事件启动。我猜这包括交换窗口句柄。

有一个最近的问题,几个小时前问关于使两个WinForms一起运行。希望它能帮助你帮助我,从而帮助我们大家:)


也在这个问题上:

XNA如何在调整大小时渲染和更新

移开焦点时XNA运行缓慢

同时运行Winform和XNA游戏

事实证明这并不难,尽管它可能会带来不受欢迎的副作用,例如从游戏中窃取资源,导致自发延迟(稍微明显),并且要使其完美工作,需要一些时间。

我所做的是创建一个新的Form,并为其ResizeEnd事件分配一个事件处理程序。事件处理程序将public static Rectangle fakeWindowRect设置为伪窗口客户端区域的新矩形,并借助Form.RectangleToScreen()方法计算。

下面是一些代码片段:

static void Main(string[] args)
{
    System.Windows.Forms.Form f = new System.Windows.Forms.Form();
    f.ClientSize = new System.Drawing.Size(800, 600);
    f.TransparencyKey = f.BackColor;
    ((Action)(() => System.Windows.Forms.Application.Run(f))).BeginInvoke(
                                                               null, null);
    using (Game1 game = new Game1())
    {
        f.ResizeEnd += new EventHandler(game.f_LocationChanged);
        game.Run();
    }
}
public class Game1 : Microsoft.Xna.Framework.Game
{
    public static Rectangle windowRect;
    /* ... */
    protected override void Update(GameTime gameTime)
    {
        if (windowRect.X != this.Window.ClientBounds.X ||
            windowRect.Y != this.Window.ClientBounds.Y ||
            windowRect.Width != this.Window.ClientBounds.Width ||
            windowRect.Height != this.Window.ClientBounds.Height)
        {
             // this method sets the game window size, but not location
            InitGraphicsMode(windowRect.Width, windowRect.Height,
              this.graphics.IsFullScreen);
            var win = System.Windows.Forms.Control.FromHandle(
             this.Window.Handle) as
              System.Windows.Forms.Form;
            win.SetBounds(windowRect.X,
                          windowRect.Y,
                          windowRect.Width,
                          windowRect.Height);
            win.Activate();
        }
    }

    public void f_LocationChanged(object sender, EventArgs e)
    {
        var FakeWindow = sender as System.Windows.Forms.Form;
        var drawClientArea = FakeWindow.RectangleToScreen(
                               FakeWindow.ClientRectangle);
        windowRect = new Rectangle(
                   drawClientArea.X,
                   drawClientArea.Y,
                   drawClientArea.Width,
                   drawClientArea.Height);
    }
}

执行可能很糟糕,但它不会从游戏中窃取所有资源,即使在调整假表单时游戏也会掉落一些帧,但不会完全暂停。

所以我测试了它,它有效,但它主要用于科学,我不打算在短期内使用这种方法。也许在我非常非常需要的时候。