首先自定义一个消息ID: UM_TEST,用于测试SendMessage和PostMessage的在发生该消息的具体区别,我们在主框架的OnCreate函数中实现该消息的测试,相关说明如下:
消息映射:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() .... ON_MESSAGE(UM_TEST, &OnTest)//自定消息END_MESSAGE_MAP()函数声明:
对于自定义的消息,其函数声明必须是LRESULT类型,第一参数是WPARAM,第二参数是LPARAM,如下所示:
afx_msg LRESULT OnTest(WPARAM wParam, LPARAM lParam);函数实现:
LRESULT CMainFrame::OnTest(WPARAM wParam, LPARAM lParam){ MessageBox("Process Msg Sucess"); return 0;}OnCreate消息响应函数:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){ if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("未能创建工具栏\n"); return -1; // 未能创建 } ...//中间省略 SendMessage(UM_TEST, 0, 0); return 0;}
过程分析:
我们首先在SendMessage()函数和return0两行分别打上断点,同时在OnTest消息响应函数体内打一个断点,F5 Debug执行代码,可以发现函数执行大致流程是:
SendMessage()->OnTest函数->SendMessage的下一句(return 0).
而如果将SendMessage改成PostMessage程序执行大致流程:
SendMessage()->SendMessage的下一句(return 0)->OnTest函数。
总结:
从程序的执行顺序可以看出,当前程序会将SendMessage的消息处理完毕后,才会返回;而PostMessage只是将消息投递到线程的消息队列中,就立即返回。下一时刻该消息才从消息队列中取出,由对应的消息处理程序处理。
运行效果:
对于SendMessage,如果我们不将“Process Msg Sucess”模态窗口点击确定,程序会一致阻塞在OnTest函数体内,不会往下执行;点击确定后,主框架窗口才会显示出来。
对于PostMessage而言,主框架窗口完成显示后,提示框的窗口也显示出来了,两者有一定的先后顺序。
从执行效果上看,就可以明白SendMessage 是同步的,具有阻塞性质,而PostMessage是异步的,没有阻塞性质。