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");
            }
        }
    }
  • 相关阅读:
    iOS Simulator功能介绍关于Xamarin IOS开发
    Unity中制作游戏的快照游戏支持玩家拍快照
    手机数据抓包入门教程
    Swift语言中为外部参数设置默认值可变参数常量参数变量参数输入输出参数
    Hierarchy视图里的Transform和Camera组件
    用JAVA编写MP3解码器——GUI(FFT)(转)
    功率W与dBm的对照表及关系(转)
    单鞭天线的长度计算方法(转)
    STM32F10X SPI操作flash MX25L64读写数据(转)
    利用STM32F唯一96bit序列号实现反拷贝加密的源代码公开(转)
  • 原文地址:https://www.cnblogs.com/zjfree/p/11811263.html
Copyright © 2011-2022 走看看