【问题标题】:showing WPF window from other process in Modal Mode在模态模式下显示来自其他进程的 WPF 窗口
【发布时间】:2025-12-28 08:10:11
【问题描述】:

我有两个 WPF 应用程序和一个进程管理器,它们将数据从第一个 WPF 应用程序传递到第二个 WPF 应用程序,反之亦然。在一个用例中,我必须以模态模式在第二个应用程序的窗口(主窗口)上显示第一个应用程序的窗口(主窗口)。因此,第二个 WPF 应用程序的窗口将被禁用,并在第一个 WPF 应用程序的窗口顶部显示。所需的行为与在单个 WPF 应用程序中以模式模式显示窗口相同。知道如何从另一个 WPF 应用程序访问一个 WPF 应用程序的窗口吗??

对于 Winform 应用程序,我们通过将 Window Handle(intPtr) 传递给另一个应用程序并在模态模式下显示窗口时使用句柄来完成此操作:

System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window)

在 WPF 应用程序的情况下可以实现多类似的事情?提前致谢。

【问题讨论】:

  • 你想要的是this吗?
  • 没有。我的要求不同

标签: wpf


【解决方案1】:

=========================== 开始更新================== ====================

代码:

using System.Windows; // Window, WindowStartupLocation
using System.Windows.Interop; // WindowInteropHelper
using System.Runtime.InteropServices; // DllImport
...

// Instantiate the owned WPF window
CenteredWindow cw = new CenteredWindow();
// Get the handle to the non-WPF owner window
IntPtr hWnd = ...

CenteredWindow cw = new CenteredWindow();

EnableWindow(hWnd, false); // disable parent window
try
{
    // Set the owned WPF window’s owner with the non-WPF owner window
    WindowInteropHelper helper = new WindowInteropHelper(cw);
    helper.Owner = hWnd;
    cw.ShowDialog();
}
finally
{
    EnableWindow(hWnd, true); // enable parent window
}

...
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool EnableWindow(IntPtr hwnd, bool enable);

在 @kamal-nayan 的 cmets 中的 MS Connect Link 的帮助下,我修改了上面的代码,对我来说效果很好。

关键是禁用父窗口,当你的模态对话框关闭时,启用父窗口。

============================ 结束更新================== ====================

using System.Windows; // Window, WindowStartupLocation
using System.Windows.Interop; // WindowInteropHelper
...
// Instantiate the owned WPF window
CenteredWindow cw = new CenteredWindow();

// Get the handle to the non-WPF owner window
IntPtr ownerWindowHandle = ...; // Get hWnd for non-WPF window

// Set the owned WPF window’s owner with the non-WPF owner window
WindowInteropHelper helper = new WindowInteropHelper(cw);
helper.Owner = ownerWindowHandle;
cw.ShowDialog();

这是我找到的唯一解决方案。 它不是真正的 Modal,即您仍然可以激活父窗口,但好在子窗口仍然在父窗口之上。

http://blogs.msdn.com/b/wpfsdk/archive/2007/04/03/centering-wpf-windows-with-wpf-and-non-wpf-owner-windows.aspx

【讨论】:

  • 这不是我想要的。我试过这个,但它不像真正的模态那样工作。我将添加我目前使用的代码来实现这一点。
  • 我会花更多时间来看看它是否有效。我会再试一次。这个链接有更多。它在打开模式模式后禁用父窗口,然后再次启用它。这可能会有所帮助。 connect.microsoft.com/VisualStudio/feedback/details/725866/…
【解决方案2】:
_parameters = new HwndSourceParameters("myWindow");

_parameters.WindowStyle = WindowStyles.WS_SYSMENU | WindowStyles.WS_VISIBLE | WindowStyles.WS_CAPTION | WindowStyles.WS_CHILD | WindowStyles.WS_POPUP;
_parameters.SetPosition(50, 50);

_parameters.ParentWindow = ParentWindowHandle;           
_hwndSource = new HwndSource(_parameters);

_hwndSource.SizeToContent = SizeToContent.WidthAndHeight;
_hwndSource.RootVisual = modalWindowContent;

这就是我能够将来自一个进程的窗口显示为模态到来自另一个进程的窗口的方式。

【讨论】:

  • 谢谢,我稍微修改了你的代码,因为HwndSourceParameters的构造函数需要一个字符串参数。
  • 它对我不起作用,也许我错过了任何东西。将再次调查。
  • 是的,它可能不起作用。它不是直的,特别是分配根视觉。它需要内容。它不接受窗口。它需要很多解决方法。我也在尝试删除这段代码。
  • 更新,在我的测试虚拟机中,您使用 HwndSourceParameters 的代码与使用 WindowInteropHelper 的代码相同。我想我可能需要设置一些窗口样式或前样式,不确定。由于 winform one 有效,因此在技术上是可行的。另一种可能的解决方案是在托管 WPF 用户控件的 WinForm 中使用 ElementHost。
  • 您的 ms 连接链接很有帮助,我已经更新了我的代码,它现在对我有用,请参阅我的更新。