将Unity3D应用程序嵌入WPF *,而 * 不会占据整个窗口

您所在的位置:网站首页 unity3d控件嵌入winform 将Unity3D应用程序嵌入WPF *,而 * 不会占据整个窗口

将Unity3D应用程序嵌入WPF *,而 * 不会占据整个窗口

2023-03-22 05:53| 来源: 网络整理| 查看: 265

上述解决方案的问题是将焦点放在Unity-exe上似乎是不可能的。所以,是的,我能够在某个WPF应用程序的某个用户控件的某个单元格上加载exe,但不能单击Unity-frame中的任何内容。我花了一整天寻找解决方案,现在可以来一个解决方案,这是在我看来更清洁,也解决了问题的重点。我将分步骤描述您可以做的事情:

Documentation of Unity:这里解释了如何在Winforms控件中嵌入Unity-exe。甚至还有一个. zip文件“EmbeddedWindow.zip“,您可以在其中下载示例代码。将基本文件从容器x1c 0d1x中复制出来。Form1.cs包含的代码与this question中的完全相同。public partial class Form1: Form { [DllImport("User32.dll")] private 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")] private 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); public Form1() { InitializeComponent(); TopLevel = false; try { process = new Process(); process.StartInfo.FileName = "[INSERT_FILE_NAME_OF_YOUR_EXE].exe"; process.StartInfo.Arguments = "-parentHWND " + panel1.Handle.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(panel1.Handle, WindowEnum, IntPtr.Zero); unityHWNDLabel.Text = "Unity HWND: 0x" + unityHWND.ToString("X8"); } catch (Exception ex) { MessageBox.Show(ex.Message + ".\nCheck if Container.exe is placed next to Child.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, panel1.Width, panel1.Height, true); ActivateUnityWindow(); } // Close Unity application private void Form1_FormClosed(object sender, FormClosedEventArgs e) { try { process.CloseMainWindow(); Thread.Sleep(1000); while (process.HasExited == false) process.Kill(); } catch (Exception) { } } private void Form1_Activated(object sender, EventArgs e) { ActivateUnityWindow(); } private void Form1_Deactivate(object sender, EventArgs e) { DeactivateUnityWindow(); } }

1.不要忘记在“Form1.cs”中查看,有可能您要更新的exe不是“Child.exe”,因此如果它是另一个,只需编辑代码中的字符串。process.StartInfo.FileName = "[INSERT_FILE_NAME_OF_YOUR_EXE].exe";还检查“SelectablePanel.cs”,其中Selectable设置为true是必不可少的。此SelectablePanel用于Form1.Designer.cs。

SplitContainer的左面板1是SelectablePanel而不是Panel!

class SelectablePanel : Panel { public SelectablePanel() { this.SetStyle(ControlStyles.Selectable, true); this.TabStop = true; } }

还请注意,在Winforms-control的构造函数中,我需要设置Toplevel = false;。Unity的示例中没有提到这一点,但在将其嵌入WPF应用程序时需要避免异常。1.转到您的WPF应用程序并创建一个将包含Winforms-Control的用户控件。创建一个类似于this link中所做的控件。在此示例中,您有一个名为Grid_To_Embed_Winforms_Control_In的网格和一小段代码隐藏,如基础代码。

public partial class WPF_User_Control: UserControl { public bool Already_Loaded = false; public WPF_User_Control() { InitializeComponent(); } private void On_Load(object sender, RoutedEventArgs e) { if (!Already_Loaded) { // Create the interop host control. var host = new WindowsFormsHost(); // Embed the Winforms Control host.Child = new Embed_Unity_Exe_Winforms_Control(); // Add the interop host control to the Grid // control's collection of child controls. Grid_To_Embed_Winforms_Control_In.Children.Add(host); Already_Loaded = true; } } }

1.不要忘记在顶部添加using System.Windows.Forms.Integration;。请注意,我添加boolean Already Loaded是为了确保当视口发生变化(您希望查看WPF应用程序的另一个页面)时,进程不会再次启动。在我的完整解决方案中,我使用了Microsoft Dependency Injection,并且此控件位于作为单例添加的视图模型中。这样,我只启动进程一次。就是这样,这对我很有效.什么是优于其他解决方案,我看到,而谷歌:

调整大小的效果更好,而且是“自动”完成的,我不需要自己调用resize方法(除了Form1.cs中的方法)。我也可以控制和专注于统一。

PS:如果你想让它看起来更漂亮,更“嵌入”,你可以用Winform控件做以下事情:

选择splitcontainer 1并转到“属性将BorderStyle设置为“无”将Panel 2Collapsed设置为“True”


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3