A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 陈君 于 2014-8-1 16:16 编辑

注意这里发送消息的函数:public static void SendMessage(string destProcessName, int msgID, string strMsg),只能发送一个msgID和一个strMsg, 接收方只接收了strMsg,我的项目中已经够用了,你如果需要读msgID,还需要改一下。客户端代码请参考csdn上的原文自己写吧。

/*
进程之间通讯的几种方法:
在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯。常用的方法有  
(1)使用内存映射文件  
(2)通过共享内存DLL共享内存  
(3)使用SendMessage向另一进程发送WM_COPYDATA消息  

比起前两种的复杂实现来,WM_COPYDATA消息无疑是一种经济实惠的一种方法.  
WM_COPYDATA消息的主要目的是允许在进程间传递只读数据。Windows在通过WM_COPYDATA消息传递期间,不提供继承同步方式。
SDK文档推荐用户使用SendMessage函数,接受方在数据拷贝完成前不返回,这样发送方就不可能删除和修改数据:  

这个函数的原型及其要用到的结构如下:  
SendMessage(hwnd, WM_COPYDATA, wParam, lParam);   
其中:
WM_COPYDATA对应的十六进制数为0x004A  
wParam设置为包含数据的窗口的句柄。
lParam指向一个COPYDATASTRUCT的结构:  
typedef  struct  tagCOPYDATASTRUCT
{  
             DWORD  dwData;  //用户定义数据  
             DWORD  cbData;  //数据大小  
             PVOID  lpData;  //指向数据的指针  
} COPYDATASTRUCT;  
该结构用来定义用户数据。  

具体过程如下:  
首先,在发送方,用FindWindow找到接受方的句柄,然后向接受方发送WM_COPYDATA消息。
接受方在DefWndProc事件中处理这条消息。由于中文编码是两个字节, 所以传递中文时候字节长度要搞清楚。
  1. protected override void DefWndProc(ref System.Windows.Forms.Message m) {
  2. switch(m.Msg) {
  3. case WinMessageUtil.WM_COPYDATA:
  4. string str = WinMessageUtil.ReceiveMessage(ref m);
  5. break;
  6. default:
  7. break;
  8. }
  9. base.DefWndProc(ref m);
  10. }
  11. */

  12. using System;
  13. using System.Runtime.InteropServices;
  14. using System.Diagnostics;

  15. namespace Speeding.Util
  16. {

  17. //WM_COPYDATA消息所要求的数据结构
  18. public struct CopyDataStruct
  19. {
  20. public IntPtr dwData; //这里注意,一定要用IntPtr网上好多别的用的int会出错
  21. public int cbData;

  22. [MarshalAs(UnmanagedType.LPStr)]
  23. public string lpData;
  24. }

  25. /// <summary>
  26. /// 本类封装了一些进程间通讯的细节
  27. /// </summary>
  28. public class WinMessageUtil
  29. {
  30. public const int WM_COPYDATA = 0x004A;

  31. //通过窗口的标题来查找窗口的句柄
  32. [DllImport("User32.dll",EntryPoint="FindWindow")]
  33. private static extern int FindWindow(string lpClassName, string lpWindowName);

  34. //在DLL库中的发送消息函数
  35. [DllImport("User32.dll",EntryPoint="SendMessage")]
  36. private static extern int SendMessage
  37. (
  38. int hWnd, // 目标窗口的句柄
  39. int Msg, // 在这里是WM_COPYDATA
  40. int wParam, // 第一个消息参数
  41. ref CopyDataStruct lParam // 第二个消息参数
  42. );

  43. /// <summary>
  44. /// 发送消息,只能传递一个自定义的消息ID和消息字符串,想传一个结构,但没成功
  45. /// </summary>
  46. /// <param name="destProcessName">目标进程名称,如果有多个,则给每个都发送</param>
  47. /// <param name="msgID">自定义数据,可以通过这个来决定如何解析下面的strMsg</param>
  48. /// <param name="strMsg">传递的消息,是一个字符串</param>
  49. public static void SendMessage(string destProcessName, int msgID, string strMsg)
  50. {
  51. if(strMsg == null) return;

  52. //按进程名称查找,同名称的进程可能有许多,所以返回的是一个数组
  53. Process []foundProcess = Process.GetProcessesByName(destProcessName);
  54. foreach(Process p in foundProcess)
  55. {
  56. int toWindowHandler = p.MainWindowHandle.ToInt32();
  57. if(toWindowHandler != 0)
  58. {
  59. CopyDataStruct cds;
  60. cds.dwData = (IntPtr) msgID; //这里可以传入一些自定义的数据,但只能是4字节整数
  61. cds.lpData = strMsg; //消息字符串
  62. cds.cbData = System.Text.Encoding.Default.GetBytes(strMsg).Length + 1; //注意,这里的长度是按字节来算的

  63. //发送方的窗口的句柄, 由于本系统中的接收方不关心是该消息是从哪个窗口发出的,所以就直接填0了
  64. int fromWindowHandler = 0;
  65. SendMessage(toWindowHandler, WM_COPYDATA, fromWindowHandler, ref cds);
  66. }
  67. }
  68. }

  69. /// <summary>
  70. /// 接收消息,得到消息字符串
  71. /// </summary>
  72. /// <param name="m">System.Windows.Forms.Message m</param>
  73. /// <returns>接收到的消息字符串</returns>
  74. public static string ReceiveMessage(ref System.Windows.Forms.Message m)
  75. {
  76. CopyDataStruct cds = (CopyDataStruct) m.GetLParam(typeof(CopyDataStruct));
  77. return cds.lpData;
  78. }

  79. }


  80. }
复制代码
转自:http://www.51csharp.com/WinForm/winform_933.html



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马