将表单窗口附加到C#中的另一个窗口

时间:2012-05-27 09:40:06

标签: c# winforms pinvoke

我想将表单附加到另一个窗口(另一个进程)。我尝试使用

来做到这一点
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

setParentWindow(myWindowHwnd, newParentHwnd);

这样做我的表单会附加,但也不可见。问题"Attach window .."基本上通过使用

解决了WPF窗口的这个问题
HwndSourceParameters parameters = new HwndSourceParameters();
...
HwndSource src = new HwndSource(parameters);

我已尝试将此格式转移到我的表单中,但我无法将其转移(例如如何处理src.RootVisual = (Visual)window.Content;? - > Complete source)。

Another comment说,我需要修改windows样式:

  

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

我在这里错过了相应的API,我可以直接从C#中执行此操作,还是让我再次使用其他DllImport

Good or evil - SetParent() win32 API between different processes建议不要在不同的进程中附加窗口,但至少我想尝试。

问题:

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

- 调查结果(后来添加) -

Modify the windows style of another application using winAPI显示了如何从C#/ PInvoke

修改样式

在此处查找所有windows styles,在底部找到C#语法。

- 与Alan讨论的结果 -

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

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

2 个答案:

答案 0 :(得分: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();
    }
  }
}

答案 1 :(得分:3)

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

对我来说,问题是你想要在另一种形式中使用的主要形式的透明度。

只需禁用透明度即可。