代码如下:
//---------------------------------------------------
//发送方:
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足够了)

解决方案 »

  1.   

    int WINDOW_HANDLER = FindWindow(null,@"接收方窗体"); // 1
    WM_COPYDATA是两个进程之间的通讯,并且双方都要有消息循环在执行。
    在C#中,没有窗体,如果可以启动消息循环,也可以通讯,
    不过我不知道有什么方法:)cds.dwData = (IntPtr) 100; // 2
    该语句不影响你其他两个变量的值,可任意写。[MarshalAs(UnmanagedType.LPStr)] // 3
    说明封送到非托管的方式,
    如果是结构,会比较麻烦,我是用非托管方式解决的。
      

  2.   

    谢谢winxieddd(一剑飘香)的热心帮助.
    对于第三点,我不能用非托管,所以还得坚持啊.
    关于结构,我首先将[MarshalAs(UnmanagedType.Struct)] 
    然后定义那个结构,遇见这样的问题
    如果结构里面就只有1个String,那是ok的,如果定义两个String,则会出现接收方crash(运行状态),如果是调试状态,则会出现第二个值是乱码(对应于第一的第二个string),而且无论发送方如何改第二个string,接收方的第二个值都是一样的乱码,比如"赴59"之类的.请大家继续帮帮忙,解决一下以上问题
      

  3.   

    using
    IntPtr p = Marshal.StructureToPtr(
       object structure,
       IntPtr ptr,
       bool fDeleteOld
    );
    封送到非托管内存,再传IntPtr
      

  4.   

    平台调用本来就麻烦,
    hdt(倦怠)这种方式你可以试试
    但以前我做过一个项目,用该方式是不行的,可能是结构比较复杂:)我有一点很纳闷,怎没就不能用非托管了?
    个人感觉非托管也相当安全:)
      

  5.   

    我想请问一下,在C#中,如何使用非托管方式,能不能有稍微具体一点的代码?thx
    我上面那段代码只是一个简单的示例,不是项目的代码,这个传递消息,只是其中很小的一部分 : )
    我先试试hdt(倦怠)的方法,呵呵,谢谢
      

  6.   

    项目-》属性-》生成-》允许不安全代码  点上
    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
      

  7.   

    发送方:
                    IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(myStruct));
                    Marshal.StructureToPtr(myStruct, p, true);
                    cds.lpData = p;
                    SendMessage(WINDOW_HANDLER, WM_COPYDATA, 0, ref cds);
    ------------------------------------------------------------------------
    接收方:
            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);
                        WholeInfo h = new WholeInfo();
                        Marshal.PtrToStructure(mystr.lpData, h);
                        this.textBox1.Text = h.m_centralFilePath;
                        this.textBox2.Text = h.m_localFilePath;
                 }.......
    它会报错: {"The structure must not be a value class.\r\nParameter name: structure"}
    请教一下怎么修改? 或者给一个简单的例子,哈哈,谢谢~~~
      

  8.   

    不好意思,接收方写的是:
               WholeInfo h;//= new WholeInfo();
               h = (WholeInfo)Marshal.PtrToStructure(mystr.lpData, typeo(WholeInfo));
    但是仍然不对,
    先是在h = (wholeInfo)Marshal.PtrTo......
    处报错,"External component has thrown an exception."
    如果继续往下走,则在main函数中的Application.Run(new AccepterDlg());
    处报错,{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}
      

  9.   

    你的结构定义有问题 
    改成
    struct CopyDataStruct
    {
    public int dwData;
    public int cbData;
    public IntPtr lpData;

    }
    因为lpData在C里面是一个void*指针,他可能是任意类型数据的指针,在C#里面对应类型为IntPtr
    注意发送消息的时候,需要将lpData指向数据的数据结构的长度存储在cbData里面,而且必须有约定,lpData里面到底存放什么类型数据,比如是char*,还是别的数据类型,接受的时候,用cbData来获取lpData数据长度,比如发送的char*数据
    byte[] buffer = new byte[data.cbData];
    System.Runtime.InteropServices.Marshal.Copy(data.lpData,buffer,0,buffer.Length);
    string  s = System.Text.ASCIIEncoding.ASCII.GetString(buffer);
    s就是c里面要发送的数据
      

  10.   

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

  11.   

    我现在的CopyDataStruct是你这么写的,但是就是传不过去,比如我想传一个结构过去
    public struct WholeInfo
    {
      public string cPath;
      public string lPath;
      public bool status;
     }
    我该怎么办呢? 我试了很久,都会有错,请指点一下. 顺便请教一下,我这个时候,cbData应该怎么处理?
      

  12.   

    如果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先把这里搞规范了,要不就有可能出现这样那样的问题,
      

  13.   

    呵呵,上面那个是个最原先的例子,不好意思,误导你了,呵呵
    我现在的是这样的: 
        public struct COPYDATASTRUCT
            {
                public IntPtr dwData;
                public int cbData;
                public IntPtr lpData;
            }
    谢谢你的耐心和细心~~ :)
    那是我最原来的一个简单的示例,传string是ok的,就用最原始那个,现在我不是光传string,而是传一个结构,就出现了后来这一系列的问题.