Unity 通过winAPI与Winform程序发消息(HoneyWell视频)

需求:通过Unity启动外部的一个winform程序,传参数进行初始化。   程序启动后,untiy通过winApi给启动的程序发消息。

unity调用HoneyWellSDK显示视频,关闭的时候藏至后台。(后续发现,honeywell能通过Rtsp的方式,直接调用视频)

Untiy端:

    Process myprocess;//摄像头程序进程
    public const int WM_COPYDATA = 0x004A; //进程发送信息标识,之前用别的不行,用这个winform才接收到消息

    public string HoneyWellWindowName = "HoneyWellVideoMonitor";

    ///


    /// 创建新进程
    ///

    ///
    ///
    private void CreateNewProcess(string args,string fileName="")
    {
        if(string.IsNullOrEmpty(fileName))
        {
            if (IsSDKInit) return;           
            fileName = Application.dataPath + "\\..\\release\\HUSSDKDemo.exe";
            if (!File.Exists(fileName))
            {
                UnityEngine.Debug.LogErrorFormat("path:{0} not exist!", fileName);
                return;
            }
            IsSDKInit = true;
        }       
        myprocess = new Process();
        ProcessStartInfo startInfo = new ProcessStartInfo(fileName, args);
        myprocess.StartInfo = startInfo;
        myprocess.StartInfo.UseShellExecute = false;
        myprocess.Start();
    }

    ///


    /// 开启视屏程序
    ///

    ///
    ///
    private void StartProcess(string args)
    {
        try
        {
            string fileName = Application.dataPath + "\\..\\release\\HUSSDKDemo.exe";
            if (!File.Exists(fileName))
            {
                UnityEngine.Debug.LogErrorFormat("path:{0} not exist!", fileName);
            }
            if (myprocess == null)
            {
                UnityEngine.Debug.LogError("create myprocess.StartInfo");
                CreateNewProcess(args,fileName);
            }
            else if (myprocess.HasExited)
            {
                UnityEngine.Debug.LogError("Camera:myprocess.HasExited");
                CreateNewProcess(args,fileName);
            }
            else
            {

                //这一部分,好像没有作用。根据名称找窗口,还是为0
                IntPtr hWnd = myprocess.MainWindowHandle; //获取Form1.exe主窗口句柄
                int pId = -1;
                if (hWnd.ToInt32() == 0)
                {

                    //HoneyWellWindowName = "HoneyWellVideoMonitor"; 窗体名为中文时,找不到。改成英文可以
                    pId = FindWindow(null, HoneyWellWindowName);                    
                }
                else
                {
                    pId = hWnd.ToInt32();
                }
                string sendString = args;
                byte[] sarr = System.Text.Encoding.Default.GetBytes(sendString);
                int len = sarr.Length;
                COPYDATASTRUCT cds;
                cds.dwData = (IntPtr)0;
                cds.cbData = len + 1;
                cds.lpData = sendString;
                ThreadManager.Run(()=> 
                {
                    //下方pid为0的情况,所有程序的 DefWndProc方法,都能接收到Untiy发的信息,这也是需要优化的地方

                     SendMessage(pId, WM_COPYDATA, 0, ref cds); //SendMessage是同步的,考虑放在线程里,防止卡住主线程

                     //想用PostMessage的方式,异步发送消息。但是测试没成功,后续得再调整

                },()=> 
                {
                    UnityEngine.Debug.LogError("Show camera:" + args);
                },"");             
            }           
        }
        catch (Exception ex)
        {
            UnityEngine.Debug.LogError("Error : CameraVideoManage.StartProcess:" + ex.Message);
        }
    }
    private void OnDestroy()
    {

        //winform关闭时,拦截了关闭消息。默认让它隐藏在后台,所以关闭untiy时,通过进程把程序关了。
        if (myprocess != null) myprocess.CloseMainWindow();  //程序关闭识,把进程关闭。不然再打开程序,会有多个视频进程
    }
    #region WinAPI

    [DllImport("User32.dll", EntryPoint = "FindWindow")]
    private static extern int FindWindow(string lpClassName, string lpWindowName);

    ///


    /// 根据句柄查找进程ID
    ///

    ///
    ///
    ///
    [System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);


    ///


    /// 使用COPYDATASTRUCT来传递字符串
    ///

    [StructLayout(LayoutKind.Sequential)]
    public struct COPYDATASTRUCT
    {
        public IntPtr dwData;
        public int cbData;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpData;
    }

    //消息发送API
    [DllImport("User32.dll", EntryPoint = "SendMessage")]
    public static extern int SendMessage(
        IntPtr hWnd,        // 信息发往的窗口的句柄
        int Msg,            // 消息ID
        int wParam,         // 参数1
        int lParam          //参数2
    );

    //消息发送API
    [DllImport("User32.dll", EntryPoint = "SendMessage")]
    public static extern int SendMessage(
        int hWnd,        // 信息发往的窗口的句柄
        int Msg,            // 消息ID
        int wParam,         // 参数1
        ref COPYDATASTRUCT lParam  //参数2
    );

    //消息发送API
    [DllImport("User32.dll", EntryPoint = "PostMessage")]
    public static extern int PostMessage(
        IntPtr hWnd,        // 信息发往的窗口的句柄
        int Msg,            // 消息ID
        int wParam,         // 参数1
        int lParam            // 参数2
    );


    //异步消息发送API
    [DllImport("User32.dll", EntryPoint = "PostMessage")]
    public static extern int PostMessage(
        int hWnd,        // 信息发往的窗口的句柄
        int Msg,            // 消息ID
        int wParam,         // 参数1
        ref COPYDATASTRUCT lParam  // 参数2
    );


    #endregion

 

 

WinFrom端:

程序启动入口,通过unity打开程序,能够收到传递的参数:

static class Program
    {
        ///


        /// The main entry point for the application.
        ///

        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            ShowLog(args);
        }
        static void ShowLog(string[] args)
        {
            args = new string[] {"192.168.1.1|admin|admin|dddddd" };
            if (args.Length <= 0)
            {
                Application.Run(new Form_SDKDemo());
            }
            if (args.Length == 1)
            {
                //MessageBox.Show("成功启动,参数为" + args.ToString());
                SingleLiveForm form = new SingleLiveForm(args);
                Application.Run(form);
            }
        }
    }

功能界面:SingleLiveForm  只放部分用到的代码

 ///


        /// 使用COPYDATASTRUCT来传递字符串
        ///

        [StructLayout(LayoutKind.Sequential)]
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
        }

 

        private static int WMA_InterPro = 0x004A;
        protected override void DefWndProc(ref Message m)
        {
            if (m.Msg == WMA_InterPro)
            {
                COPYDATASTRUCT cds = new COPYDATASTRUCT();
                Type t = cds.GetType();
                cds = (COPYDATASTRUCT)m.GetLParam(t);
                string receiveInfo = cds.lpData;
                this.Show();
                this.ShowInTaskbar = true;
                string[] values = receiveInfo.Split('|');
                if (values.Length < 4)
                {
                    return;
                }
                string devGuid = values[3];
                ShowVideo(devGuid);
            }
            else
            {
                base.DefWndProc(ref m);
            }
        }

 

 private void SingleLiveForm_FormClosing(object sender, FormClosingEventArgs e)
        {

            //取消关闭窗口 ,隐藏至后台
            e.Cancel = true; 
            this.Hide();   
            this.ShowInTaskbar = false;
        }

 

你可能感兴趣的:(Unity视频)