并行运行Winform和XNA游戏

时间:2013-03-09 01:41:57

标签: c# winforms xna

注意:关于将一个嵌入另一个问题,这个问题

我正在想办法让XNA游戏窗口stop pausing its execution成为dragged or resized,因为它在大多数情况下会中断网络连接并导致与游戏服务器失去同步。拥有无边框游戏窗口和winform作为可视容器可以解决问题。问题是,当用户调整虚假游戏窗口边框(实际上是winform)时,游戏窗口会检查并调整其边界以适应winform的客户区域。听起来很简单,但我一直无法完成这项工作。

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

有几个小时前提到this very recent question关于让两个WinForms一起运行的问题。希望它可以帮助你,帮助我们所有人:)


还有这个问题:

XNA How to Render and Update while resizing

XNA Is Running Slow when focus is removed

1 个答案:

答案 0 :(得分:0)

事实证明它并不难,虽然它可能带来不良副作用,例如从游戏中窃取资源,导致自发滞后(略微明显),并使其完美运作,这需要一些时间。 / p>

我所做的是创建了一个新的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);
    }

}

实施可能是非常糟糕和错误的,但是它可以在不从游戏中窃取所有资源的情况下工作,即使在调整假形式时游戏会丢弃一些帧,但不会完全停顿。

所以我测试了它,它有效,但它主要用于科学,我不打算很快就使用这种方法。也许当我真的,真的需要它。