MFC中的消息发送与响应
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MFC中的消息发送与响应
1. 主窗口向子窗口发送消息:
/phenixyf/article/details/9300425
从主窗口向子窗口发送消息,可以在子窗口中添加自定义的消息,然后在主窗口中需要地方呼叫该消息。
呼叫方法:
1.将子窗口添加为主窗口的成员变量;
2.主窗口呼叫该消息,成员变量名.SendMessage(UM_PROGRESS);
子窗口添加自定义消息步骤如下:
1、定义消息。
在Windows中,所有的消息都用一个特定的整数值来表示,为了避免自定义消息与已存在的其他消息发生冲突,应该利用Windows提供的一个常量:WM_USER,小于这个常量的是系统保留的。
即用户自定义的消息至少为WM_USER+1,注意最后表示的消息的数值不要超过0x7FFF。
在开发Windows95应用程序时,Microsoft推荐用户自定义消息至少是WM_USER+100,因为很多新控件也要使用WM_USER消息。
#define UM_PROGRESS WM_USER + 100
将上句添加到子窗口类的头文件(.h)中。
2、在子窗口类头文件的AFX_MSG块中声明消息处理函数:
class CMainFrame:public CFrameWnd{
protected:
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg LRESULT OnProgress(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
3、在子窗口类的实现文件(.cpp)中,使用ON_MESSAGE宏指令将消息映射到消息处理表中。
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_WM_TIMER()
ON_MESSAGE(UM_PROGRESS, OnProgress)//注意这条语句的后面没有分号
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
4、实现消息处理函数。
该函数使用WPRAM和LPARAM参数并返回LPESULT。
LRESULT CMainFrame::OnProgress(WPARAM wParam,LPARAM lParam){
CRect rect;
m_wndStatusBar.GetItemRect(2,&rect); //获得窗格区域
//创建进度栏,注意第三个参数为CWnd* pParentWnd,根据情况选择父窗体
m_progress.Create(WS_CHILD|WS_VISIBLE|PBS_VERTICAL,rect,this,123);
m_progress.SetPos(50);
return 0;
}
5、在适当的时候发送自定义消息,进行消息处理。
需要注意使用SendMessage还是PostMessage进行处理:SendMessage是消息处理完毕后再返回;而PostMessage则是把消息放到消息队列后立即返回。
SendMessage(UM_PROGRESS);
PostMessage(UM_PROGRESS);
如果用户需要整个系统唯一的消息,可以调用SDK函数RegisterWindowMessage并使用ON_REGISTER_MESSAGE宏指令取代ON_MESSAGE宏指令,其余步骤同上。
2. 子窗口向主窗口发送消息:
2.1 子窗口向主窗口发送一个消息
在MFC中,使用用户自定义消息,子窗口向父窗口发送消息过程、代码:
1)在resourse.h中增加定义:
//#define WM_add_event_ok (WM_USER + 100) //这种定义方法没有测试,不知道行不行;static UINT WM_add_event_ok = RegisterWindowMessage(_T("User"));//测试过,可行。
2)在父窗口的.h文件中,增加定义:
protected:
afx_msg LRESULT Onadd_event_ok(WPARAM wParam, LPARAM lParam);
两个参数:WPARAM wParam, LPARAM lParam类型不能更改。
3)在父窗口的.cpp文件中增加消息映射部分:
//ON_MESSAGE(WM_add_event_ok, Onadd_event_ok) //没有测试过,不知道是否可行;ON_REGISTERED_MESSAGE(WM_add_event_ok,Onadd_event_ok)//测试通过,可行。
4)在父窗口的.cpp中定义消息处理函数的实现:
LRESULT 类名::Onadd_event_ok(WPARAM wParam, LPARAM lParam)
{
int c=10;
return 0;
}
5)在需要发送消息处使用代码:
WPARAM a=8;
LPARAM b=9;
GetParent()->SendMessage(WM_add_event_ok,a,b);
//或使用如下代码发送消息:
HWND hwnd = ::GetParent(m_hWnd);
::SendMessage(hwnd,WM_add_event_ok,a,b);
//SendMessage(WM_add_event_ok,a,b);//在测试中,不使用GetParent()->的时候,消息无法传递到父窗口的消息处理函数中,只有增加了GetParent()->后,消息才能成功的发送。
2.2 Tab子窗口向主窗口发送多个消息
/phenixyf/article/details/16872615
1. 在Resource.h文件中定义消息
[cpp]view plaincopy
1.#define WM_OpenComm_event WM_USER + 101
2.#define WM_CommTx_event WM_USER + 102
注意,当新增加控件后,这些在Resouce.h中添加的语句会被清除,需重新再添加一次。
2. 在父窗口的.h文件,类定义中添加对应的消息处理函数,作为类的成员函数:
[cpp]view plaincopy
1.afx_msg LRESULT OnOpenComm(WPARAM wParam, LPARAM iParam);
2.afx_msg LRESULT OnCommTx(WPARAM wP, LPARAM iP);
3. 在父窗体的.cpp文件中,增加各消息的消息映射
[cpp]view plaincopy
1.ON_MESSAGE(WM_OpenComm_event, OnOpenComm)
2.AGE(WM_CommTx_event, OnCommTx)
4. 完成消息对应处理函数的内容:
[cpp]view plaincopy
1.LRESULT CPCR_ChipDlg::OnCommTx(WPARAM wP, LPARAM iP)
2.{
3.// SendCom(dataNum);
4.
5. AfxMessageBox("Receive Message");
6.
7.return 0;
8.}
[cpp]view plaincopy
1.LRESULT CPCR_ChipDlg::OnOpenComm(WPARAM wParam, LPARAM iParam)
2.{
3.//open com
4.if(m_ctrlComm.GetPortOpen())
5. m_ctrlComm.SetPortOpen(FALSE);
6. m_ctrlComm.SetCommPort(ComNum); // 打开串口
7.if(!m_ctrlComm.GetPortOpen())
8. m_ctrlComm.SetPortOpen(TRUE);
9.else
10. AfxMessageBox("can not open serial port");
11.
12. m_ctrlComm.SetSettings("9600,n,8,1"); //波特率9600,无校验,8个数据位,1
个停止位
13. m_ctrlComm.SetInputMode(1); //1:表示以二进制方式检取数据
14.
15.// m_ctrlComm.SetRThreshold(1); //参数1表示每当串口接收缓冲区
中有多于或等于1个字符时将引发一个接收数据的OnComm事件
16. m_ctrlComm.SetRThreshold(ComByteNum); //本案一个包有35个有效字
节
17.//定接收33个字符时引发OnComm事件
18.
19.// m_ctrlComm.SetInputLen(1); //设置当前接收区数据长度为0
20. m_ctrlComm.SetInputLen(ComByteNum); //本案中设置接收buffer数
据长度为33
21. m_ctrlComm.GetInput();//先预读缓冲区以清除残留数据
22.
23. AfxMessageBox("Open Comm successfully");
24.
25.return 0;
26.}
注意,函数最后要加return 0;
5. 在子对话框需要发送消息的地方,执行发送消息语句:
[cpp]view plaincopy
1. <span style="color:#000000;">WPARAM a=8;
2.LPARAM b=9;
3.HWND hwnd = AfxGetApp()->GetMainWnd()->GetSafeHwnd();
4.
5. ::SendMessage(hwnd,WM_CommTx_event,a,b);
6.</span>
重要:
WPARAM a=8;LPARAM b=9;
HWND hwnd = AfxGetApp()->GetMainWnd()->GetSafeHwnd();
::SendMessage(hwnd,WM_CommTx_event,a,b);
2.3 Tab子窗口向主窗口发送消息注意事项
/phenixyf/article/details/16871623
子对话框向主对话框发送消息的详细操作,参考下面链接文章:
/phenixyf/article/details/11383509
当子对话框的属性->样式选择的是弹出时,可以使用上面的方法完成子对话框到主对话框的消息发送。
但当使用Tab控件后,各子对话框的属性->样式均必须被设置成下层(child),
上面的方法就要做适当的改动:
在上面文章方法最后步骤的消息发送部分,如果子对话框属性为弹出,则可以直接使用GetParent()->SendMessage(WM_add_event_ok,a,b);
而当子对话框属性为下层(child)时,GetParent()函数并不能得到主对话框的句柄,所以使用该语句,无法发送消息给主对话框。
使用下面的语句完成消息发送:
HWND hwnd = AfxGetApp()->GetMainWnd()->GetSafeHwnd();
::SendMessage(hwnd,WM_add_event_ok,a,b);
通过AfxGetApp()->GetMainWnd()->GetSafeHwnd();可以得到主对话框的句柄,然后再用SendMessage发送对应到消息到对应的主对话框。