代码如下:
//---------------------------------------------------
//发送方:
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足够了)
//---------------------------------------------------
//发送方:
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足够了)
解决方案 »
- 有会delphi7和C#的大侠帮帮忙!!!
- 在网站中更新数据库中的数据
- 问一个比较菜的问题,用了richTextBox控件后,想让这个自定义类作用到这个控件上,该怎么操作呢?
- 我往textbox中添加数据库中读取的数据出错了!高手给指导一下
- GridView 中 Lable控件问题?
- 在C#窗体内绘图,在滚动时不能正确刷新
- 通过代理上网,在.net里怎样用windows 2000 server自带的CDO组件发送邮件,smtp需要做怎样的设置?
- 请问如获取来电显示的数据!
- 那位大哥能给我winform下datagrid的添加,删除,保存,取消的完整例子吗?
- 在线等待,马上给分!!!--如果一句语句太长,要分几行书写,该怎么写,请举个例子
- 一个超菜的截字符串问题
- 求将</p>替换成<br />的正则表达式
WM_COPYDATA是两个进程之间的通讯,并且双方都要有消息循环在执行。
在C#中,没有窗体,如果可以启动消息循环,也可以通讯,
不过我不知道有什么方法:)cds.dwData = (IntPtr) 100; // 2
该语句不影响你其他两个变量的值,可任意写。[MarshalAs(UnmanagedType.LPStr)] // 3
说明封送到非托管的方式,
如果是结构,会比较麻烦,我是用非托管方式解决的。
对于第三点,我不能用非托管,所以还得坚持啊.
关于结构,我首先将[MarshalAs(UnmanagedType.Struct)]
然后定义那个结构,遇见这样的问题
如果结构里面就只有1个String,那是ok的,如果定义两个String,则会出现接收方crash(运行状态),如果是调试状态,则会出现第二个值是乱码(对应于第一的第二个string),而且无论发送方如何改第二个string,接收方的第二个值都是一样的乱码,比如"赴59"之类的.请大家继续帮帮忙,解决一下以上问题
IntPtr p = Marshal.StructureToPtr(
object structure,
IntPtr ptr,
bool fDeleteOld
);
封送到非托管内存,再传IntPtr
hdt(倦怠)这种方式你可以试试
但以前我做过一个项目,用该方式是不行的,可能是结构比较复杂:)我有一点很纳闷,怎没就不能用非托管了?
个人感觉非托管也相当安全:)
我上面那段代码只是一个简单的示例,不是项目的代码,这个传递消息,只是其中很小的一部分 : )
我先试试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
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"}
请教一下怎么修改? 或者给一个简单的例子,哈哈,谢谢~~~
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."}
改成
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里面要发送的数据
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconplatforminvokedatatypes.asp
public struct WholeInfo
{
public string cPath;
public string lPath;
public bool status;
}
我该怎么办呢? 我试了很久,都会有错,请指点一下. 顺便请教一下,我这个时候,cbData应该怎么处理?
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先把这里搞规范了,要不就有可能出现这样那样的问题,
我现在的是这样的:
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}
谢谢你的耐心和细心~~ :)
那是我最原来的一个简单的示例,传string是ok的,就用最原始那个,现在我不是光传string,而是传一个结构,就出现了后来这一系列的问题.