zoukankan      html  css  js  c++  java
  • C# 嵌入第三方EXE界面到panel中,并相互通讯

    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");
            }
        }
    }
  • 相关阅读:
    .NetCore Grpc 客服端 工厂模式配置授权
    DOCKER 拉取 dotnet 镜像太慢 docker pull mcr.microsoft.com too slow
    Introducing .NET 5
    VSCode 出现错误 System.IO.IOException: The configured user limit (128) on the number of inotify instances has been reached.
    Omnisharp VsCode Attaching to remote processes
    zookeeper3.5.5 centos7 完全分布式 搭建随记
    Hadoop2.7.7 centos7 完全分布式 配置与问题随记
    MySQL索引 索引分类 最左前缀原则 覆盖索引 索引下推 联合索引顺序
    SQL基础随记3 范式 键
    MySQL调优 优化需要考虑哪些方面
  • 原文地址:https://www.cnblogs.com/zjfree/p/11811263.html
Copyright © 2011-2022 走看看