和其它消息通信的区别:
WM_* 只用于windows预定义的消息,都有特定的含义;
WM_USER+* 只能用于窗口过程(即通信目标必须是窗口类注册的窗口),否则无效;
WM_COPYDATA 是一个特殊的WM_*消息,但只用于同步通信,必须使用SendMessage。
注册消息:比WM_USER+*更灵活,常用于多个进程同时处理统一个消息(注意是进程而不只是窗口)。
发送方和接收方都需要做的:
// 1、定义注册消息:参数字符串必须在系统内保证唯一
static const UINT WM_CHECK_ITS_ME = RegisterWindowMessage(_T("##DUIVISION_APPLICATION##"));
// 2、定义消息数据结构
// 进程间消息内容的结构定义
struct DUI_INTERPROCESS_MSG
{
TCHAR wAppName[128]; // 应用名
UINT uControlID; // 控件ID
TCHAR wControlName[64]; // 控件名字
UINT uMsg; // 消息
WPARAM wParam; // 参数1
LPARAM lParam; // 参数2
TCHAR wInfo[10240]; // 信息字符串
UINT uDataLen; // 扩展部分长度
};
1、发送方:
BOOL SendInterprocessMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, CString strAppName, CString strInfo)
{
// number of characters in memory-mapped file
const DWORD dwMemoryFileSize = sizeof(DUI_INTERPROCESS_MSG);
// memory-mapped file name
const LPCTSTR sMemoryFileName = _T("DF034858-1608-4147-0604-4A0CD86F6C9F");
HANDLE hFileMapping = NULL;
LPVOID pViewOfFile = NULL;
// Create file mapping which can contain dwMemoryFileSize characters
hFileMapping = CreateFileMapping(
INVALID_HANDLE_VALUE, // system paging file
NULL, // security attributes
PAGE_READWRITE, // protection
0, // high-order DWORD of size
dwMemoryFileSize*sizeof(TCHAR), // low-order DWORD of size
sMemoryFileName); // name
DWORD dwError = GetLastError(); // if ERROR_ALREADY_EXISTS
// this instance is not first (other instance created file mapping)
if(! hFileMapping)
{
//TRACE(_T("Creating of file mapping failed.\n"));
return FALSE;
}
pViewOfFile = MapViewOfFile(
hFileMapping, // handle to file-mapping object
FILE_MAP_ALL_ACCESS, // desired access
0,
0,
0); // map all file
if(!pViewOfFile)
{
//TRACE(_T("MapViewOfFile failed.\n"));
CloseHandle(hFileMapping);
return FALSE;
}
// 初始化进程间通知消息
DUI_INTERPROCESS_MSG interMsg;
memset(&interMsg, 0, sizeof(DUI_INTERPROCESS_MSG));
_tcscpy_s(interMsg.wAppName, strAppName.GetBuffer(0));
strAppName.ReleaseBuffer();
interMsg.uControlID = APP_IPC; // 控件ID使用预定义的进程间消息控件ID
interMsg.uMsg = uMsg;
interMsg.wParam = wParam;
interMsg.lParam = lParam;
_tcscpy_s(interMsg.wInfo, strInfo.GetBuffer(0));
strInfo.ReleaseBuffer();
memcpy(pViewOfFile, &interMsg, sizeof(DUI_INTERPROCESS_MSG));
ULONG_PTR result;
LRESULT ok = SendMessageTimeout(HWND_BROADCAST, // 发送广播消息
WM_CHECK_ITS_ME,
wParam, // wParam参数,表示应用类型
0, // lParam参数,默认为0
SMTO_BLOCK |
SMTO_ABORTIFHUNG,
200, // 超时时间
&result);
UnmapViewOfFile(pViewOfFile);
CloseHandle(hFileMapping);
return TRUE;
}
3、接收方
在窗口处理过程中加入消息处理:
// 1、以MFC为例
BEGIN_MESSAGE_MAP(CDlgBase, CDialog)
ON_REGISTERED_MESSAGE(WM_CHECK_ITS_ME, OnCheckItsMe)
END_MESSAGE_MAP()
// 函数实现:
LRESULT CDlgBase::OnCheckItsMe(WPARAM wParam, LPARAM lParam)
{
// wParam用于区分应用,lParam用于具体命令,传送的内容则通过内存映射文件传递
// 此跨进称消息是通过广播方式传送的,因此所有窗口都会收到,只有主窗口需要处理此消息,其他窗口应该忽略
// 主窗口收到消息之后调用事件处理对象进行处理
// 判断是否当前的应用
if(wParam != GetAppID())
{
return FALSE;
}
// 获取内存映射文件的内容
// number of characters in memory-mapped file
const DWORD dwMemoryFileSize = sizeof(DUI_INTERPROCESS_MSG);
// memory-mapped file name
const LPCTSTR sMemoryFileName = _T("DF034858-1608-4147-0604-4A0CD86F6C9F");
HANDLE hFileMapping = NULL;
LPVOID pViewOfFile = NULL;
// Create file mapping which can contain dwMemoryFileSize characters
hFileMapping = CreateFileMapping(
INVALID_HANDLE_VALUE, // system paging file
NULL, // security attributes
PAGE_READWRITE, // protection
0, // high-order DWORD of size
dwMemoryFileSize*sizeof(TCHAR), // low-order DWORD of size
sMemoryFileName); // name
DWORD dwError = GetLastError(); // if ERROR_ALREADY_EXISTS
// this instance is not first (other instance created file mapping)
if(! hFileMapping)
{
//TRACE(_T("Creating of file mapping failed.\n"));
return FALSE;
}
pViewOfFile = MapViewOfFile(
hFileMapping, // handle to file-mapping object
FILE_MAP_ALL_ACCESS, // desired access
0,
0,
0); // map all file
if(!pViewOfFile)
{
//TRACE(_T("MapViewOfFile failed.\n"));
CloseHandle(hFileMapping);
return FALSE;
}
DUI_INTERPROCESS_MSG interMsg;
memcpy(&interMsg, pViewOfFile, sizeof(DUI_INTERPROCESS_MSG));
UnmapViewOfFile(pViewOfFile);
CloseHandle(hFileMapping);
return TRUE;
}