【问题标题】:Attach window to window of another process将窗口附加到另一个进程的窗口
【发布时间】:2012-05-20 19:50:08
【问题描述】:

我的 WPF 应用程序有多个窗口,我想将其中一些窗口附加到另一个进程的窗口。我的问题是,一旦我附加了我的窗口,它就会变得不可见。

我正在尝试使用以下代码:

public static bool setParentWindow(IntPtr hWndChild, IntPtr hWndNewParent)
    {
    IntPtr previousParent = SetParent(hWndChild, hWndNewParent);
    return (previousParent == null ? false : true);
}

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

setParentWindow(myWindowHwnd, newParentHwnd);

所以,上面的代码成功地附加了窗口,但不幸的是使它不可见。

我这样做的原因是我试图通过为它构建“小部件”来扩展应用程序,我的小部件将挂钩并向用户显示额外信息。

两个窗口都有以下样式:WS_OVERLAPPEDWINDOW、WS_OVERLAPPED、WS_VISIBLE、WS_CLIPSIBLINGS、WS_CLIPCHILDREN。

【问题讨论】:

  • 附加窗口是什么意思?涉及到的窗口有哪些窗口样式?
  • @Neil:我已将样式添加到问题的末尾,通过附加我的意思是我希望我的 WPF 窗口成为新窗口的子窗口。
  • 将窗口重新设置为其他进程非常困难。我会推荐一个不同的解决方案。
  • @DavidHeffernan:我的窗口要么是孩子,要么只是(对用户)看起来是孩子。反正你知道做后者吗?
  • 您可以控制其他应用程序吗?如果是这样,则在该其他应用程序中进行编码。如果不是,那么是什么让您认为您可以将另一个进程窗口和一个 WPF 窗口推送到另一个应用程序中?

标签: c# wpf


【解决方案1】:

我发现即使不使用 setParent 调用也可以做到这一点。我使用 HwndSource 类如下:

MyWindow window = new MyWindow();
window.ShowActivated = true;

HwndSourceParameters parameters = new HwndSourceParameters();

parameters.WindowStyle = 0x10000000 | 0x40000000;
parameters.SetPosition(0, 0);
parameters.SetSize((int)window.Width, (int)window.Height);
parameters.ParentWindow = newParent;
parameters.UsesPerPixelOpacity = true;
HwndSource src = new HwndSource(parameters);

src.CompositionTarget.BackgroundColor = Colors.Transparent;
src.RootVisual = (Visual)window.Content;

现在运行良好,没有任何问题。

【讨论】:

  • 嗨@Gerve。你的例子是我能找到的唯一例子,但它对我不起作用。 Spy++ 告诉我,就我而言,MyWindow 不是 newParent 的孩子。我的问题是:a) 您在 MyWindow.xaml 中为 MyWindow 的 WindowStyle、AllowsTransparency 和 Background 属性设置了哪些值? b) 你在窗口上调用 Show() 吗?如果是这样,您在上述代码之前还是之后执行它是否重要? c)就我而言,MyWindow 获得了 WS_EX_LAYERED 扩展样式,我读到的样式与子窗口不兼容。不知道为什么。 d) 您是否使用 SetWindowLong() 设置任何其他样式?
  • 我的 WPF 窗口始终为黑色背景(无论我将其背景颜色设置为透明(并允许透明)还是某种颜色)...
【解决方案2】:

我不确定您需要对重叠的窗口做什么,但来自 MSDN:

出于兼容性原因,SetParent 不会修改父正在更改的窗口的 WS_CHILDWS_POPUP 窗口样式。因此,如果 hWndNewParentNULL,还应在调用 WS_CHILD 位并设置 WS_POPUP 样式强>SetParent。相反,如果 hWndNewParent 不是 NULL 并且窗口以前是桌面的子窗口,则应清除 WS_POPUP 样式并设置 WS_CHILD 调用 SetParent 之前的样式。

【讨论】:

    【解决方案3】:
    private void TryToAttach(IntPtr ownerHandle)
    {
        if(ownerHandle == IntPtr.Zero)
        {
            return;
        }
        try
        {
            var helper = new WindowInteropHelper(window) { Owner = ownerHandle };
        }
        catch(Exception e)
        {
            Logger.Error(e, "Could not attach window.");
        }
    }
    

    【讨论】:

    • 虽然这可以回答问题,但它没有提供任何上下文来解释如何或为什么。考虑添加一两句话来解释你的答案。
    • WindowInteropHelper 是 System.Windows.Interop 命名空间中的类。协助 Windows Presentation Foundation (WPF) 和 Win32 代码之间的互操作。
    • 我很高兴看到您正在尝试改进您的答案,通常您应该通过编辑而不是在 cmets 中添加类似的说明。评论可能会被清理掉,但并不是每个人都会阅读它们,因此您的说明可能会被遗漏。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多