Встраивание приложения Unity3D на страницу WPF приводит к исчезновению имени процесса после перехода на новую страницу - PullRequest
0 голосов
/ 17 февраля 2019

Я использую код, размещенный в этом вопросе, с некоторыми незначительными изменениями: Внедрение приложения Unity3D в WPF * без * того, чтобы оно занимало все окно

Этот подход работал отлично, нокогда я смотрю на процессы менеджера задач.Имя моего основного исполняемого файла WPF удаляется из процесса, когда я выхожу со страницы, на которой запущен проигрыватель Unity Player, и загружаю другую страницу.Приложение по-прежнему работает просто отлично.Диспетчер задач просто показывает значок без имени процесса рядом с ним.Это только проблема, потому что у меня есть другая фоновая служба, которая контролирует мое приложение WPF и запускает и останавливает его удаленно на основе его имени.Любое предложение?

Код страницы показан ниже.

    public System.Windows.Forms.Integration.WindowsFormsHost host = new System.Windows.Forms.Integration.WindowsFormsHost();
    [DllImport("User32.dll")]
    static extern bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);

    internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);
    [DllImport("user32.dll")]
    internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);

    [DllImport("user32.dll")]
    static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

    private Process process;
    private IntPtr unityHWND = IntPtr.Zero;

    private const int WM_ACTIVATE = 0x0006;
    private readonly IntPtr WA_ACTIVE = new IntPtr(1);
    private readonly IntPtr WA_INACTIVE = new IntPtr(0);
    System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
    bool initialized = false;
    public UnityPlayer()
    {
        InitializeComponent();
        if (this.grid1.Children.Count == 0)
        {
            this.grid1.Children.Add(host);
        }


        dispatcherTimer.Tick += attemptInit;
        dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
        dispatcherTimer.Start();

    }

    void attemptInit(object sender, EventArgs e)
    {
        if (process != null) 
        {
            if (process.HasExited)
            {
                Thread.Sleep(1000);
                FSC.GoHome();
            }

        }

        if (initialized)
            return;

        HwndSource source = (HwndSource)HwndSource.FromVisual(host);

        Console.WriteLine("attempting to get handle...");

        if (source == null)
        {
            Console.WriteLine("Failed to get handle source");
            return;
        }

        IntPtr hWnd = source.Handle;

        try
        {
            process = new Process();
            process.StartInfo.FileName = "Block Breaker.exe";
            process.StartInfo.Arguments = "-parentHWND " + hWnd.ToInt32() + " " + Environment.CommandLine;

            process.StartInfo.UseShellExecute = true;
            process.StartInfo.CreateNoWindow = true;

            process.Start();

            process.WaitForInputIdle();
            // Doesn't work for some reason ?!
            //unityHWND = process.MainWindowHandle;
            EnumChildWindows(host.Handle, WindowEnum, IntPtr.Zero);

            //unityHWNDLabel.Text = "Unity HWND: 0x" + unityHWND.ToString("X8");
            Console.WriteLine("Unity HWND: 0x" + unityHWND.ToString("X8"));

            panel1_Resize(this, EventArgs.Empty);

            initialized = true;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message + ".\nCheck if Container.exe is placed next to UnityGame.exe.");
        }
    }

    private void ActivateUnityWindow()
    {
        SendMessage(unityHWND, WM_ACTIVATE, WA_ACTIVE, IntPtr.Zero);
    }

    private void DeactivateUnityWindow()
    {
        SendMessage(unityHWND, WM_ACTIVATE, WA_INACTIVE, IntPtr.Zero);
    }

    private int WindowEnum(IntPtr hwnd, IntPtr lparam)
    {
        unityHWND = hwnd;
        ActivateUnityWindow();
        return 0;
    }

    private void panel1_Resize(object sender, EventArgs e)
    {
        MoveWindow(unityHWND, 0, 0, (int)host.Width, (int)host.Height, true);
        Console.WriteLine("RESIZED UNITY WINDOW TO: " + (int)host.Width + "x" + (int)host.Height);
        ActivateUnityWindow();
    }


    private void Page_Unloaded(object sender, RoutedEventArgs e)
    {
        dispatcherTimer.Stop();
        dispatcherTimer = null;
        host.Dispose();
    }

Процесс показа изображения до загрузки страниц

Процесс показа изображения во время процессастраница запущена

Процесс показа изображения После выхода из страниц и загрузки новой страницы

...