场景 :需要开发一个通讯组件 流程为:界面-开启接收服务-通过发送组件发送信息到 其他客户端和服务端 接受服务接收其他客户端发送的消息 需要传递给对应组件或者界面 因此会出现类库重复引用问题。因为采用消息队列,和数据库中转来传递消息需要每个组件知道太多其他组件的业务,并且耗损性能和时间更多一下因此都被排除掉。最后采用Windows API传递消息 后续如果有更好地办法再继续更新上来 由于项目进程间和线程间需要进行通讯,因此通过api调用windows底层消息传递 [DllImport("User32.dll", EntryPoint = "PostMessage")] public static extern int PostMessage(IntPtr wnd, int msg, IntPtr wP, IntPtr lP);
但是由于程序开发是WPF因此与传统的WinForm调用 PostMessage 消息有一定区别,并且无法传递结构体 因此通过实验和调查实现了WPF调用PostMessage传递消息,并且支持传递结构体(转换概念:现将结构体进行转换为16进制,WinProc接收后在进行转换为结构体) 具体代码如下: /// <summary> /// Receive message window form handle 消息接收窗口句柄 /// </summary> public static IntPtr Handle; /// <summary> /// PostMessage Dll Import API方法 /// </summary> [DllImport("User32.dll", EntryPoint = "PostMessage")] public static extern int PostMessage(IntPtr wnd, int msg, IntPtr wP, IntPtr lP); /// <summary> /// Message Data Struct 结构体 /// </summary> public struct MessageDataStruct { //message对象 public CMessageData messageData; } /// <summary> /// user-defined message no 自定义消息 /// </summary> public const int USER_MESSAGE = 0x0400; 发送消息 /// <summary> /// Send mesage data to window message queue /// </summary> /// <param name="messageData">message data</param> public void PostMessageToMessageQueue(MessageDataStruct messageData) { //结构体赋值 MessageDataStruct mds = new MessageDataStruct(); mds.messageData = new CMessageData(); LocalClientInfo lci = new LocalClientInfo(); lci.ClientID = "我是客户端id"; lci.ClientIP = "我是客户端ip"; mds.messageData.LocalClientInfo = new LocalClientInfo(); mds.messageData.LocalClientInfo = lci;
//结构体转换为 IntPtr 16进制 IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(mds)); Marshal.StructureToPtr(mds, buffer, false);
//发送消息 PostMessage(Handle, BaseTypeParameters.USER_MESSAGE(等同于消息编号), buffer, IntPtr.Zero); } Windows消息接收 调用系统WinProc方法 void win_SourceInitialized(object sender, EventArgs e) {
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; if (hwndSource != null) { hwndSource.AddHook(new HwndSourceHook(WindowProc)); } }
protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); this.win_SourceInitialized(this, e); }
#region USB识别操 private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { IntPtr result = IntPtr.Zero; { //WM_DEVICECHANGE,系统硬件改变发出的系统消息
int param = msg; switch (param) { //判断是否为自定义消息 case BaseTypeParameters.USER_MESSAGE: //将消息转换为结构体
MessageDataStruct mds = (MessageDataStruct)Marshal.PtrToStructure(wParam, typeof(MessageDataStruct)); MessageBox.Show(mds.messageData.LocalClientInfo.ClientID + "----" + mds.messageData.LocalClientInfo.ClientIP); break; } return result; } } #endregion //将窗句柄赋值给服务 private void Window_Loaded(object sender, RoutedEventArgs e) { ReceiveDataImplement.Handle = new WindowInteropHelper(this).Handle; }