Хостинг XNA внутри WPF - странная проблема с «фантомным» окном - PullRequest
1 голос
/ 05 ноября 2011

Я пытаюсь разместить игру XNA в окне WPF с помощью хост-элемента управления Windows Forms. У меня странная проблема с тем, что при запуске игры создается окно «Призрак». Он создается точно при первом вызове выхода из игры 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 отображает правильно. Но фантомное окно (заголовок окна - это имя моей сборки), в нем ничего нет, размер не изменяется, курсор не отображается внутри него, и он действует как главное окно в том смысле, что когда я минимизирую это окно мое главное окно перестает отображать содержимое XNA, пока я не сверну это фантомное окно. Моя программа не закрывается, пока я не закрою ОБА окна. (Если я закрою только фантом, мое главное окно, как вы догадались, прекратит рендеринг содержимого XNA). Я попытался перебрать окна своего приложения с помощью App.Current.Windows, и все, что у меня есть, это мое главное окно, перечисленное там, поэтому я называю это полуадаптивное окно «фантомным» окном. Это не видно в моей объектной модели в WPF.

Когда я писал «Фантомное окно XNA WPF», первое, что я получил, было следующее: WPF: Как определить происхождение фантомного окна?

Так что я пошел и попробовал Снуп. Но Snoop, вероятно, также полагается на итерацию Windows и не видит там дополнительного окна. Я использую функцию перетаскивания (вы перетаскиваете курсор по экрану, а Snoop сообщает, какому процессу и окну он принадлежит), а Snoop сообщает, что Phantom Window на самом деле является моим MainWindow. Но мое MainWindow ТАКЖЕ то же самое окно, согласно Snoop. Так что этот фантом несколько тесно связан (или, может быть, «ребенок»?) Моего экземпляра MainWindow, но мне нужен способ закрыть его (или, по крайней мере, скрыть).

Есть идеи?

Ответы [ 3 ]

1 голос
/ 26 апреля 2012

Я написал это и закончил только сейчас, может быть, это может помочь вам. Я написал это специально для XNA <-> WPF Compatibility; то есть наличие XNA для рендеринга внутри определенного элемента управления в WPF. Дайте ему шанс:

https://xnaml.codeplex.com/

1 голос
/ 06 ноября 2011

Два хороших способа встраивания XNA в WPF, о которых я знаю, находятся в этом посте (один описан в самом посте, другой описан в первой ссылке в посте):

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 ожидает быть окном верхнего уровня.Я пытался возиться с решениями, такими как то, что вы опубликовали в прошлом, но никогда не выходили за рамки проблемы с фантомным окном.

0 голосов
/ 06 декабря 2011

Помимо того, что это просто обходной путь, я думаю, что мы застряли с этим, будучи лучшим, пока не появится что-то новое ..

После дальнейшего изучения я обнаружил, что фантомное окно - это «дескриптор окна» экземпляра Game, и оно необходимо для продолжения игры. К нему можно обращаться как к дескриптору окна игры, так и к созданию (фактически получая ссылку на существующую) формы из нее. Игра также предотвратила механизмы ввода объектов, таких как WPF TextBox, и я получил очень неудобный (но работающий сейчас для меня) обходной путь, извлекая класс TextBox и переопределяя OnKeyDown вручную (он улавливал четные, но странно не помещал в вводе текста.) и вызов события TextInput вручную. Немного хакерский, но работает. А с помощью формы я могу просто установить непрозрачность на ноль и переместить ее куда-то не посередине, и она останется там.

Но мое решение - просто хакерский обходной путь, и решение Майка определенно лучше, поэтому, если вы читаете это и собираетесь начать новый проект, подобный этому, следуйте его ответу.

...