首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

请问几个关于"在C#中用WM_COPYDATA消息来实现进程间通信"的有关问题

2012-03-04 
请教几个关于在C#中用WM_COPYDATA消息来实现进程间通信的问题代码如下://-----------------------------

请教几个关于"在C#中用WM_COPYDATA消息来实现进程间通信"的问题
代码如下:
//---------------------------------------------------
//发送方:
using   System;
using   System.Drawing;
using   System.Collections;
using   System.ComponentModel;
using   System.Windows.Forms;
using   System.Data;
using   System.Runtime.InteropServices;
namespace   WinFormSendMsg
{
public   class   Form1   :   System.Windows.Forms.Form
{
private   System.Windows.Forms.TextBox   textBox1;
private   System.Windows.Forms.Button   button1;
private   System.ComponentModel.Container   components   =   null;
const   int   WM_COPYDATA   =   0x004A;
public   Form1()
{
InitializeComponent();
}
protected   override   void   Dispose(   bool   disposing   )
{
if(   disposing   )
{
if   (components   !=   null)  
{
components.Dispose();
}
}
base.Dispose(   disposing   );
}

private   void   InitializeComponent()
{
this.textBox1   =   new   System.Windows.Forms.TextBox();
this.button1   =   new   System.Windows.Forms.Button();
this.SuspendLayout();
//  
//   textBox1
//  
this.textBox1.Location   =   new   System.Drawing.Point(184,   24);
this.textBox1.Name   =   "textBox1 ";
this.textBox1.Size   =   new   System.Drawing.Size(128,   21);
this.textBox1.TabIndex   =   0;
this.textBox1.Text   =   "textBox1 ";
//  
//   button1
//  
this.button1.Location   =   new   System.Drawing.Point(344,   16);
this.button1.Name   =   "button1 ";
this.button1.Size   =   new   System.Drawing.Size(112,   32);
this.button1.TabIndex   =   1;
this.button1.Text   =   "button1 ";
this.button1.Click   +=   new   System.EventHandler(this.button1_Click);
//  
//   Form1
//  
this.AutoScaleBaseSize   =   new   System.Drawing.Size(6,   14);
this.ClientSize   =   new   System.Drawing.Size(536,   142);
this.Controls.AddRange(new   System.Windows.Forms.Control[]   {
this.button1,
this.textBox1});
this.Name   =   "Form1 ";
this.Text   =   "发送方窗体 ";
this.ResumeLayout(false);
}
static   void   Main()  
{
Application.Run(new   Form1());
}
[DllImport( "User32.dll ",EntryPoint= "SendMessage ")]
private   static   extern   int   SendMessage(
int   hWnd,   //   handle   to   destination   window
int   Msg,   //   message
int   wParam,   //   first   message   parameter
ref   COPYDATASTRUCT   lParam   //   second   message   parameter
);

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

private   void   button1_Click(object   sender,   System.EventArgs   e)
{
int   WINDOW_HANDLER   =   FindWindow(null,@ "接收方窗体 ");   //   1
if(WINDOW_HANDLER   ==   0)
{
}
else
{
byte[]   sarr   =   System.Text.Encoding.Default.GetBytes(this.textBox1.Text);


int   len   =   sarr.Length;
COPYDATASTRUCT   cds;
cds.dwData   =   (IntPtr)   100;   //   2
cds.lpData   =   this.textBox1.Text;
cds.cbData   =   len   +   1;
SendMessage(WINDOW_HANDLER,   WM_COPYDATA,   0,   ref   cds);

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

}

//---------------------------------------------------
//接受方
//---------------------------------------------------
using   System;
using   System.Drawing;
using   System.Collections;
using   System.ComponentModel;
using   System.Windows.Forms;
using   System.Data;
using   System.Runtime.InteropServices;
namespace   WindowsFormGetMsg
{
public   class   Form1   :   System.Windows.Forms.Form
{
private   System.Windows.Forms.TextBox   textBox1;
private   System.ComponentModel.Container   components   =   null;
const   int   WM_COPYDATA   =   0x004A;
public   Form1()
{
InitializeComponent();
}
protected   override   void   Dispose(   bool   disposing   )
{
if(   disposing   )
{
if   (components   !=   null)  
{
components.Dispose();
}
}
base.Dispose(   disposing   );
}
private   void   InitializeComponent()
{
this.textBox1   =   new   System.Windows.Forms.TextBox();
this.SuspendLayout();
//  
//   textBox1
//  
this.textBox1.Location   =   new   System.Drawing.Point(176,   32);
this.textBox1.Name   =   "textBox1 ";
this.textBox1.Size   =   new   System.Drawing.Size(160,   21);
this.textBox1.TabIndex   =   0;
this.textBox1.Text   =   "textBox1 ";
//  
//   Form1
//  
this.AutoScaleBaseSize   =   new   System.Drawing.Size(6,   14);
this.ClientSize   =   new   System.Drawing.Size(432,   266);
this.Controls.AddRange(new   System.Windows.Forms.Control[]   {
this.textBox1});
this.Name   =   "Form1 ";
this.Text   =   "接收方窗体 ";
this.ResumeLayout(false);
}
static   void   Main()  
{
Application.Run(new   Form1());
}
protected   override   void   DefWndProc(ref   System.Windows.Forms.Message   m)
{
switch(m.Msg)
{
case   WM_COPYDATA:
COPYDATASTRUCT   mystr   =   new   COPYDATASTRUCT();
Type   mytype   =   mystr.GetType();
mystr   =(COPYDATASTRUCT)m.GetLParam(mytype);
this.textBox1.Text   =mystr.lpData;
break;
default:
base.DefWndProc(ref   m);
break;
}
}
}
public   struct   COPYDATASTRUCT
{
public   IntPtr   dwData;
public   int   cbData;
[MarshalAs(UnmanagedType.LPStr)]  
  public   string   lpData;
}
}

---------------------------------------------------

问题如下:
1.   在代码中标注1处,如果不需要通过一个form来接收,比如我的工程里面就没有form,那我该如何接收?
2.能否讲解一下标注2处的含义,这个是什么意思呢?我查了查,
DWORD   dwData;//用户定义数据
那么它这个是什么意思?   如果我的lpdata是一个结构或者类,那这个地方应该如何处理?


3.同样,标注3处说明了什么,我不写这段可以吗?   如果的lpdata是个类,那么我该写什么呢?(我觉得好像写成类没必要,传递的是一些信息,用struct足够了)

[解决办法]
int WINDOW_HANDLER = FindWindow(null,@ "接收方窗体 "); // 1
WM_COPYDATA是两个进程之间的通讯,并且双方都要有消息循环在执行。
在C#中,没有窗体,如果可以启动消息循环,也可以通讯,
不过我不知道有什么方法:)

cds.dwData = (IntPtr) 100; // 2
该语句不影响你其他两个变量的值,可任意写。

[MarshalAs(UnmanagedType.LPStr)] // 3
说明封送到非托管的方式,
如果是结构,会比较麻烦,我是用非托管方式解决的。
[解决办法]
using
IntPtr p = Marshal.StructureToPtr(
object structure,
IntPtr ptr,
bool fDeleteOld
);
封送到非托管内存,再传IntPtr

[解决办法]
平台调用本来就麻烦,
hdt(倦怠)这种方式你可以试试
但以前我做过一个项目,用该方式是不行的,可能是结构比较复杂:)

我有一点很纳闷,怎没就不能用非托管了?
个人感觉非托管也相当安全:)
[解决办法]
项目-》属性-》生成-》允许不安全代码 点上
class TestCopy
{
// The unsafe keyword allows pointers to be used within the following method:
static unsafe void Copy(byte[] src, int srcIndex, byte[] dst, int dstIndex, int count)
{
if (src == null || srcIndex < 0 ||
dst == null || dstIndex < 0 || count < 0)
{
throw new System.ArgumentException();
}

int srcLen = src.Length;
int dstLen = dst.Length;
if (srcLen - srcIndex < count || dstLen - dstIndex < count)
{
throw new System.ArgumentException();
}

// The following fixed statement pins the location of the src and dst objects
// in memory so that they will not be moved by garbage collection.
fixed (byte* pSrc = src, pDst = dst)
{
byte* ps = pSrc;
byte* pd = pDst;

// Loop over the count in blocks of 4 bytes, copying an integer (4 bytes) at a time:
for (int i = 0 ; i < count / 4 ; i++)
{
*((int*)pd) = *((int*)ps);
pd += 4;
ps += 4;
}

// Complete the copy by moving any bytes that weren 't moved in blocks of 4:
for (int i = 0; i < count % 4 ; i++)
{
*pd = *ps;
pd++;
ps++;
}
}
}

static void Main()
{
byte[] a = new byte[100];
byte[] b = new byte[100];

for (int i = 0; i < 100; ++i)
{
a[i] = (byte)i;
}

Copy(a, 0, b, 0, 100);
System.Console.WriteLine( "The first 10 elements are: ");

for (int i = 0; i < 10; ++i)
{
System.Console.Write(b[i] + " ");
}
System.Console.WriteLine( "\n ");
}
}

来自MSDN
[解决办法]
有关平台调用数据类型的信息
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconplatforminvokedatatypes.asp
[解决办法]
如果lpData里面是struct类型数据
WholeInfo wi=(WholeInfo)System.Runtime.InteropServices.Marshal.PtrToStructure(IntPtr, typeof(WholeInfo));
这样就可以得到结构了。
struct CopyDataStruct
{
public int dwData;


public int cbData;
public IntPtr lpData;

}
您看看你的定义跟我的一样么?void*是指针,你一定需要将其定义为IntPtr数据类型,你的是string,一样么?还有dwData是DWORD,Specifies up to 32 bits of data to be passed to the receiving application.
你定义成IntPtr有什么意思,直接定义成int就可以了,具体的数据定义参考

有关平台调用数据类型的信息
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconplatforminvokedatatypes.asp

先把这里搞规范了,要不就有可能出现这样那样的问题,

热点排行