C#自定义消息通信往往采用事件驱动的方式实现,但有时候我们不得不采用操作系统的消息通信机制,例如在和底层语言开发的DLL交互时,是比较方便的。下面列举了一些实现方式,供大家参考:一、通过SendMessage或postmessage函数发送:

1、 定义消息
在C++中引用底层的函数很简单,自定义消息如下
#define WM_TEST WM_USER + 101
而在c#中消息需要定义成windows系统中的原始的16进制数字,比如自定义消息
public const int USER = 0x0400;

public const int WM_TEST =USER+101;

2、 发送消息
消息发送是通过windows提供的API函数SendMessage或postmessage来实现的,它的原型定义:

[DllImport("User32.dll",EntryPoint="SendMessage")]
private static extern int SendMessage(
IntPtr hWnd, // 窗体句柄
uint Msg, // 消息的标识符
uint wParam, // 具体取决于消息
uint lParam // 具体取决于消息
);

[DllImport("User32.dll",EntryPoint="PostMessage")]
private static extern int SendMessage(
IntPtr hWnd, // 接收消息的那个窗口的句柄。如设为HWND_BROADCAST,表示投递给系统中的所有顶级窗口。如设为零,表示投递一条线程消息(可参考PostThreadMessage)
uint Msg, // 消息的标识符
uint wParam, // 具体取决于消息
uint lParam // 具体取决于消息
);

至于两个函数的区别这里就不累述了,有兴趣的朋友可以自己查阅资料。

3、 消息接收
消息发出之后,在Form中如何接收呢?我们可以重载DefWinproc函数来接收消息。
protected override void DefWndProc ( ref System.Windows.Forms.Message m )
{
switch(m.Msg)
{
case Message.WM_TEST: //处理消息
break;
default:
base.DefWndProc(ref m); //调用基类函数处理非自定义消息。
break;
}
}

二、使用PostThreadMessage函数向线程发送消息

1、映射消息结构体原型和自定义消息

public struct tagMSG
{
public int hwnd;
public uint message;
public int wParam;
public long lParam;
public uint time;
public int pt;
}

public const int WM_CX_NULL = 0x400 + 100;

2、发送消息

[DllImport("user32.dll")]

private static extern int PostThreadMessage(

                  int threadId, //线程标识

                  uint msg, //消息标识符

                  int wParam, //具体由消息决定

                  int lParam); //具体由消息决定

此函数获取当前线程一个唯一的线程标识符,这点需要特别注意:Win32 API无法识别管理线程,你必须发送消息到Windows的线程ID上,而不是管理线程的ID上。

[DllImport("kernel32.dll")]

private static extern int GetCurrentThreadId();

因此发送消息过程如下:

private int _NewThreadId =GetCurrentThreadId();

PostThreadMessage(_NewThreadId, WM_CX_NULL, 1, 1);

3、接收消息

该函数从调用线程的消息队列里取得一个消息并将其放于指定的结构。此函数可取得与指定窗口联系的消息和由PostThreadMesssge寄送的线程消息。此函数接收一定范围的消息值。GetMessage不接收属于其他线程或应用程序的消息

[DllImport("user32.dll")]
private static extern int GetMessage(

                  ref tagMSG lpMsg, //指向MSG结构的指针,该结构从线程的消息队列里接收消息信息;

                  int hwnd, //取得其消息的窗口的句柄。这是一个有特殊含义的值(NULL)。GetMessage为任何属于调用线程的窗口检索消息;                                              int wMsgFilterMin, //指定被检索的最小消息值的整数

                  int wMsgFilterMax); //指定被检索的最大消息值的整数

接收实现如下:

public void ThreadExectue()
{
_NewThreadId= GetCurrentThreadId(); //发送线程和接收线程一定要是同一个线程,否则接收不到消息
while (GetMessage(ref msg, 0, 0, 0) > 0)
{
if (msg.message == WM_CX_NULL)
{
MessageBox.Show("消息收到!");
}
}
}

三、使用Application.AddMessageFilter拦截系统消息

1、实现消息过滤器接口

internal class MyMessager : IMessageFilter
{
//截取消息,进行处理
public bool PreFilterMessage(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case CUSTOM_MESSAGE:      //拦截自定义消息 
MessageBox.Show("消息收到!");
return true;    
default:
return false;     //返回false则消息未被裁取,系统会处理
}
}
}
2、安装消息过滤器
private void Form1_Load(object sender, EventArgs e)
{
Application.AddMessageFilter(new MyMessager());
}

实例代码:

C#简单实现自定义消息的发送和接收 收藏
//=================================发送窗口代码=============================

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

/*

制作人:林龙江

制作时间:2007年5月1日

只供参考,有错误之处请指出 !

*/

//手动加入的命名空间

using System.Runtime.InteropServices;

namespace SendCustomMessage

{

public partial class SendForm. Form

{

public SendForm(IntPtr Handle)

{

SendToHandle = Handle;

InitializeComponent();

}

private IntPtr SendToHandle;//这个变量用于保存要发送窗口的句柄

//自定义的消息

public const int USER = 0x500;

public const int MYMESSAGE=USER + 1;

//消息发送API

[DllImport("User32.dll", EntryPoint = "SendMessage")]

private static extern int SendMessage(

IntPtr hWnd, // 信息发住的窗口的句柄

int Msg, // 消息ID

int wParam, // 参数1

ref SENDDATASTRUCT lParam // 参数2 [MarshalAs(UnmanagedType.LPTStr)]StringBuilder lParam

);

//发关按钮

private void Send_Click(object sender, EventArgs e)

{

string myText = textBox1.Text;

byte[] myInfo = System.Text.Encoding.Default.GetBytes(myText);

int len = myInfo.Length;

SENDDATASTRUCT myData;

myData.dwData = (IntPtr)100;

myData.lpData = myText;

myData.DataLength = len + 1;

SendMessage(SendToHandle, MYMESSAGE, 100, ref myData);//发送自定义消息给句柄为SendToHandle 的窗口,

//本例为创建本窗口的窗口句,创建时,传递给本窗口的构造函数

}

}

//要发信息数据结构,作为SendMessage函数的LParam参数

public struct SENDDATASTRUCT

{

public IntPtr dwData; //附加一些个人自定义标志信息,自己喜欢

public int DataLength; //信息的长度

[MarshalAs(UnmanagedType.LPStr)]

public string lpData; //要发送的信息

}

}

//=============================接收窗口代码====================================

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

/*

制作人:林龙江

制作时间:2007年5月1日

只供参考,有错误之处请指出 !

*/

//手动加入的命名空间

using System.Runtime.InteropServices;

namespace SendCustomMessage

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

sendForm. = new SendForm(this.Handle);

sendForm.Show();

}

SendCustomMessage.SendForm. sendForm;

//自定义消息

public const int USER = 0x500;

public const int MYMESSAGE = USER + 1;

///重写窗体的消息处理函数DefWndProc,从中加入自己定义消息 MYMESSAGE 的检测的处理入口

protected override void DefWndProc(ref Message m)

{

switch (m.Msg)

{

//接收自定义消息MYMESSAGE,并显示其参数

case MYMESSAGE:

SendCustomMessage.SENDDATASTRUCT myData = new SendCustomMessage.SENDDATASTRUCT();//这是创建自定义信息的结构

Type mytype = myData.GetType();

myData = (SendCustomMessage.SENDDATASTRUCT)m.GetLParam(mytype);//这里获取的就是作为LParam参数发送来的信息的结构

textBox1.Text = myData.lpData; //显示收到的自定义信息

break;

default:

base.DefWndProc(ref m);

break;

}

}

}

}

c# 如何处理自定义消息的更多相关文章

  1. ASP.NET Core应用针对静态文件请求的处理[3]: StaticFileMiddleware中间件如何处理针对文件请求

    我们通过<以Web的形式发布静态文件>和<条件请求与区间请求>中的实例演示,以及上面针对条件请求和区间请求的介绍,从提供的功能和特性的角度对这个名为StaticFileMidd ...

  2. Nginx如何处理一个请求

    看了下nginx的官方文档,其中nginx如何处理一个请求讲解的很好,现在贴出来分享下.Nginx首先选定由哪一个虚拟主机来处理请求.让我们从一个简单的配置(其中全部3个虚拟主机都在端口*:80上监听 ...

  3. ASP.NET Core管道深度剖析(3):管道是如何处理HTTP请求的?

    我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成,所以从总体设计来讲是非常简单的,但是就具体的实现来说,由于其中涉及很多对象的交互,我想很少人能够地把它弄清楚.为了让读者 ...

  4. 【WP8.1】类似“IT之家” 自定义消息 的实现

    曾经在WP7.WP8下的消息 使用的都是Coding4Fun.Phone.Toolkit里面的ToastPrompt类来实现的. 现在我们来自己做个类似IT之家的这种效果:从右边弹出,经过几秒后会自动 ...

  5. ENode框架Conference案例分析系列之 - 事件溯源如何处理重构问题

    前言 本文可能对大多数不太了解ENode的朋友来说,理解起来比较费劲,这篇文章主要讲思路,而不是一上来就讲结果.我写文章,总是希望能把自己的思考过程尽量能表达出来,能让大家知道每一个设计背后的思考的东 ...

  6. MFC用户自定义消息

    之前做过佳能相机和位移平台的额二次开发,当时遇到一个棘手的问题,就是位移平台如何知道相机已经拍完照了,或者相机如何知道位移平台已经运行到指定位置,当时为了方便采用了定时器来定时检测位移平台的位置,结果 ...

  7. postgresql是如何处理死连接(转)

    在数据库postgresql中,一个客户端到服务器连接实际上是一个tcp socket连接,tcp连接是虚连接,一方非正常退出(如断电),另一方会继续维持这个连接.   举个例子,一个客户端电脑正常连 ...

  8. (转)如何处理iOS中照片的方向

    如何处理iOS中照片的方向 31 May 2015 • 7 min. read • Comments 使用过iPhone或者iPad的朋友在拍照时不知是否遇到过这样的问题,将设备中的照片导出到Wind ...

  9. 新增资产时YTD折旧与累计折旧录入错误如何处理

    如新增资产时YTD折旧与累计折旧录入错误,但资产已入账处理,如何处理: 1.需要先报废资产: 2.需要在总账手工帐冲销未冲抵凭证: 3.重新增加资产,录入资产时YTD折旧及累计折旧金额应为0.  

随机推荐

  1. andriod开发,简单的封装网络请求并监听返回.

    一.为什么封装 因为android 4.0 以后的发送网络请求必须要放到异步线程中,而异步线程必须跟handle合作才能更新主线程中的UI,所以建议用一个类继承handler来异步处理网络请求. 二. ...

  2. 参数对象Struts2中Action的属性接收参数

    题记:写这篇博客要主是加深自己对参数对象的认识和总结实现算法时的一些验经和训教,如果有错误请指出,万分感谢. Action中三种传递并接受参数: 1.  在Action添加成员属性接受参数 例如请求的 ...

  3. Android使用百度定位SDK 方法及错误处理

    之前我的项目中的位置定位使用的是基站方法,使用的Google提供的API,但是前天中午突然就不返回数据了,到网上搜了一下才知道,Google的接 口不提供服务了,基于时间紧迫用了百度现有的SDK,但是 ...

  4. Java log code example

    Java log example Logrecord filter import java.util.logging.Filter; import java.util.logging.Level; i ...

  5. iOS开发——UI_swift篇&UItableView实现移动单元格

    UItableView实现移动单元格   1,下面的样例是给表格UITableView添加单元格移动功能: (1)给表格添加长按功能,长按后表格进入编辑状态 (2)在编辑状态下,可以看到单元格后面出现 ...

  6. 使用命令xrandr设置当前系统的显示分辨率及显示的旋转脚本

    /*********************************************************************  * Author  : Samson  * Date   ...

  7. 使用Jquery+EasyUI进行框架项目开发案例解说之中的一个---员工管理源代码分享

    使用Jquery+EasyUI 进行框架项目开发案例解说之中的一个 员工管理源代码分享 在開始解说之前,我们先来看一下什么是Jquery EasyUI?jQuery EasyUI是一组基于jQuery ...

  8. Asp.Net+Extjs实现登录

    通过对Ext的学习,发现学习分三部曲:1.看官网的Demo,宏观了解Ext能做什么:2.看相关书籍,做理论指导:3.实现官网的Demo,体会Ext的真谛. 在完毕了第一.二部后,如今我们须要做的是实现 ...

  9. BI之ETL学习(一)kettle

    最近开始折腾数据,起源是多业务数据源需要转换到数据分析平台.这个过程需要跨机器,跨库.同时还需要将业务数据表的内容进行转换,合并,清洗等等操作. 经过多方选型,最终决定使用kettle来作为数据抽取处 ...

  10. RPC框架Thrift例子-PHP调用C++后端程序

    更新 2016-02-22: Response对象不用主动创建. 前言 前段时间用了一下Facebook的开源RPC框架Thrift,做PHP客户端调用C++后端程序,真心觉得Thrift不错! 本文 ...