win窗口之间的消息交互

有时候,开发一个桌面程序,经常会出现很多窗体,而一个窗体比如说设置窗体生效后,对应的其他窗体要能够同步反映最新的变化。利用委托与事件机制是一种非常好的方式。但是这里介绍的却是通过消息机制来实现。

本人对这方面了解的不够深入,但是能做些简单的应用。

先来看看例子:

 image

点击Form2与Form3按钮,分别show()方式出对应窗口,窗口中有发送按钮实现发送消息给Form1。

image 点击发送消息按钮:

image

明白两件事情,就知道如何应用了。

首先理解:

protected override void WndProc(ref Message m)

 

 

怎么说了:你在该控件(窗口)中做的所有事情其实都变成了消息m,然后这个m被发配到了这个方法,来接受处理。

我们需要重载下(override),因为有些自定义的消息需要处理。

Message可以查看定义,反正属性都比较重要:

image

还是看Form1重载的WndProc吧!

image

第一件事情ok了,剩下的就是其他窗口如何发消息给Form1了。

第二件事情,调用API--SendMessage

[DllImport("user32.dll", CharSet = CharSet.Auto)] 
       public static extern int PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

注意需要引用:using System.Runtime.InteropServices;

发送消息的Api选择了PostMessage,其它的我忘记了,这个可以用。

注意第一个参数:hwnd,表示 接收消息的窗口句柄。(Form1实例化对象form1.Handle)。

然后调用: PostMessage(form1.Handle, 5678, 0, 0);

就这么简单。

当然,为了以后扩展方便,这里建立了类:WinManagerMsg,这里只抛砖引玉供大家参考:

 

View Code
 1 public enum Form1MessageMethod 
2 {
3 Form1=1, 消息响应1 = 5678, 消息响应2 = 8765
4 }
5
6 class WinManagerMsg
7 {
8 [DllImport("user32.dll", CharSet = CharSet.Auto)]
9 public static extern int PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
10
11 private static SortedList<string, IntPtr> handlers=new SortedList<string,IntPtr>();
12 public static void Add(string winName,IntPtr winHandle)
13 {
14 if (handlers.ContainsKey(winName)) return;
15 handlers.Add(winName,winHandle);
16 }
17 /// <summary>
18 /// 根据窗口名获得对应的句柄
19 /// </summary>
20 /// <param name="winName"></param>
21 /// <returns></returns>
22 public static IntPtr GetHandler(string winName)
23 {
24 if (handlers.ContainsKey(winName)) return handlers[winName];
25 return IntPtr.Zero;
26 }
27 public static int SendMessage(string winName, Message m)
28 {
29 return PostMessage(GetHandler(winName), m.Msg,m.WParam,m.LParam);
30 }
31 /// <summary>
32 /// 根据句柄获得窗口名
33 /// </summary>
34 /// <param name="winHandle"></param>
35 /// <returns></returns>
36 public static string GetWinName(IntPtr winHandle)
37 {
38 string result = "未知窗口";
39 for (int i = 0; i < handlers.Values.Count; i++)
40 {
41 if (handlers.Values[i] == winHandle) return handlers.Keys[i];
42 }
43 return result;
44 }
45
46 public static int SendMessage(Form1MessageMethod msgParam)
47 {
48 string winName= Enum.GetName(typeof(Form1MessageMethod), 1);
49 int msgValue = (int)msgParam;
50 return SendMessage(winName, Message.Create(GetHandler(winName), msgValue, IntPtr.Zero, IntPtr.Zero));
51 }
52 /// <summary>
53 /// 告诉接收消息的窗体该消息来自哪个窗口
54 /// </summary>
55 /// <param name="msgParam"></param>
56 /// <param name="msgSrc">消息来源的窗口(发送消息窗口)的句柄</param>
57 /// <returns></returns>
58 public static int SendMessage(Form1MessageMethod msgParam,IntPtr msgSrc)
59 {
60 string winName = Enum.GetName(typeof(Form1MessageMethod), 1);
61 int msgValue = (int)msgParam;
62 return SendMessage(winName, Message.Create(GetHandler(winName), msgValue, IntPtr.Zero, msgSrc));
63 }
64
65 }

 

 

Form1的WndProc对应修改如下:

View Code
 1 protected override void WndProc(ref Message m) 
2 {
3 switch (m.Msg)
4 {
5 case (int)Form1MessageMethod.消息响应1:
6 this.Text =string.Format( "接收到了窗口{0}发来的消息 ",
7 WinManagerMsg.GetWinName(m.LParam))+DateTime.Now.Millisecond.ToString();
8 return;
9 case (int)Form1MessageMethod.消息响应2:
10 this.Text = string.Format("接收到了窗口{0}发来的消息 ",
11 WinManagerMsg.GetWinName(m.LParam)) + DateTime.Now.Millisecond.ToString();
12 return;
13 }
14 base.WndProc(ref m);
15 }


 

Form3发消息的按钮Click:

private void button1_Click(object sender, EventArgs e)
        {
            WinManagerMsg.SendMessage(Form1MessageMethod.消息响应2,this.Handle);
        }

 

每个窗口的加载事件:

private void Form?_Load(object sender, EventArgs e)
        {
            WinManagerMsg.Add(this.Name, this.Handle);
        }

 

如果不同的应用程序之间互发消息,留给以后作为扩展,现在还没有继续深入!

posted @ 2012-03-11 17:53  net小虫  阅读(325)  评论(0编辑  收藏  举报