class NestedHelper : HwndHost, IKeyboardInputSink
{
[DllImport("user32.dll")]
private static extern int SetParent(IntPtr hWndChild, IntPtr hWndParent);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern uint SetWindowLong(IntPtr hwnd, int nIndex, uint newLong);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern uint GetWindowLong(IntPtr hwnd, int nIndex);
[DllImport("user32.dll")]
private static extern int EnumWindows(CallBackPtr callPtr, ref WindowInfo WndInfoRef);
[DllImport("User32.dll")]
static extern int GetWindowText(IntPtr handle, StringBuilder text, int MaxLen);
[DllImport("user32.dll")]
public static extern int GetWindowRect(IntPtr hwnd, ref RECT rc);
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam); //对外部软件窗口发送一些消息(如 窗口最大化、最小化等)
internal const int
GWL_WNDPROC = (-4),
GWL_HINSTANCE = (-6),
GWL_HWNDPARENT = (-8),
GWL_STYLE = (-16),
GWL_EXSTYLE = (-20),
GWL_USERDATA = (-21),
GWL_ID = (-12);
internal const uint
WS_CHILD = 0x40000000,
WS_VISIBLE = 0x10000000,
LBS_NOTIFY = 0x00000001,
HOST_ID = 0x00000002,
LISTBOX_ID = 0x00000001,
WS_VSCROLL = 0x00200000,
WS_BORDER = 0x00800000,
WS_POPUP = 0x80000000;
public const long WS_CATION = 0x00C00000L;
public const long WS_CATION_2 = 0x00C0000L;
private const int HWND_TOP = 0x0;
private const int WM_COMMAND = 0x0112;
private const int WM_QT_PAINT = 0xC2DC;
private const int WM_PAINT = 0x000F;
private const int WM_SIZE = 0x0005;
private const int SWP_FRAMECHANGED = 0x0020;
private const int WM_SYSCOMMAND = 0x0112;
private const int SC_CLOSE = 0xF060;
private const int SC_MINIMIZE = 0xF020;
private const int SC_MAXIMIZE = 0xF030;
private const uint WM_LBUTTONDOWN = 0x0201;
private const uint WM_LBUTTONUP = 0x0202;
private const int BM_CLICK = 0xF5;
private Border WndHoster;
private double screenW, screenH;
private Process appProc;
private uint oldStyle;
public IntPtr hwndHost;
private String appPath;
private String arguments;
public NestedHelper(Border b, String p, String args, String f)
{
WndHoster = b;
appPath = p;
WinInfo = new WindowInfo();
WinInfo.winTitle = f;
this.arguments = args;
}
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
hwndHost = FindTheWindow();
appProc = new Process();
ProcessStartInfo info = new ProcessStartInfo(appPath)
{
UseShellExecute = true,
WindowStyle = ProcessWindowStyle.Minimized,
Arguments = arguments
};
appProc.StartInfo = info;
appProc.Start();
hwndHost = appProc.MainWindowHandle;
while (hwndHost.ToInt32() == 0)
{
Thread.Sleep(1000);
hwndHost = appProc.MainWindowHandle;
}
SendMessage(hwndHost, WM_SYSCOMMAND, SC_MINIMIZE, 0);
// 嵌入在HwnHost中的窗口必须要 设置为WS_CHILD风格
oldStyle = GetWindowLong(hwndHost, GWL_STYLE);
uint newStyle = (uint)(oldStyle & (~(WS_CATION | WS_CATION_2)));//消除白边框
//WS_CHILD和WS_POPUP不能同时存在。
newStyle |= WS_CHILD;
newStyle &= ~WS_POPUP;
newStyle &= ~WS_BORDER;
SetWindowLong(hwndHost, GWL_STYLE, newStyle);
//将窗口居中,实际上是将窗口的容器居中
// RePosWindow(WndHoster, WndHoster.Width, WndHoster.Height);
//将netterm的父窗口设置为HwndHost
SetParent(hwndHost, hwndParent.Handle);
return new HandleRef(this, hwndHost);
}
protected override void DestroyWindowCore(System.Runtime.InteropServices.HandleRef hwnd)
{
SetWindowLong(hwndHost, GWL_STYLE, oldStyle);
SetParent(hwndHost, (IntPtr)0);
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct WindowInfo
{
public String winTitle;
public RECT r;
public IntPtr hwnd;
}
public delegate bool CallBackPtr(IntPtr hwnd, ref WindowInfo WndInfoRef);
private static CallBackPtr callBackPtr;
private WindowInfo WinInfo;
public static bool CallBackProc(IntPtr hwnd, ref WindowInfo WndInfoRef)
{
StringBuilder str = new StringBuilder(512);
GetWindowText(hwnd, str, str.Capacity);
Console.WriteLine(str.ToString());
if (str.ToString().IndexOf(WndInfoRef.winTitle, 0) >= 0)
{
WndInfoRef.hwnd = hwnd;
GetWindowRect(hwnd, ref (WndInfoRef.r));
}
return true;
}
public IntPtr FindTheWindow()
{
callBackPtr = new CallBackPtr(CallBackProc);
EnumWindows(callBackPtr, ref WinInfo);
return WinInfo.hwnd;
}
public void RePosWindow(Border b, double w, double h)
{
double width = WinInfo.r.right - WinInfo.r.left;
double height = WinInfo.r.bottom - WinInfo.r.top;
double left = (w - screenW) / 2;
double right = (w - screenW) / 2;
double top = (h - screenH) / 2;
double bottom = (h - screenH) / 2;
b.Margin = new Thickness(0, 0, 0, 0);
}
}
//自定义UserControl容器
<UserControl x:Class="WpfTest.Godot3dGraph"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfTest"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="600" Loaded="UserControl_Loaded">
<Border x:Name="GodotControl">
</Border>
</UserControl>
/// </summary>
public partial class Godot3dGraph : UserControl
{
public Godot3dGraph(string TAG)
{
InitializeComponent();
string path = @"D:\...\xxx.exe";
//通过ProcessStartInfo传递参数给exe程序,随自己定义
string args = string.Format("--Params={0};{1};{2}", xxxx, TAG, 1001);
NestedHelper ea = new NestedHelper(this.GodotControl, path, args, "Godot3D");
GodotControl.Child = ea;
// WebSocketHelper.Instance.Start(12333);
}
}
主窗口 MainWindow
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTest" x:Class="WpfTest.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="420" Width="800">
<StackPanel Orientation="Horizontal" x:Name="border" Margin="0,0,0,0" >
<!-- 可以xaml添加子控件嵌套
<local:Godot3dGraph Width="400" Height="400" />
<local:Godot3dGraph Width="400" Height="400" />
-->
</StackPanel>
</Window>
public MainWindow()
{
InitializeComponent();
this.WindowState = WindowState.Normal;
// this.ResizeMode = ResizeMode.NoResize;
// this.Topmost = true;
this.Left = 0.0;
this.Top = 0.0;
this.Width = SystemParameters.WorkArea.Width;
this.Height = SystemParameters.WorkArea.Height;
this.Closing += MainWindow_Closing;
//this.WindowStyle = WindowStyle.None;
// AllowsTransparency = true;
//也可以 代码添加子控件嵌入
Godot3dGraph godot = new Godot3dGraph("LEFT");
godot.Width = this.Width / 2;
this.border.Children.Add(godot);
Godot3dGraph godot2 = new Godot3dGraph("RIGHT");
godot2.Width = this.Width / 2;
this.border.Children.Add(godot2);
WSClientHelper.Instance.OpenWS();
}

NestedHelper是参考几个大佬文章写的,也忘了是谁的,如有侵权可联系删除。