gpt4 book ai didi

wpf - 使用 WIn32 SetParent() 在非 WPF 应用程序中托管 WPF 应用程序

转载 作者:可可西里 更新时间:2023-11-01 12:47:39 27 4
gpt4 key购买 nike

我有一个 WPF 应用程序,我希望它看起来像托管在另一个 - 非 WPF - 应用程序中。在现实生活中,这个非 WPF 应用程序是 Internet Explorer 中的一个 ActiveX,但为了说明问题,我使用了一个简单的 Windows 窗体应用程序。

我使用 Windows API 函数 SetParent,它上面已经有几十个线程。但是,我找不到关于我的确切问题的任何内容:WPF 应用程序右侧和底部的一个小区域未在非 WPF 应用程序的窗口内绘制

自己运行的WPF窗口:
alt text

以 WinForm 应用程序窗口为父窗口的 WPF 窗口:
alt text

如果将 WPF 应用程序替换为 WinForms 应用程序或普通 Win32 应用程序(如记事本),我不会遇到此问题。

WinForm 代码如下所示:

private void Form1_Load(object sender, EventArgs e)
{
// Start process
var psi = new ProcessStartInfo("c:\\wpfapp\\wpfapp\\bin\\Debug\\wpfapp.exe");
psi.WindowStyle = ProcessWindowStyle.Normal;
_process = Process.Start(psi);

// Sleep until new process is ready
Thread.Sleep(1000);

// Set new process's parent to this window
SetParent(_process.MainWindowHandle, this.Handle);

// Remove WS_POPUP and add WS_CHILD window style to child window
const int GWL_STYLE = -16;
const long WS_POPUP = 0x80000000;
const long WS_CHILD = 0x40000000;
long style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
style = (style & ~(WS_POPUP)) | WS_CHILD;
SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);

// Move and resize child window to fit into parent's
MoveWindow(_process.MainWindowHandle, 0, 0, this.Width, this.Height, true);
}

注意:我知道这种 SetParent 的使用不一定是推荐的做法,但我想并且需要找出如何这样做,所以请让我 :)

最佳答案

我找到了一个非常有效的解决方法:在 SetParent 之前调用 MoveWindow:

private void Form1_Load(object sender, EventArgs e)
{
// Start process
var psi = new ProcessStartInfo("C:\\WpfApp\\WpfApp.exe");
psi.WindowStyle = ProcessWindowStyle.Normal;
_process = Process.Start(psi);

// Sleep until new process is ready
Thread.Sleep(3000);

// Move and resize child window to fit into parent's
Rectangle rect;
GetClientRect(this.Handle, out rect);
MoveWindow(_process.MainWindowHandle, 0, 0, rect.Right - rect.Left, rect.Bottom - rect.Top, true);

// Set new process's parent to this window
SetParent(_process.MainWindowHandle, this.Handle);

// Remove WS_POPUP and add WS_CHILD window style to child window
long style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
style = (style & ~(WS_POPUP) & ~(WS_CAPTION)) & ~(WS_THICKFRAME) | WS_CHILD;
SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);
}

在 SizeChanged 事件处理程序中,我将子项从父项中取出,调用 MoveWindow 并将其移回父项中。为了减少闪烁,我在执行这些操作时隐藏了窗口:

private void Form1_SizeChanged(object sender, EventArgs e)
{
ShowWindow(_process.MainWindowHandle, SW_HIDE);

var ptr = new IntPtr();
SetParent(_process.MainWindowHandle, ptr);

Rectangle rect;
GetClientRect(this.Handle, out rect);

MoveWindow(_process.MainWindowHandle, 0, 0, rect.Right - rect.Left, rect.Bottom - rect.Top, true);
SetParent(_process.MainWindowHandle, this.Handle);
ShowWindow(_process.MainWindowHandle, SW_SHOW);
}

它没有解释为什么 MoveWindow 在 SetParent 之后不起作用,但它解决了我的问题,所以我将把它标记为答案,除非出现更好的东西。

关于wpf - 使用 WIn32 SetParent() 在非 WPF 应用程序中托管 WPF 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4135891/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com