C#可以通过windows API,将第三方程序嵌入到panel中,并且可以隐藏程序边框。
问题:
焦点在内部程序时,主窗口失去焦点;
通讯解决方案
使用 User32.dll SendMessage 发送窗口级的 WM_COPYDATA 消息;使用 DefWndProc 处理消息;
来实现两个独立C#程序之间的通讯。
主程序代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Windows.Forms; namespace CallMain { public partial class Form1 : Form { #region 外部DLL定义 [DllImport("User32.dll", EntryPoint = "SetParent")] public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); [DllImport("user32.dll", EntryPoint = "ShowWindow")] public static extern int ShowWindow(IntPtr hwnd, int nCmdShow); [DllImport("user32.dll", SetLastError = true)] public static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint); [DllImport("user32.dll")] public static extern int GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll")] public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); const int WS_THICKFRAME = 262144; const int WS_BORDER = 8388608; const int GWL_STYLE = -16; [DllImport("User32.dll")] public static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wParam, ref COPYDATASTRUCT IParam); public const int WM_COPYDATA = 0x004A; public struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; [MarshalAs(UnmanagedType.LPStr)] public string lpData; } // 发送 windows 消息 public void SendMsg(IntPtr hwnd, string str) { byte[] arr = Encoding.Default.GetBytes(str); int len = arr.Length; COPYDATASTRUCT cdata; cdata.dwData = (IntPtr)100; cdata.lpData = str; cdata.cbData = len + 1; SendMessage(hwnd, WM_COPYDATA, this.Handle, ref cdata); } public delegate void EventMsg(object sender, IntPtr wnd, string str); public event EventMsg OnMsg; // 进程间消息通讯 protected override void DefWndProc(ref Message m) { switch (m.Msg) { case WM_COPYDATA: COPYDATASTRUCT cdata = new COPYDATASTRUCT(); Type mytype = cdata.GetType(); cdata = (COPYDATASTRUCT)m.GetLParam(mytype); OnMsg(this, m.WParam, cdata.lpData); break; default: base.DefWndProc(ref m); break; } } #endregion public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { this.OnMsg += Form1_OnMsg; ; } private void Form1_OnMsg(object sender, IntPtr wnd, string str) { // 接收消息处理 SendMsg(wnd, "收到了子窗口消息:" + str); } private void button1_Click(object sender, EventArgs e) { Process proApp = new Process(); proApp.StartInfo.FileName = Application.StartupPath + "\\CallTest.exe"; proApp.StartInfo.WindowStyle = ProcessWindowStyle.Minimized; proApp.Start(); proApp.WaitForInputIdle(); while (proApp.MainWindowHandle == IntPtr.Zero) { Thread.Sleep(100); proApp.Refresh(); } IntPtr wnd = proApp.MainWindowHandle; Int32 wndStyle = GetWindowLong(wnd, GWL_STYLE); wndStyle &= ~WS_BORDER; wndStyle &= ~WS_THICKFRAME; SetWindowLong(wnd, GWL_STYLE, wndStyle); SetParent(wnd, panel1.Handle); ShowWindow(wnd, (int)ProcessWindowStyle.Maximized); panel1.Tag = proApp; SendMsg(wnd, "hi"); } private void button2_Click(object sender, EventArgs e) { // 给子窗口发消息 Process proApp = (Process)panel1.Tag; SendMsg(proApp.MainWindowHandle, "hello 子窗口"); } } }
子程序通讯代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; namespace CallTest { public partial class Form1 : Form { #region 消息通讯 [DllImport("User32.dll")] public static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wParam, ref COPYDATASTRUCT IParam); const int WM_COPYDATA = 0x004A; public struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; [MarshalAs(UnmanagedType.LPStr)] public string lpData; } private IntPtr MainWnd = IntPtr.Zero; public delegate void EventMsg(object sender, string str); public event EventMsg OnMsg; //发送消息 private void SendMsg(string str) { if (MainWnd == IntPtr.Zero) { return; } byte[] arr = Encoding.Default.GetBytes(str); int len = arr.Length; COPYDATASTRUCT cdata; cdata.dwData = (IntPtr)100; cdata.lpData = str; cdata.cbData = len + 1; SendMessage(MainWnd, WM_COPYDATA, this.Handle, ref cdata); } protected override void DefWndProc(ref Message m) { switch (m.Msg) { case WM_COPYDATA: COPYDATASTRUCT cdata = new COPYDATASTRUCT(); Type mytype = cdata.GetType(); cdata = (COPYDATASTRUCT)m.GetLParam(mytype); MainWnd = m.WParam; OnMsg(this, cdata.lpData); break; default: base.DefWndProc(ref m); break; } } #endregion public Form1() { InitializeComponent(); } private int index = 0; private void button1_Click(object sender, EventArgs e) { // 发送消息 index++; SendMsg("收到啦!" + index); } private void Form1_Load(object sender, EventArgs e) { this.OnMsg += Form1_OnMsg; } private void Form1_OnMsg(object sender, string str) { // 接收消息 if (str == "hi") { SendMsg("hi"); return; } label1.Text = str; label2.Text = MainWnd.ToString("x"); } } }
欢迎转载,转载请注明:转载自[ http://www.cnblogs.com/zjfree/ ]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
2016-11-07 PHP 模拟POST请求
2016-11-07 PHP http 简单用户验证