17

我想将表单附加到另一个窗口(另一个进程)。我尝试通过使用来做到这一点

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

setParentWindow(myWindowHwnd, newParentHwnd);

这样做时,我的形式变得依附,但也是不可见的。问题“附加窗口..”解决了 WPF 窗口的这个问题,基本上是通过使用

HwndSourceParameters parameters = new HwndSourceParameters();
...
HwndSource src = new HwndSource(parameters);

我试图将其转移到我的表格中,但我无法这样做(例如如何处理src.RootVisual = (Visual)window.Content;?->完整来源)。

另一条评论说,我需要修改 windows 样式:

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

在这里我错过了相应的 API,我可以直接从 C# 中完成,还是让我DllImport再次使用另一个?

好或坏 - 不同进程之间的 SetParent() win32 API建议不要在不同进程中附加窗口,但至少我想尝试一下。

问题:

我需要做什么才能使表单窗口可见?如果使用的方法WS_Child是正确的,我将如何设置它?或者WPF 方法是要走的路,但我如何将它应用于 Windows 窗体?

-- 调查结果(后来补充) --

使用 winAPI 修改另一个应用程序的 windows 样式显示如何从 C# / PInvoke 修改样式

在这里找到所有的windows 样式,C# 语法在底部。

-- 与 Alan 讨论的结果 --

我确实在 Win XP 上运行了我的程序以进行交叉检查(请参阅下面 Alan 的回答和评论)。至少我现在确实看到了一些东西。由于我添加了 Alan 示例中的坐标,因此当在左上角附近的另一个窗口上移动时,我的窗口现在在记事本中闪耀。您仍然可以看到在记事本中键入的文本作为覆盖。在 Win 7 (32) 下,我什么也看不到。

  1. 现在我需要找出这是否可以以稳定的方式编写,也出现在 Win 7 上。
  2. 尽管如此,我仍然无法单击表单上的任何按钮,也需要解决。

附在记事本上的 WinXP WinForm

4

2 回答 2

14

这是一个工作示例。托管应用程序是一个简单的 WinForms 应用程序,带有一个空白表单(此处未包括),而“访客应用程序”有一个主表单(包含下面的代码),其中包含一些控件,包括一个测试按钮,用于在更改访客后显示消息表单的父级。

与 OP 问题相关的通常警告也适用于此。

public partial class GuestForm: Form
{
  [DllImport("user32.dll")]
  public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

  [DllImport("user32.dll")]
  public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

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

  public static int GWL_STYLE = -16;
  public static int WS_CHILD = 0x40000000; 

  public GuestForm()
  {
    InitializeComponent();
  }

  private void button1_Click(object sender, EventArgs e)
  {
    MessageBox.Show("done");
  }

  private void button2_Click(object sender, EventArgs e)
  {
    Process hostProcess = Process.GetProcessesByName("HostFormApp").FirstOrDefault();
    if (hostProcess != null)
    {
      Hide();
      FormBorderStyle = FormBorderStyle.None;
      SetBounds(0, 0, 0, 0, BoundsSpecified.Location);

      IntPtr hostHandle = hostProcess.MainWindowHandle;
      IntPtr guestHandle = this.Handle;
      SetWindowLong(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD);
      SetParent(guestHandle, hostHandle);

      Show();
    }
  }
}
于 2012-05-27T12:42:14.797 回答
3

@Horst Walter嘿伙计,我不确定你是否已经解决了这个问题,但我刚刚找到了解决方案..

对我来说,问题是您想要在另一个表单中的主表单的透明度。

只需禁用透明度,它应该可以工作。

于 2017-01-02T08:15:58.147 回答