在 Windows Forms 应用程序(WinForm)中嵌入第三方软件窗体通常涉及使用API函数来获取并操控其他进程的窗口句柄。以下是一种常见的实现方式:

1using System;
2using System.Runtime.InteropServices;
3using System.Windows.Forms;
4
5public class MainForm : Form
6{
7    [DllImport("user32.dll")]
8    static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
9    
10    [DllImport("user32.dll")]
11    static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
12
13    [DllImport("user32.dll")]
14    static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
15
16    const int GWL_HWNDPARENT = -8; // Set parent window flag
17
18    public void EmbedExternalForm(string processName)
19    {
20        Process externalProcess = Process.GetProcessesByName(processName).FirstOrDefault();
21        if (externalProcess != null)
22        {
23            // 获取第三方软件窗体的主窗口句柄
24            IntPtr externalHwnd = externalProcess.MainWindowHandle;
25            
26            // 将外部窗体设为本窗体的子窗口
27            SetParent(externalHwnd, this.Handle);
28
29            // 设置嵌入后窗体的样式,可能需要去掉WS_CAPTION等样式,保持无边框
30            int style = GetWindowLong(externalHwnd, GWL_HWNDPARENT);
31            style &= ~WS_CAPTION; // 去掉标题栏
32            SetWindowLong(externalHwnd, GWL_STYLE, style);
33
34            // 设置嵌入窗体的位置和大小使其适应本窗体内的某个Panel
35            Panel containerPanel = this.flowLayoutPanel1; // 假设有一个Panel用于承载外部窗体
36            MoveWindow(externalHwnd, 0, 0, containerPanel.Width, containerPanel.Height, true);
37        }
38    }
39
40    // 其他相关API声明...
41    [DllImport("user32.dll")]
42    static extern int GetWindowLong(IntPtr hWnd, int nIndex);
43    
44    private const int WS_CAPTION = 0xC00000; // 标题栏样式
45
46    // ...
47}
48
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.

演示了如何查找指定进程名的第三方软件进程,获取其主窗口句柄,并将其嵌入到WinForm应用程序中的一个Panel容器内。请注意,为了使嵌入效果更好,可能还需要调整被嵌入窗体的样式,比如移除边框等非客户区部分。

此外,这种方法存在一定的限制:

  • 第三方软件必须允许其窗体被重新父化,且没有特别的安全措施阻止这种操作。
  • 需要正确处理安全性和权限问题。
  • 对于某些软件,这种方式可能会影响其正常工作或者导致意外行为。

需要注意的是,如果你想要嵌入的是.NET框架下另一个WinForm应用,可能还有更高级的方式,比如使用.NET Remoting、WCF或者托管附加进程(Managed Add-In Framework, MAF)等技术来集成而不是简单地嵌入窗体。而对于非托管的外部程序,上述API调用方式更为常见。

可以参考文章 【C#】在winform中如何实现嵌入第三方软件窗体