本例练习消息窗体的实现以及消息窗体收发消息; 对消息窗体的定义MSDN里描述大体是这样的, 父窗体指定为HWND_MESSAGE常量,它可以收发消息,没z-order, 不可遍历且不无能接收到广播消息仅做简单的消息分发; 我们可以在创建窗体时指定其父窗体为HWND_MESSAGE常量也可以将现有窗体通过SetParent将父窗体设为HWND_MESSAGE常量从而达到变成消息窗体的目的;
查找消息窗体句柄, 可以通过FindWindowEx这个函数将其hParent设为HWND_MESSAGE, 并指定类名或窗体名即可找到;
一、代码演示(为了方便演示提供了二个工程分别为Demo0050 – 实现消息窗体创建以及接受消息和发送消息; Demo0050Ex – 实现消息的发送以及广播消息的接收
1. 创建消息窗体(Demo0050)
//////////////////////////////////////////////////////////////////////////
HWND CreateWnd(const TCHAR* szClsName, const TCHAR* szWndCaption, HWND hParent = NULL,
DWORD dwStyle = WS_POPUP|WS_VISIBLE|WS_SYSMENU|WS_CAPTION,
DWORD dwStyleEx = 0)
{
if (NULL != szClsName)
{
HWND hWnd = CreateWindowEx(dwStyleEx, szClsName, szWndCaption, dwStyle,
0, 0, 800, 480, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
if (NULL != hWnd && IsWindow(hWnd))
{
return hWnd;
}
}
return NULL;
}
2. 查找消息窗体并发送消息(Demo0050Ex)
for (int ii = 0; ii < sizeof(CtrlsInfo) / sizeof(*CtrlsInfo); ii++)
{
if (wParam == CtrlsInfo[ii].m_ID)
{
CtrlsInfo[ii].m_fnProc(hMsgWnd, hWnd);
break;
}
}
列举了自定义消息(WM_UMSG_DATA),系统默认消息(WM_QUIT), 广播消息(WM_UMSG_BROADCAST、WM_UMSG_MSGWNDCREATED) 以及WM_COPYDATA消息
const UINT WM_UMSG_REGISTER = RegisterWindowMessage(_T("Register_MSG"));
const UINT WM_UMSG_BROADCAST = RegisterWindowMessage(_T("BroadCast_MSG"));
const UINT WM_UMSG_MSGWNDCREATED = RegisterWindowMessage(_T("MSGWndCreated_MSG"));
typedef void (*FUNPROC)(HWND hWnd, HWND hSender);
struct TCtrlInfo {
TCHAR m_szClsName[32];
TCHAR m_szText[64];
UINT m_ID;
FUNPROC m_fnProc;
};
void OnSendUserMsg(HWND hWnd, HWND hSender)
{
PostMessage(hWnd, WM_UMSG_DATA, 100, 110);
return;
}
void OnSendRegisterMsg(HWND hWnd, HWND hSender)
{
PostMessage(hWnd, WM_UMSG_REGISTER, 200, 220);
return;
}
void OnSendBroadcastMsg(HWND hWnd, HWND hSender)
{
PostMessage(HWND_BROADCAST, WM_UMSG_BROADCAST, 300, 330);
return;
}
void OnSendCopyDataMsg(HWND hWnd, HWND hSender)
{
struct TPerson {
UINT m_nAge;
TCHAR m_szName[64];
};
TPerson Person = { 25, _T("Greg.Yi") };
COPYDATASTRUCT cds;
cds.dwData = 1;
cds.cbData = sizeof(Person);
cds.lpData = &Person;
SendMessage(hWnd, WM_COPYDATA, (WPARAM)hSender, (LPARAM)&cds);
return;
}
void OnSendExitMsg(HWND hWnd, HWND hSender)
{
PostMessage(hWnd, WM_CLOSE, 0, 0);
return;
}
3. 接收消息( Demo0050, Demo0050Ex)
a. Demo0050 消息处理
const UINT WM_UMSG_DATA = (WM_APP + 1001);
const UINT WM_UMSG_REGISTER = RegisterWindowMessage(_T("Register_MSG"));
const UINT WM_UMSG_BROADCAST = RegisterWindowMessage(_T("BroadCast_MSG"));
const UINT WM_UMSG_MSGWNDCREATED = RegisterWindowMessage(_T("MSGWndCreated_MSG"));
struct TPerson {
UINT m_nAge;
TCHAR m_szName[64];
};
LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
switch (nMsg)
{
case WM_CREATE:
{
MessageBox(hWnd, _T("Message Reciver(Demo0050) Launched!"), _T("Demo0050"), MB_OK);
PostMessage(HWND_BROADCAST, WM_UMSG_MSGWNDCREATED, 0, 0);
break;
}
case WM_COPYDATA:
{
COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam;
TPerson* pPerson = (TPerson*)cds->lpData;
TCHAR szTmp[129];
_stprintf(szTmp, _T("Demo0050 Received a CopyData Messaged -- age: %d name: %s"), pPerson->m_nAge, (LPTSTR)pPerson->m_szName);
MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);
break;
}
case WM_UMSG_DATA:
{
TCHAR szTmp[129];
_stprintf(szTmp, _T("Demo0050 Received a User Messaged -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);
break;
}
case WM_CLOSE:
{
SendMessage(HWND_BROADCAST, WM_UMSG_MSGWNDCREATED, 0, 1);
PostQuitMessage(0);
break;
}
}
if (WM_UMSG_REGISTER == nMsg)
{
TCHAR szTmp[129];
_stprintf(szTmp, _T("Demo0050 Received a Register Message -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);
} else if (WM_UMSG_BROADCAST == nMsg) {
TCHAR szTmp[129];
_stprintf(szTmp, _T("Demo0050 Received a Broadcast Message -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);
}
return ::DefWindowProc(hWnd, nMsg, wParam, lParam);
}
b. Demo0050Ex 消息处理
if (WM_UMSG_BROADCAST == nMsg)
{
TCHAR szTmp[129];
_stprintf(szTmp, _T("Demo0050Ex Broadcast Message -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
MessageBox(NULL, szTmp, _T("Demo0050Ex"), MB_OK);
} else if (WM_UMSG_MSGWNDCREATED == nMsg) {
HWND hMsgWnd = FindWindowEx(HWND_MESSAGE, NULL, _T("Win32App"), NULL);
for (int ii = 0; ii < sizeof(CtrlsInfo) / sizeof(*CtrlsInfo); ii++)
{
EnableWindow(GetDlgItem(hWnd, CtrlsInfo[ii].m_ID), (0 == lParam) ? TRUE : FALSE);
}
}
二、演示结果总结
1. 消息窗体窗体是不可见,在SPY++窗体中可以找到, 但同步不到也就是说没有被遍历到.
2. 在Demo0050Ex发出广播消息(WM_UMSG_BROADCAST)后, Demo0050Ex自己收到, 但Demo0050没有收到
3. WM_COPYDATA 消息必须由SendMessage 函数发送(同步方式,系统为了确保数据有效)