学了这么久的VC了,对WINDOWS的消息机制还是理解得不够到位,今天晚上来把SDK中得消息机制整理一下;先说明一下,这篇文章是我在边查资料的情况下写的,如果那里存在错误希望各位看客帮我指正一下,小弟感激不尽。
首先是消息得结构:
老办法先查MSDN
The MSG structure contains message information from a thread's message queue.
Syntax
ypedef struct {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG, *PMSG;Members
hwnd
Handle to the window whose window procedure receives the message.
//指向消息窗口的句柄
message
Specifies the message identifier. Applications can only use the low word; the high word is reserved by the system.
//消息得表示符,应用程序只能使用低字节,高字节得作为保留字
wParam
Specifies additional information about the message. The exact meaning depends on the value of the message member.
//大致意思是不同得消息有不同的意思
lParam
Specifies additional information about the message. The exact meaning depends on the value of the message member.
//和Wparam定义一样
time
Specifies the time at which the message was posted.
//发送消息的时间
pt
Specifies the cursor position, in screen coordinates, when the message was posted.
//指明消息发送的坐标
其实消息结构也没有什么可多说的地方
关键地方是消息怎样被发送还有怎样被处理的
要是把这二个方面搞清楚了,应该能很好地理解SDK中的消息机制了。
首先是消息的发送:我开始的问题是,一个窗口在什么时候会发送消息?怎样在函数体内发送消息?也就是在一个函数内怎样调用消息函数去发送消息然后让制定的窗口作出相应的动作。
把一个消息发送到窗口有3种方式:发送、寄送和广播。
发送消息的函数有SendMessage、SendMessageCallback、SendNotifyMessage、SendMessageTimeout;
寄送消息的函数主要有PostMessage、PostThreadMessage、PostQuitMessage;
广播消息的函数我知道的只有BroadcastSystemMessage、BroadcastSystemMessageEx。
先看是拿SendMessage开刀。。。
MSDN:
The SendMessage function sends the specified message to a window or windows. It calls the window procedure for the specified window and does not return until the window procedure has processed the message.
To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message immediately, queue and return use the PostMessage or PostThreadMessage function.
//SendMessage发送一个消息等待返回结果, 使用SendMessageCallback or SendNotifyMessage 立即返回,使用PostMessage or PostThreadMessage发送消息到一个线程
Syntax
LRESULT SendMessage( HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);Parameters
hWnd
[in] Handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.
如果这个参数是HWND_BROADCAST消息将发送到所有的顶层窗口包括失效,隐藏,重叠和弹出窗口,但是这个消息不发送到子窗口
Msg
[in] Specifies the message to be sent.
wParam
[in] Specifies additional message-specific information.
lParam
[in] Specifies additional message-specific information.
Return Value
The return value specifies the result of the message processing; it depends on the message sent.
Remarks
Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a unique message for inter-application communication.
The system only does marshalling for system messages (those in the range 0 to WM_USER). To send other messages (those above WM_USER) to another process, you must do custom marshalling.
上面这句是消息机制很关键的部分,请高手帮我翻译一下,谢谢了先
If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. For more information on nonqueued messages, see Nonqueued Messages.
消息的接收主要有3个函数:GetMessage、PeekMessage、WaitMessage。
我们用SDK写程序都要用下面这样的代码
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
上面那样的代码在消息少的情况下执行起来还可以,但是消息一多久会太让人受不了的
如是消息分流的概念被提出
下面是WindowsX.h中的部分内容
/****** Message crackers ****************************************************/
#define HANDLE_MSG(hwnd, message, fn) /
case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))
/* void Cls_OnCompacting(HWND hwnd, UINT compactRatio) */
#define HANDLE_WM_COMPACTING(hwnd, wParam, lParam, fn) /
((fn)((hwnd), (UINT)(wParam)), 0L)
#define FORWARD_WM_COMPACTING(hwnd, compactRatio, fn) /
(void)(fn)((hwnd), WM_COMPACTING, (WPARAM)(UINT)(compactRatio), 0L)
/* void Cls_OnWinIniChange(HWND hwnd, LPCTSTR lpszSectionName) */
#define HANDLE_WM_WININICHANGE(hwnd, wParam, lParam, fn) /
((fn)((hwnd), (LPCTSTR)(lParam)), 0L)
#define FORWARD_WM_WININICHANGE(hwnd, lpszSectionName, fn) /
(void)(fn)((hwnd), WM_WININICHANGE, 0L, (LPARAM)(LPCTSTR)(lpszSectionName))
/* void Cls_OnSysColorChange(HWND hwnd) */
#define HANDLE_WM_SYSCOLORCHANGE(hwnd, wParam, lParam, fn) /
((fn)(hwnd), 0L)
#define FORWARD_WM_SYSCOLORCHANGE(hwnd, fn) /
(void)(fn)((hwnd), WM_SYSCOLORCHANGE, 0L, 0L)
/* BOOL Cls_OnQueryNewPalette(HWND hwnd) */
#define HANDLE_WM_QUERYNEWPALETTE(hwnd, wParam, lParam, fn) /
MAKELRESULT((BOOL)(fn)(hwnd), 0L)
#define FORWARD_WM_QUERYNEWPALETTE(hwnd, fn) /
(BOOL)(DWORD)(fn)((hwnd), WM_QUERYNEWPALETTE, 0L, 0L)
/* void Cls_OnPaletteIsChanging(HWND hwnd, HWND hwndPaletteChange) */
#define HANDLE_WM_PALETTEISCHANGING(hwnd, wParam, lParam, fn) /
((fn)((hwnd), (HWND)(wParam)), 0L)
#define FORWARD_WM_PALETTEISCHANGING(hwnd, hwndPaletteChange, fn) /
(void)(fn)((hwnd), WM_PALETTEISCHANGING, (WPARAM)(HWND)(hwndPaletteChange), 0L)
.....................................................
下面就是分流的效果
switch(message)
{
HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);
HANDLE_MSG(hWnd,WM_DESTROY,MsgCracker);
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
明天在来研究了吧
睡觉了:(