没有办法按照我的要求去做。但我们找到了一个转机。“简单地”将 xaml 窗口嵌入 Windows 窗体中。
这些是我们遵循的步骤:
1 - 将 Windows 窗体添加到项目中。
2 - 删除 app.xaml 并使新表单成为应用程序的入口点。
3 - 由于我们需要 main.xaml 的 hwnd,因此我们将此道具添加到其代码后面
public IntPtr Hwnd
{
get { return new WindowInteropHelper(this).Handle; }
}
4 - 然后从窗体的构造函数中创建 wpf 窗口类的实例
private Main app;
public ContainerForm()
{
InitializeComponent();
app = new Main();
ElementHost.EnableModelessKeyboardInterop(app);
}
我们需要
ElementHost.EnableModelessKeyboardInterop(app);
因为我们希望所有键盘输入都从 windows 窗体传递到 xaml 窗口
5 - 现在我们要将 xpf 窗口绑定到 winform。为了做到这一点,我们需要使用 Windows Api,并且我们在表单的 OnShow 事件中执行此操作(原因将在后面解释)。
[DllImport("user32.dll", SetLastError = true)]
private static extern long SetFocus(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
private static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
private const int GWL_STYLE = (-16);
private const int WS_VISIBLE = 0x10000000;
private void ContainerForm_Shown(object sender, EventArgs e)
{
app.Show();
SetParent(app.Hwnd, this.Handle);
SetWindowLong(app.Hwnd, GWL_STYLE, WS_VISIBLE);
MoveWindow(app.Hwnd, 0, 0, this.Width, this.Height, true);
SetFocus(app.Hwnd);
}
和
SetParent(app.Hwnd, this.Handle);
wo做魔术,然后用
SetWindowLong(app.Hwnd, GWL_STYLE, WS_VISIBLE);
我们从 wpf 窗口中删除所有 chrome(即使窗口定义为无边框,也有边框,不要问我为什么)
然后我们让wpf窗口填满winform的所有客户区
MoveWindow(app.Hwnd, 0, 0, this.Width, this.Height, true);
然后我们聚焦 wpf 窗口
SetFocus(app.Hwnd);
这就是我们在演出活动中做所有事情的原因。因为如果我们在窗体的构造函数中执行此操作,则 wpf 窗口将失去其焦点,因为在 winform 中,主窗口从操作系统获得了焦点。
我们不明白为什么此时我们需要添加其他 api 调用,但是如果我们将它们留在构造函数中,那么这个技巧就不起作用了。
无论如何,问题解决了;)