最近由于项目要用到C#,所以最近学了一下C#,其中别人的代码里面用了 自定义消息,不过他们的代码是半开源,所以为了验证他们程序的传递机制,我自己写了一个Demo,学习了一下这
最近由于项目要用到C#,所以最近学了一下C#,其中别人的代码里面用了 自定义消息,不过他们的代码是半开源,所以为了验证他们程序的传递机制,我自己写了一个Demo,学习了一下这种机制。
主要是两个函数:
//发送消息
public static extern void PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);
//处理消息
protected override void DefWndProc(ref System.Windows.Forms.Message m)
发送消息
我自己写了一个类,专门用来进行类之间的消息传递
源代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;//DLLImport
namespace WindowsFormsApplication1
{
//用于向窗口发送消息的类
public class MsgGenerator
{
[DllImport("user32.dll")]
public static extern void PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);
/// <summary>
/// 存放窗口的句柄
/// </summary>
private static List<IntPtr> m_hWndList = new List<IntPtr>();
/// <summary>
/// 加载窗口的句柄
/// </summary>
/// <param name="hWnd"></param>
public static void AddHandle(IntPtr hWnd)
{
if (null != hWnd)
{
m_hWndList.Add(hWnd);
Debug.WriteLine("After Add:");
for (int i=0;i<m_hWndList.Count;i++)
{
Debug.WriteLine("List[{0}] = {1}",i,m_hWndList[i]);
}
Debug.WriteLine("Over!\n");
}
}
public static void RemoveHandle(IntPtr hWnd)
{
if (null != hWnd)
{
m_hWndList.Remove(hWnd);
}
Debug.WriteLine("After Remove:");
for (int i = 0; i < m_hWndList.Count; i++)
{
Debug.WriteLine("List[{0}] = {1}", i, m_hWndList[i]);
}
Debug.WriteLine("Over!\n");
}
public static void PostMsg2All(int msg, int wParam, int lParam)
{
for (int i = 0; i < m_hWndList.Count; i++)
{
if (null != m_hWndList[i])
{
PostMessage(m_hWndList[i], msg, wParam, lParam);
}
}
}
}
}
详解
首先要导出 Windows API 的发送消息函数
[DllImport("user32.dll")]
public static extern void PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);
然后,我定义了一个静态的指针列表,用于存放窗口的句柄。
private static List<IntPtr> m_hWndList = new List<IntPtr>();
最后定义了3个静态的成员函数,用于窗口句柄的添加、删除,以及向存储句柄的窗口发送消息的函数。
//添加窗口句柄
public static void AddHandle(IntPtr hWnd);
//删除窗口句柄
public static void RemoveHandle(IntPtr hWnd);
//给存储句柄对应的窗口发送消息
public static void PostMsg2All(int msg, int wParam, int lParam);
成员函数使用
添加句柄
在窗口Load事件对应的处理函数中,添加窗口句柄
MsgGenerator.AddHandle(this.Handle);//将窗口句柄加入MsgGenerator
删除句柄
在窗口Closed事件对应的处理函数中,删除窗口句柄
MsgGenerator.RemoveHandle(this.Handle);
发送消息
MsgGenerator.PostMsg2All((MSG.WM_USER + 1), 90, 8000);
接收消息
接收消息要重写 DefWndProc() 函数,而且要注意不要干扰其他消息的响应。
源代码
protected override void DefWndProc(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case (MSG.WM_USER + 1):
string message = string.Format("收到消息的参数:{0},{1}\n收到的时间:{2}", m.WParam, m.LParam, DateTime.Now.ToLongTimeString().ToString());
//MessageBox.Show(message, this.Text);
Label_Child.Text = message;
break;
default:
base.DefWndProc(ref m);//一定要调用基类函数,以便系统处理其它消息。
break;
}
}
其中这个 MSG.WM_USER 也是我自定义的一个类,代码如下
namespace WindowsFormsApplication1
{
public class MSG
{
public const int WM_USER = 0x0400;//自定义消息
}
}
解释
我的接收到我自定义的消息后,我就让窗口在Label控件上显示收到的消息以及对应的时间,上图所示,我向两个窗体都发送了相同的消息,所以才有那样的效果。