本例练习消息窗体的实现以及消息窗体收发消息; 对消息窗体的定义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 函数发送(同步方式,系统为了确保数据有效)