WPF应用程序中的嵌入式Unity3D - > SetWindowLong问题

时间:2017-03-29 09:54:28

标签: c# wpf unity3d styles host

我正在WPF中开发一个承载Unity应用程序的应用程序。 这个托管是通过使用HwndHost类来设置的(因为与_hwndparent参数的统一方式似乎没有(t工作)。

在我的HwndHost类的BuilWindowCore中,我需要使用GetWindowLong和SetWindowLong更改窗口子样式。

所有这些都完美适用于我的计算机。但我无法在另一台计算机上使用该应用程序。

当我只设置WS_CCHILD值(没有使用GetWindowLong检索样式)时,所有计算机上都没有崩溃,但是子应用程序没有正确显示(最大化等等)。这就是为什么我认为这个问题与造型子窗口部分有关。

有我的HwndHost类代码:

public class UnityHwndHost : HwndHost
{
    private Process _process;
    private HandleRef _hwnd;
    private IntPtr _unityHWND; // = IntPtr.Zero;

    private const int GWL_STYLE = -16;

    // Window Styles 
    const UInt32 WS_OVERLAPPED = 0;
    const UInt32 WS_POPUP = 0x80000000;
    const UInt32 WS_CHILD = 0x40000000;
    const UInt32 WS_MINIMIZE = 0x20000000;
    const UInt32 WS_VISIBLE = 0x10000000;
    const UInt32 WS_DISABLED = 0x8000000;
    const UInt32 WS_CLIPSIBLINGS = 0x4000000;
    const UInt32 WS_CLIPCHILDREN = 0x2000000;
    const UInt32 WS_MAXIMIZE = 0x1000000;
    const UInt32 WS_CAPTION = 0xC00000;      // WS_BORDER or WS_DLGFRAME  
    const UInt32 WS_BORDER = 0x800000;
    const UInt32 WS_DLGFRAME = 0x400000;
    const UInt32 WS_VSCROLL = 0x200000;
    const UInt32 WS_HSCROLL = 0x100000;
    const UInt32 WS_SYSMENU = 0x80000;
    const UInt32 WS_THICKFRAME = 0x40000;
    const UInt32 WS_GROUP = 0x20000;
    const UInt32 WS_TABSTOP = 0x10000;
    const UInt32 WS_MINIMIZEBOX = 0x20000;
    const UInt32 WS_MAXIMIZEBOX = 0x10000;
    const UInt32 WS_TILED = WS_OVERLAPPED;
    const UInt32 WS_ICONIC = WS_MINIMIZE;
    const UInt32 WS_SIZEBOX = WS_THICKFRAME;

    // Extended Window Styles 
    const UInt32 WS_EX_DLGMODALFRAME = 0x0001;
    const UInt32 WS_EX_NOPARENTNOTIFY = 0x0004;
    const UInt32 WS_EX_TOPMOST = 0x0008;
    const UInt32 WS_EX_ACCEPTFILES = 0x0010;
    const UInt32 WS_EX_TRANSPARENT = 0x0020;
    const UInt32 WS_EX_MDICHILD = 0x0040;
    const UInt32 WS_EX_TOOLWINDOW = 0x0080;
    const UInt32 WS_EX_WINDOWEDGE = 0x0100;
    const UInt32 WS_EX_CLIENTEDGE = 0x0200;
    const UInt32 WS_EX_CONTEXTHELP = 0x0400;
    const UInt32 WS_EX_RIGHT = 0x1000;
    const UInt32 WS_EX_LEFT = 0x0000;
    const UInt32 WS_EX_RTLREADING = 0x2000;
    const UInt32 WS_EX_LTRREADING = 0x0000;
    const UInt32 WS_EX_LEFTSCROLLBAR = 0x4000;
    const UInt32 WS_EX_RIGHTSCROLLBAR = 0x0000;
    const UInt32 WS_EX_CONTROLPARENT = 0x10000;
    const UInt32 WS_EX_STATICEDGE = 0x20000;
    const UInt32 WS_EX_APPWINDOW = 0x40000;
    const UInt32 WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
    const UInt32 WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
    const UInt32 WS_EX_LAYERED = 0x00080000;
    const UInt32 WS_EX_NOINHERITLAYOUT = 0x00100000; // Disable inheritence of mirroring by children
    const UInt32 WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring
    const UInt32 WS_EX_COMPOSITED = 0x02000000;
    const UInt32 WS_EX_NOACTIVATE = 0x08000000;


    private const int WM_ACTIVATE = 0x0006;
    private readonly IntPtr WA_ACTIVE = new IntPtr(1);
    private readonly IntPtr WA_INACTIVE = new IntPtr(0);

    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, UInt32 dwNewLong);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32")]
    private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent);

    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);

    [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
    public static extern bool IsWindow(IntPtr hWnd);

    #region CONSTRUCTORS
    #endregion

    #region METHODS
    protected override HandleRef BuildWindowCore(HandleRef hwndParent)
    {
        var context = DataContext as UltrasoundVM;
        var psi = new ProcessStartInfo("UnityStandAlone.exe");

        psi.Arguments = "\"" + context.Workspace.Replace('\\', '/') + "\" " + context.SelectedFlexible;
        LoggerHelper.Write(GetType().FullName + "." + new StackTrace().GetFrame(0).GetMethod().Name + " : " + psi.Arguments, EventLogEntryType.Information);
        psi.WindowStyle = ProcessWindowStyle.Minimized;

        _process = Process.Start(psi);
        _process.WaitForInputIdle();
        while (_process.MainWindowHandle == IntPtr.Zero || !IsWindow(_process.MainWindowHandle))
        {
            Thread.Yield();
        }
        _unityHWND = _process.MainWindowHandle;
        SetParent(_unityHWND, hwndParent.Handle);

        var style = GetWindowLong(_unityHWND, GWL_STYLE);
        style = style & ~WS_CAPTION & ~WS_THICKFRAME; // Removes Caption bar and the sizing border
        style |= (WS_CHILD); // Must be a child window to be hosted
        SetWindowLong(_unityHWND, GWL_STYLE, style);

        SetWindowLong(_unityHWND, GWL_STYLE, WS_CHILD | WS_MAXIMIZE);

        SendMessage(_unityHWND, WM_ACTIVATE, WA_ACTIVE, IntPtr.Zero);

        _hwnd = new HandleRef(this, _unityHWND);
        return _hwnd;
    }

    protected override void DestroyWindowCore(HandleRef hwnd)
    {
        SendMessage(_hwnd.Handle, WM_ACTIVATE, WA_INACTIVE, IntPtr.Zero);

        _process.CloseMainWindow();

        _process.WaitForExit(5000);

        if (_process.HasExited == false)
        {
            _process.Kill();
        }

        _process.Close();
        _process.Dispose();
        _process = null;
    }
    #endregion   
}

备注:

开发计算机 - 操作系统:Windows 10 Home Edition - Unity 3D 5.5.2.f.1免费版

测试计算机 - 操作系统:Windows 10(家庭版和专业版)

当然,我尝试使用不同的参数构建Unity应用程序,与我的父应用程序相同。

1 个答案:

答案 0 :(得分:0)

似乎问题来自我的统一立场,这在我的源和我的调试文件夹之间是不一样的。