C++基础(十五)C++ afx_msg消息处理详细分析:BEGIN_MESSAGE_MAP 、ON_WM_TIMER(&ReduceDB::OnTimer) 、ON_MESSAGE

本文详细介绍了在MFC框架下,如何使用afx_msg关键字定义消息及其处理函数,包括定时器消息、串口接收消息等。并通过实例展示了消息映射的使用方法,以及如何在代码中实现这些消息的响应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

       最近用到了获取,串口消息,消息处理主要用到了微软的<afxwin.h>头文件的afx_msg类。先调研一番消息处理函数,然后举例说明。那么我们分为下面几个步骤讨论MFC中afx_msg定义的消息。

步骤一:

         在头文件KGenDel.h中,用afx_msg定义消息及其格式

步骤二:

        在KGenDel.cpp中,使用 BEGIN_MESSAGE_MAP 启动消息及其格式,它的具体格式如下:

BEGIN_MESSAGE_MAP(KGenDel, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
        ON_WM_TIMER(&ReduceDB::OnTimer)  //启动定时器
	ON_MESSAGE(WM_COMM_RXCHAR, &KGenDel::OnComm)//单字节响应函数
	ON_BN_CLICKED(IDC_BUTTON1, &KGenDel::OnBnClickedButton1)
	ON_WM_CLOSE()
END_MESSAGE_MAP()

稍后我会解释每一行的代码。 

步骤三:

          在KGenDel.cpp中,对消息函数KGenDel::OnComm 和 ReduceDB::OnTimer进行实现

二、afx_msg定义消息及其格式

     afx_msg主要在MFC中应用,比较古老了。消息函数主要用到afx_msg关键字来定义。这几篇博客完美的解析了afx_msg关键字。

https://blog.youkuaiyun.com/holandstone/article/details/7452384

https://www.cnblogs.com/linkzijun/p/6196165.html

     那么,我把我项目中的KGenDel.h文件拿出来,分析下afx_msg及其格式。

KGenDel.h:

class KGenDel : public CDialogEx
{
    public:
	    KGenDel(CWnd* pParent = NULL);   // 标准构造函数
	    virtual ~KGenDel();
        //nIDEvent:是触发器的名字,启动定时器,间隔发指令给串口
        afx_msg void OnTimer(UINT_PTR  nIDEvent); 
        //接收来自串口的指令。
        afx_msg LRESULT OnComm(WPARAM ch, LPARAM port);
}

三、BEGIN_MESSAGE_MAP 启动消息及其格式

https://www.cnblogs.com/liangjq/p/4462926.html

https://blog.youkuaiyun.com/luoti784600/article/details/10070939

参看https://www.cnblogs.com/linkzijun/p/6196165.html,得到了在MFC界面中,按钮的点击消息,使得界面显示的结果得以改变,它提供的BEGIN_MESSAGE_MAP 格式如下:

而我的KGenDel.cpp用到的格式如下:

BEGIN_MESSAGE_MAP(KGenDel, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
        ON_WM_TIMER(&ReduceDB::OnTimer)  //启动定时器
	ON_MESSAGE(WM_COMM_RXCHAR, &KGenDel::OnComm)//单字节响应函数
	ON_BN_CLICKED(IDC_BUTTON1, &KGenDel::OnBnClickedButton1)
	ON_WM_CLOSE()
END_MESSAGE_MAP()

 那么你可以看到,格式大致相同。基类CWnd与基类CDialogEx不同,消息类型也有很多种,比如CHANGE、CLICKED、TIMER不同。

那么来解说下这样的结构。

1、BEGIN_MESSAGE_MAP(参数1,参数2):表示开启消息映射,参数1为该类的类名,参数2为该类基类的类名。

 https://www.cnblogs.com/liangjq/p/4462926.html

BEGIN_MESSAGE_MAP(CChileView, Cwnd)——CChileView.cpp类是继承Cwnd类,用来操作窗体。

BEGIN_MESSAGE_MAP(KGenDel, CDialogEx)——KGenDel.cpp类是继承CDialogEx类,用来操作对话框。

2、END_MESSAGE_MAP()——结束消息映射

3、ON_MESSAGE(参数1,参数2):参数1为响应的消息,参数2为该消息对应的处理的函数名。

ON_MESSAGE(WM_COMM_RXCHAR, &KGenDel::OnComm)—— 表示开启消息响应函数,一旦受到串口来的消息WM_COMM_RXCHAR(注意啊,WM_COMM_RXCHAR是一个消息,它由串口类触发),那么响应函数KGenDel::OnComm。这行代码就是用来接收串口传回来的指令。

4、ON_BN_CLICKED(参数1,参数2)—— 单击控件后,响应此消息。

5、ON_WM_TIMER(&ReduceDB::OnTimer) ——定时器。

四、消息函数KGenDel::OnComm 和 ReduceDB::OnTimer进行实现:工程中应用举例

1、.h文件中定义消息

LRESULT——表示长整数(默认)

WPARAM——表示长整数(默认)

LPARAM——表示短整数(默认)

ch——形参

port——形参

2、启动消息

BEGIN_MESSAGE_MAP(KGenDel, CDialogEx)——启动消息,KGenDel表示类。CDialogEx是系统生成了不知道啥意思。

ON_MESSAGE(WM_COMM_RXCHAR, &KGenDel::OnComm)——通过WM_COMM_RXCHAR与串口关联起来,一旦接收串口类的指令,则响应消息OnComm。事件上,OnComm是KGenDel.cpp的函数。

END_MESSAGE_MAP()——关闭

3、 消息函数的实现

定时器发消息给串口:

void KGenDel::OnTimer(UINT_PTR nIDEvent)
 {
	switch (nIDEvent)
	{
	case 1:
		Exposure();//检测高压命令
		//RetrErrorLog();//检索高压错误日志
		//ErrorParameters();//检查曝光参数错误
		//RetrieveExposure();//检索曝光结果
		break;
	default:
		break;
	}
}

注意啊, nIDEvent表示定时器的ID,因为一个系统可能要用多个定时器,所以,必须设置定时器的ID。

当ID = 1,那么我就启动第一个定时器,来处理第一件事情。

当ID = 2,那么我就启动第2个定时器,来处理第2件事情。

当ID = 3,那么我就启动第3个定时器,来处理第3件事情。

......

好了,那么,请问如何设置定时器?微软给我提供了SetTimer定时器:

int TimerID = 1;
SetTimer(TimerID, 200, NULL); 

200ms表示定时器的时间:每隔200ms让它执行Exposure()函数。

接收来自串口的消息:

//消息响应函数:
LRESULT KGenDel::OnComm(WPARAM ch, LPARAM port)
{
		if (16 > ch)
		{
			str.Format(_T("0%X "), ch);
		}
		else
		{
			str.Format(_T("%X "), ch);
		}
		m_RecvBuf += str;
		data[cnt] = ch;
		cnt++;
		
		BYTE *p = (BYTE*)&data;
		if (136 == data[12] && 240 == data[0]) //函数发送短命令
		{
			m_cLogger.WriteDebugLog("KGenDel::OnComm: 命令解析开始 ", 200);
			m_cLogger.WriteDebugLog("KGenDel:: OnComm:  " + m_RecvBuf, 200);
			m_RecvBuf.ReleaseBuffer();      //第一步清空函数内存,保证存取上一次数据
			m_RecvBuf.Empty();              //第二步清空函数内存,强制设置为空
			m_cLogger.WriteDebugLog("KGenDel::OnComm:  命令结束", 200);
		}
		if (136 == data[18] && 240 == data[0]) //函数发送长命令
		{
			m_cLogger.WriteDebugLog("KGenDel::OnComm: 命令解析开始 ", 200);
			m_cLogger.WriteDebugLog("KGenDel:: OnComm:  " + m_RecvBuf, 200);
			m_RecvBuf.ReleaseBuffer();
			m_RecvBuf.Empty();  
			m_cLogger.WriteDebugLog("KGenDel::OnComm:  命令结束", 200);
		}
		OnComm1();

	return 0;
}

4、串口类中,包含了WM_COMM_RXCHAR(虽然不知道串口怎么关联消息)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我爱AI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值