首先程序主体来自网络,我只是应用在我自己的项目中,其中出现了一系列的问题,有些已经解决,有些使用了折中的方案,如果有大神能够给予知道,感激不尽!

首先是发送端程序:

这是我的程序任务执行主界面,此处已经显示了每个消防队员的空呼数据;

消防员在着火的大楼内部的具体方位采用Unity3d进行开发,因此我wpf程序需要将队员的位置信息传输到三维场景中;

发送数据的程序如下:

        /// <summary>
/// 查找窗口
/// </summary>
[DllImport("user32.dll")]
public static extern IntPtr FindWindowA(string lpClassName, string lpWindowName);      //user32.dll中的SendMessage
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, ref COPYDATASTRUCT lParam);      //本窗口句柄
     public IntPtr m_hWnd;      //接收方窗口句柄
     private IntPtr hWndPalaz; /// <summary>
/// 发送windows消息方便user32.dll中的SendMessage函数使用
/// </summary>
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}      //宏定义
private const ushort IPC_VER = ;
private const int IDT_ASYNCHRONISM = 0x0201;
private const uint WM_COPYDATA = 0x004A;
private const ushort IPC_CMD_GF_SOCKET = ;
private const ushort IPC_SUB_GF_SOCKET_SEND = ;
private const int IPC_SUB_GF_CLIENT_READY = ;
private const int IPC_CMD_GF_CONTROL = ;
private const int IPC_BUFFER = ;//最大缓冲长度 //数据包头配合使用
public unsafe struct IPC_Head
{
public ushort wVersion;
public ushort wPacketSize;
public ushort wMainCmdID;
public ushort wSubCmdID;
} public unsafe struct IPC_Buffer
{
public IPC_Head Head; //IPC_Head结构
public fixed byte cbBuffer[IPC_BUFFER]; //指针 存放数据 利用byte[]接收存放
}      /// <summary>
/// 将字符串转换为指针用于发送
/// </summary>
public void SendData(string data)
{
hWndPalaz = FindWindowA(null, "Navigation2.0");//获取接收窗口句柄 if (hWndPalaz != null)
{
//获得当前窗口句柄
m_hWnd = FindWindowA("Mission", null); byte[] bytes = Encoding.UTF8.GetBytes(data.PadRight(, '/'));
IntPtr pData = Marshal.AllocHGlobal( * bytes.Length);
Marshal.Copy(bytes, , pData, bytes.Length);
SendData(hWndPalaz, IPC_CMD_GF_SOCKET, IPC_SUB_GF_SOCKET_SEND, pData, (ushort)bytes.Length);
}
}      /// <summary>
/// SendMessage发送
/// </summary>
/// <param name="hWndServer">指针</param>
/// <param name="wMainCmdID">主命令</param>
/// <param name="wSubCmdID">次命令</param>
/// <param name="pData">json转换的指针</param>
/// <param name="wDataSize">数据大小</param>
/// <returns></returns>
public unsafe bool SendData(IntPtr hWndServer, ushort wMainCmdID, ushort wSubCmdID, IntPtr pData, ushort wDataSize)
{
//给IPCBuffer结构赋值
IPC_Buffer IPCBuffer;
IPCBuffer.Head.wVersion = IPC_VER;
IPCBuffer.Head.wSubCmdID = wSubCmdID;
IPCBuffer.Head.wMainCmdID = wMainCmdID;
IPCBuffer.Head.wPacketSize = (ushort)Marshal.SizeOf(typeof(IPC_Head)); //内存操作
if (pData != null)
{
//效验长度
if (wDataSize > ) return false;
//拷贝数据
IPCBuffer.Head.wPacketSize += wDataSize; byte[] bytes = new byte[IPC_BUFFER];
Marshal.Copy(pData, bytes, , wDataSize); for (int i = ; i < IPC_BUFFER; i++)
{
IPCBuffer.cbBuffer[i] = bytes[i];
}
} //发送数据
COPYDATASTRUCT CopyDataStruct;
IPC_Buffer* pPCBuffer = &IPCBuffer;
CopyDataStruct.lpData = (IntPtr)pPCBuffer;
CopyDataStruct.dwData = (IntPtr)IDT_ASYNCHRONISM;
CopyDataStruct.cbData = IPCBuffer.Head.wPacketSize;
SendMessage(hWndServer, 0x004A, (int)m_hWnd, ref CopyDataStruct); return true;
}

SendData函数重载了,只要调用void SendData(string args)即可。

接下来是接收端,接收端比较特殊,因为是Unity程序发布的exe,不是普通的窗口程序;

首先是我的三维程序界面:

地面是直接加载的百度地图或高德地图,手动绘制建筑物的轮廓,再通过设置层数、层高等参数即可生成楼层;

数据接收的代码:

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System;
using System.Threading;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices; public class DataClient : MonoBehaviour
{
List<string> caches = new List<string>();
void Start()
{
//安装钩子
HookLoad();
}void OnGUI()
{
GUI.contentColor = Color.red; GUILayout.Label(caches.Count.ToString());
for (int i = ; i < caches.Count; i++)
GUILayout.Label(caches[i].Length + ":" + caches[i]);
} void OnApplicationQuit()
{ 
     //关闭钩子
HookClosing();
    } 

   //钩子接收消息的结构  
   public struct CWPSTRUCT { public int lparam; public int wparam; public uint message; public IntPtr hwnd; }
//建立钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, uint dwThreadId);
//移除钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook); //把信息传递到下一个监听
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, int lParam);
//回调委托
private delegate int HookProc(int nCode, int wParam, int lParam);
//钩子
int idHook = ;
//是否安装了钩子
bool isHook = false;
GCHandle gc;
private const int WH_CALLWNDPROC = ; //钩子类型 全局钩子 //定义结构和发送的结构对应
public unsafe struct IPC_Head
{
public int wVersion;
public int wPacketSize;
public int wMainCmdID;
public int wSubCmdID;
}
private const int IPC_BUFFER = ;//最大缓冲长度
public unsafe struct IPC_Buffer
{
public IPC_Head Head;
public fixed byte cbBuffer[IPC_BUFFER]; //json数据存的地方
}
public struct COPYDATASTRUCT
{
public int dwData;
public int cbData;
public IntPtr lpData;
} void OnDestroy()
{
//关闭钩子
HookClosing();
}
private void HookLoad()
{
Debug.Log("开始运行");
//安装钩子
{
//钩子委托
HookProc lpfn = new HookProc(Hook);
//关联进程的主模块
IntPtr hInstance = IntPtr.Zero;// GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
idHook = SetWindowsHookEx(WH_CALLWNDPROC, lpfn, hInstance, (uint)AppDomain.GetCurrentThreadId());
if (idHook > )
{
Debug.Log("钩子[" + idHook + "]安装成功");
isHook = true;
//保持活动 避免 回调过程 被垃圾回收
gc = GCHandle.Alloc(lpfn);
}
else
{
Debug.Log("钩子安装失败");
isHook = false;
UnhookWindowsHookEx(idHook);
}
}
} //卸载钩子
private void HookClosing()
{
if (isHook)
{
UnhookWindowsHookEx(idHook);
}
} private bool _bCallNext;
public bool CallNextProc
{
get { return _bCallNext; }
set { _bCallNext = value; }
} //钩子回调
private unsafe int Hook(int nCode, int wParam, int lParam)
{
try
{
IntPtr p = new IntPtr(lParam);
CWPSTRUCT m = (CWPSTRUCT)Marshal.PtrToStructure(p, typeof(CWPSTRUCT)); if (m.message == )
{
COPYDATASTRUCT entries = (COPYDATASTRUCT)Marshal.PtrToStructure((IntPtr)m.lparam, typeof(COPYDATASTRUCT));
IPC_Buffer entries1 = (IPC_Buffer)Marshal.PtrToStructure((IntPtr)entries.lpData, typeof(IPC_Buffer)); IntPtr intp = new IntPtr(entries1.cbBuffer);
string str = new string((sbyte*)intp - wParam);
caches.Add(str);
if (caches.Count > )
caches.RemoveAt();
} if (CallNextProc)
{
return CallNextHookEx(idHook, nCode, wParam, lParam);
}
else
{
return CallNextHookEx(idHook, nCode, wParam, lParam);
}
}
catch (Exception ex)
{
Debug.Log(ex.Message);
return ;
}
}
}

直接将脚本挂在某个物体上,然后注意的是发布后程序的名字(运行exe在窗口标题栏显示的名字),因为发送端是通过这个名字来找到该窗口的。

运行的效果如下:

注意,由于程序中用到的unsafe,不安全代码,因此要讲工程设置为允许不安全代码,而unity中则需要在工程Assets的根目录创建文本文件,内容设置:-unsafe,注意不要有多余的空格什么的,然后文件复制4分,文件名分别为:us.rsp、smcs.rsp、gmcs.rsp

、csc.rsp、boo.rsp,其实不是全部都要,每个针对一种语言的不安全代码,文件创建好了之后要重启一下unity。

使用C#进行应用程序间通信(WPF与Unity通信)的更多相关文章

  1. wpf集成unity

    定义一个帮助类 实际上就是为了设置以下这两种属性 安全性信任和从html中可见的属性  即: 在html的javaScript中可用 window.external.方法名来调用C#方法    [Pe ...

  2. Wpf Prism.Unity 7

    Prism.Unity 中UnityBootStrapper已经不用了,可以继承PrismApplication 1.Install-package Prism.Unity -v 7.2.0.1367 ...

  3. MVVM在WPF中应用(1)

    在软件行业浸润了这么多年,第一次在MES的工厂里从事软件开发. 在这里的感觉就是安静.宽松,比在那些专门以软件为主的企业中轻松自在.在这里的第一个项目是关于数据的导入和导出,还有数据的比较这些功能. ...

  4. 2: 使用Prism初始化程序 Initializing Applications Using the Prism Library 5.0 for WPF(英汉对照版)

    This topic addresses what needs to happen to get a Prism for WPF application up and running. A Prism ...

  5. 如何实现Windows Phone代码与Unity相互通信(事件方式)

    源地址:http://www.cnblogs.com/petto/p/3909063.html 一些废话 昨天写一篇今天写一篇.不是我闲的蛋疼,是今天一天碰到了好几个恼人的问题,浪费一天时间搞定.本文 ...

  6. Unity 命令行参数

    通常情况下,Unity可以通过双击桌面上的图标启动,也可以通过输入命令行启动(例如,MacOS终端或者Windows的CMD窗口),通过这种方式在启动时会接受命令和信息.我们可以制作一些小工具跟Uni ...

  7. Unity接第三方SDK时遇到的坑

    1.大部分SDK的方法需要在线程中执行,一般会放在主线程里执行,安卓中主线程一般用于UI渲染. this.runOnUiThread(new Runnable() { @Override public ...

  8. Unity Web前端研究

    原地址:http://blog.csdn.net/libeifs/article/details/7200630 开发环境 Window7 Unity3D  3.4.1 MB525defy Andro ...

  9. Unity之SDK接入(Unity与Android通信)

    首先介绍一点关于Android与unity通信的知识: 完成通信主要靠unity中的class.jar包(在unity的安装目录下). 在unity中调用android的方法: jo.call(&qu ...

随机推荐

  1. struct字节对齐原则

    原则1:windows下,k字节基本类型以k字节倍数偏移量对齐,自定义结构体则以结构体中最高p字节基本类型的p字节倍数偏移量对齐,Linux下则以2或4字节对齐; 原则2:整体对齐原则,例如数组结构体 ...

  2. Hadoop生态圈-Zookeeper的工作原理分析

    Hadoop生态圈-Zookeeper的工作原理分析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   无论是是Kafka集群,还是producer和consumer都依赖于Zoo ...

  3. js 数组与字符串的相互转化

    数组转字符串:join() 字符串转数组:split('')

  4. vue 中this指向遇到的坑

    vue中的this指向问题 如果方法中没有使用箭头函数,记得把this赋值给另一个变量再使用.

  5. Hive记录-使用Hue管理Hive元数据

    Hue是一个开源的Apache Hadoop UI系统,由Cloudera Desktop演化而来,最后Cloudera公司将其贡献给Apache基金会的Hadoop社区,它是基于Python Web ...

  6. ruby计算完成率

    task_complete = ((task_forms_w.to_f / task_forms_num.to_f)*100).round(2).to_s << "%" ...

  7. 超哥带你学GIT

    git入门 git安装 git基础 git分支 github与gitlab与git三个基佬的故事 gitlab与pycharm结合 github使用 git超清技能图 学习git站点: git官网 廖 ...

  8. HDU - 5117 Fluorescent(状压dp+思维)

    原题链接 题意 有N个灯和M个开关,每个开关控制着一些灯,如果按下某个开关,就会让对应的灯切换状态:问在每个开关按下与否的一共2^m情况下,每种状态下亮灯的个数的立方的和. 思路1.首先注意到N< ...

  9. Java编程思想 学习笔记1

    一.对象导论 1.抽象过程 Alan Kay曾经总结了第一个成功的面向对象语言.同时也是Java所基于的语言之一的Smalltalk的五个基本特性,这些特性表现了纯粹的面向对象程序设计方式 1)万物皆 ...

  10. 如何用matplotlib绘制决策边界

    import matplotlib.pyplot as plt import numpy as np import sklearn import sklearn.datasets import skl ...