本例练习消息窗体的实现以及消息窗体收发消息; 对消息窗体的定义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)
HWND
hMsgWnd
=
FindWindowEx
(
HWND_MESSAGE
,
NULL
,
_T
(
"Win32App"
),
NULL
);
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_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"
));
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 函数发送(同步方式,系统为了确保数据有效)
演示代码