WINDOWS下,窗口之间的通信

首先说一下,因为我写的东西很杂,所以不细分类别,也不指明是那种语言写的,但干我们这行的应该能一眼看出用什么语言写的。呵呵
 

进程之间通讯的几种方法:

在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯。常用的方法有

  使用内存映射文件
  通过共享内存DLL共享内存
  使用SendMessage向另一进程发送WM_COPYDATA消息

比起前两种的复杂实现来,WM_COPYDATA消息无疑是一种经济实惠的一中方法. 

 
这里就简单讲一下,首先是调用WINDOWS API
 
::FindWindow,原型如下
 
FindWindowA(
    __in_opt LPCSTR lpClassName,
    __in_opt LPCSTR lpWindowName);
 
第一个参数表示窗口派生类的名字,第二个参数是窗口的名字,这两个参数可以通过vs工具中的spy++获得。
 
用法:HWND hWnd = ::FindWindow(NULL,"ePhone");(这是我ePhone项目中窗口的名字);
 
得到窗口句柄然后发送消息,发送消息有两种选择:
::SendMessage
原型
SendMessageA(
    __in HWND hWnd,
    __in UINT Msg,
    __in WPARAM wParam,
    __in LPARAM lParam);
第一个参数是控制句柄,通过FindWindow可以拿到,第二个参数是消息类型,第三,四个参数是附加消息。
 
这里我讲我用过的消息类型,自定义消息。
 
#define WM_COPYDATA                     0x004A
 
根据定义看到该自定义消息十六进制代码是0x004A,也就是说如果如我项目一样用其他程序(C#,JAVA)来接受这个自定义消息类型,则需要在程序中定义该变量,名字不重要,
但后面的十六进制代码必须一致。
 
一下是传递数据的结构:
typedef struct tagCOPYDATASTRUCT {
    ULONG_PTR dwData;
    DWORD cbData;
    PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
 
COPYDATASTRUCT为结构名,可以直接用来声明结构变量,如COPYDATASTRUCT cpd;
其中有三个参数,第一个从名字上就知道是长整数指针类型,这个参数指定要发送的数据类型,这个完全可以自己定义
                        第二个是发送数据的大小,这个要相当准确,否则接受方无法分配合适的数据块大小,导致接受数据失败
                        第三个是关键,发送到指定程序的数据的指针,就是上面定义的cpd数据块的其实地址。
举个例子:
 
COPYDATASTRUCT cpd;
 cpd.dwData = LOCATION; //标志为LOCATION类型,这个LOCATION是我自己定义的#define LOCATION 1
 cpd.cbData = sizeof(COPYDATASTRUCT); //要传输数据结构的大小
 cpd.lpData = (LPVOID) data;//要传输数据的指针
 
这里的data也是我自己定义的一个结构,看例子
struct location
 {
  ATW_TUNER_EVENT movement;
  int x;
  int y;
 };
 location * data = new location();
 
这样看下来就可以知道COPYDATASTRUCT 是本身winuser.h文件中定义的数据结构,用来发送自定义消息,而具体我要发送的数据又是我自己定义的一个结构
也就是包了两层发送出去。接下来看怎么发
::SendMessage(hWnd,WM_COPYDATA,(WPARAM)NULL,(LPARAM)& cpd);
这里的cpd我给的还是引用,传的是地址,也就是这个数据结构块。发送到指定的句柄。发送完了不要忘记释放刚才声明的 data。
 
再来是怎么收
收是发的逆过程,也就是拆包。同样你需要在接受端定义COPYDATASTRUCT 数据结构, 然后把接到的数据还原,也就是拆箱的过程
例如:
COPYDATASTRUCT *pCopyDataStruct
location *data = (location*)(pCopyDataStruct->lpData);
 
然后再拆,这里不细说。看到这里有人会问,那么我在哪里来写这段程序呢?这里本人只能给出在C#中的例子,不过相信在C/C++中也有相应的方法。
方法就是重写消息处理函数,每个FORM都会有这个函数。C#中:
protected override void WndProc(ref Message m);
在网上也可能看到
protected override void DefWndProc(ref Message m)看名字就是消息处理定义,具体读者可以自己去试验,我用的是上一个函数。
这里的 m 参数就是指定窗体接收到的消息。看例子:
protected override void WndProc(ref Message m)
        {
          
            if (m.Msg == WM_COPYDATA)
            {
               //这里就是具体你想做的事……
            }
            else//其他消息扔给父类自己处理
                base.WndProc(ref m);
        }
 
好了,大致就是这些内容,毕竟本人水平有限,还是个菜鸟,详情还是参见MSDN,希望这些对朋友有些帮助。
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DockPanel Suite 是一个用于 Windows 窗体应用程序开发的开源工具包,它提供了一个易于使用的 Docking 系统,可以为应用程序提供多窗口管理功能。如果要实现多个窗口之间通信,可以通过使用事件和委托来实现。 具体来说,可以在窗口类中定义事件,当事件被触发时,可以调用委托将数据传递给其他窗口。例如,假设我们有两个窗口 A 和 B,窗口 A 中定义了一个事件 MyEvent,我们可以在窗口 B 中订阅这个事件,然后在窗口 A 中触发这个事件,并传递需要传递的数据。代码示例: 在窗口 A 中定义事件: ``` public class WindowA : DockContent { public delegate void MyEventHandler(object sender, MyEventArgs e); public event MyEventHandler MyEvent; private void OnMyEvent() { if (MyEvent != null) { MyEventArgs args = new MyEventArgs(); args.Data = "Hello, World!"; MyEvent(this, args); } } // 触发事件的代码 private void button1_Click(object sender, EventArgs e) { OnMyEvent(); } } public class MyEventArgs : EventArgs { public string Data { get; set; } } ``` 在窗口 B 中订阅事件: ``` public class WindowB : DockContent { private void WindowB_Load(object sender, EventArgs e) { WindowA windowA = new WindowA(); windowA.MyEvent += new WindowA.MyEventHandler(windowA_MyEvent); } private void windowA_MyEvent(object sender, MyEventArgs e) { MessageBox.Show(e.Data); } } ``` 这样,在窗口 A 中触发 MyEvent 事件时,窗口 B 就可以接收到事件并处理数据了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值