窗口消息按照消息的来源可以分为系统定义的消息和应用程序自定义的消息。系统消息编号的范围是0 ~ WM_USER-1,应用程序自定义消息是WM_USER ~ 0x7FFF,WM_USER的数值是1024(0x400)。常用的一些消息,如WM_CLOSE(0x0010)、WM_MOUSEMOVE(0x0200)等都属于系统消息。
1)SendMessage和PostMessage函数都是消息传递函数。
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
2)SendMessage和PostMessage这两个函数消息的区别如下。
- 返回值类型不同。2个函数的4个参数的意义是一样的,只有返回值类型不同,LRESULT表示消息被处理后的返回值,BOOL表示消息是否传递成功。
- PostMessage是异步的,SendMessage是同步的。PostMessage只把消息放入窗口消息队列中,不管消息被处理后的结果就返回;而SendMessage等待消息被处理完了以后才返回。
- 如果在同一个线程内,则经常使用SendMessage发送消息,速度快并能得到返回消息处理结果。在不同线程或者进程之间,一般使用PostMessage发送消息,把消息先放入目标窗口的消息队列中,然后由目标窗口通过消息循环自行派发处理。
3)新建一个Win32工程,编写一段简单的代码测试消息传递函数。
在不同进程之间,经常使用PostMessage发送命令或者传递数据。
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
//查找一个记事本窗口
HWND hWnd = FindWindow("NotePad",NULL);
if(hWnd)
PostMessage(hWnd,WM_CLOSE,0,0);//发送一个关闭窗口的消息
return 0;
}
4)MFC封装后的传递函数。
LRESULT SendMessage(UINT message,WPARAM wParam=0,LPARAM lParam=0);
BOOL PostMessage(UINT message,WPARAM wParam=0,LPARAM lParam=0);
在MFC工程中调用。
CWnd* p = FindWindow("NotePad",NULL);//查找一个记事本的窗口
if(p)
p->PostMessage(WM_CLOSE);//发送一个关闭窗口的消息
MFC在CWnd类中封装了以上两个函数带有两个默认参数使用起来更加方便。在MFC工程中也可以使用上面的Win32函数,通过窗口句柄传递消息。在MFC中调用Win32函数时,函数名前经常要使用空定义域符号"::",这是C++用于区别全局函数和成员函数的标志。
HWND hWnd = ::FindWindow("NotePad",NULL);//查找一个记事本的窗口
if(hWnd)
::PostMessage(hWnd,WM_CLOSE,0,0);//发送一个关闭窗口的消息
5)接受自定义消息
在Win32程序中只要在回调函数中使用分支语句,即可接收并处理自定义消息。在MFC程序中,必须使用ON_MESSAGE来关联消息映射函数,它是用于处理用户自定义消息的。接收自定义消息的函数,即ON_MESSAGE的消息映射函数,必须完全符合以下定义。
afx_msg LRESULT OnTestSend(WPARAM wParam,LPARAM lParam);
6)定义一个自定义消息函数
- 定义宏
#define WM_TEST_SEND (WM_USER + 1)
- 声明并实现自定义消息函数
protected:
//自定义消息回调函数
afx_msg LRESULT OnTestSend(WPARAM wParam,LPARAM lParam);
LRESULT CSoftKeyboardDlg::OnTestSend(WPARAM wParam, LPARAM lParam)
{
CString str = (LPCTSTR)wParam;
return wParam + lParam;
}
- 绑定消息和回调函数
BEGIN_MESSAGE_MAP(CSoftKeyboardDlg, CDialogEx)
ON_MESSAGE(WM_TEST_SEND,OnTestSend) //绑定自定义消息回调函数
END_MESSAGE_MAP()
7)用SendMessage发送数据
//得到父窗口句柄
HWND hWnd = m_pParent->GetSafeHwnd();
if (!hWnd)
return;
//发送消息
CString str = _T("0");
WPARAM wParam = (WPARAM)(LPCTSTR)str;
LPARAM lParam = 0;
LRESULT nRt = ::SendMessage(hWnd, WM_TEST_SEND, wParam, lParam);