将表单窗口附加到 C# 中的另一个窗口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10773003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Attach form window to another window in C#
提问by Horst Walter
I want to attach a form to another window (of another process). I try to do this by using
我想将表单附加到另一个窗口(另一个进程)。我尝试通过使用来做到这一点
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
setParentWindow(myWindowHwnd, newParentHwnd);
In doing so my form becomes attached, but is also invisible. Question "Attach window .."solves this issue for a WPF Window, basically by using
这样做时,我的形式变得依附,但也是隐形的。问题“附加窗口..”解决了 WPF 窗口的这个问题,基本上是通过使用
HwndSourceParameters parameters = new HwndSourceParameters();
...
HwndSource src = new HwndSource(parameters);
I have tried to transfer this to my form, but I am unable to do so (e.g. how to handle src.RootVisual = (Visual)window.Content;? -> Complete source).
我试图将其转移到我的表单中,但我无法这样做(例如如何处理src.RootVisual = (Visual)window.Content;?->完整源代码)。
Another commentsays, I need to modify the windows style:
另一条评论说,我需要修改 windows 样式:
For compatibility reasons, SetParent does not modify the WS_CHILD or WS_POPUP window styles of the window whose parent is being changed. Therefore, if hWndNewParent is NULL, you should also clear the WS_CHILD bit and set the WS_POPUP style after calling SetParent. Conversely, if hWndNewParent is not NULL and the window was previously a child of the desktop, you should clear the WS_POPUP style and set the WS_CHILD style before calling SetParent.
出于兼容性原因,SetParent 不会修改正在更改其父级的窗口的 WS_CHILD 或 WS_POPUP 窗口样式。因此,如果 hWndNewParent 为 NULL,您还应该在调用 SetParent 后清除 WS_CHILD 位并设置 WS_POPUP 样式。相反,如果 hWndNewParent 不为 NULL 并且窗口以前是桌面的子窗口,则应在调用 SetParent 之前清除 WS_POPUP 样式并设置 WS_CHILD 样式。
Here I miss the corresponding API for doing so, can I do it directly from C# or have I to use another DllImportagain?
在这里,我错过了相应的 API,我可以直接从 C# 中完成,还是必须DllImport再次使用另一个?
Good or evil - SetParent() win32 API between different processesadvises against attaching windows in different processes at all, but at least I want to try.
好或坏 - 不同进程之间的 SetParent() win32 API建议根本不要在不同进程中附加窗口,但至少我想尝试一下。
Question:
题:
What would I need to do to get the form window visible? If the approach with WS_Childis the correct one, how would I set it? Or is the WPF approachthe way to go, but how would I apply it to an windows form?
我需要做什么才能使表单窗口可见?如果方法WS_Child正确,我将如何设置它?或者WPF 方法是要走的路,但我如何将它应用于 Windows 窗体?
-- Findings (later added) --
——调查结果(后来补充)——
Modify the windows style of another application using winAPIshows how to modify the style from C# / PInvoke
使用 winAPI修改另一个应用程序的窗口样式显示了如何从 C#/PInvoke 修改样式
Find all windows styleshere, C# syntax at the bottom.
在此处找到所有窗口样式,在底部找到C# 语法。
-- Findings due to discussion with Alan --
-- 与艾伦讨论的结果 --
I did run my program on Win XP to crosscheck (see Alan's answer below and the comments). At least I do now see something. Since I have added the coordinates as of Alan's examples, my window now shines through in notepad when moving over the other window near the left upper corner. You can still see the text typed in notepad as overlay. Under Win 7 (32) I do see nothing at all.
我确实在 Win XP 上运行了我的程序以进行交叉检查(请参阅下面 Alan 的回答和评论)。至少我现在确实看到了一些东西。由于我已经添加了 Alan 示例中的坐标,因此当移动到靠近左上角的另一个窗口时,我的窗口现在会在记事本中透出。您仍然可以看到在记事本中键入的文本作为覆盖。在 Win 7 (32) 下,我什么也看不到。
- Now I need to find out whether this can be written in a stable way, appearing on Win 7 as well.
- Nevertheless, I still cannot click any buttons on my form, needs to be solved too.
- 现在我需要找出这是否可以以稳定的方式编写,是否也出现在 Win 7 上。
- 尽管如此,我仍然无法点击表单上的任何按钮,也需要解决。


采纳答案by Alan
Here is a working example. The hosting app is a simple WinForms application with a blank form (not included here), while the "guest app" has a main form (code behind included below) with some controls, including a test button to display a message after changing the guest form's parent.
这是一个工作示例。托管应用程序是一个简单的 WinForms 应用程序,带有一个空白表单(此处不包括在内),而“访客应用程序”有一个主表单(包含下面的代码)和一些控件,包括一个测试按钮,用于在更改访客后显示消息表单的父级。
The usual caveats linked to in the OP's question apply to this, too.
与 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();
}
}
}
回答by Red Fane
@Horst Walter Hey man, I'm not sure if you've fixed the issue, but I just found a solution to this..
@Horst Walter 嘿伙计,我不确定你是否已经解决了这个问题,但我刚刚找到了一个解决方案..
For me the issue was the transparency of the main form you want inside the other form.
对我来说,问题是您想要在另一个表单中的主表单的透明度。
Just disable transparency and it should work.
只需禁用透明度,它应该可以工作。

