有容兄请进,关于Windows消息循环机制,高手略过本帖。
如何正确理解消息循环机制,罗云彬的汇编例子举得很好,所以偶昨天花了点时间,把汇编的改成C语言,你可以按着最上面的提示,开启一个空的记事本,然后运行本程序。
程序代码:
/**
; MsgWindow.cpp (MsgWindows01)
; 将窗口的消息流程显示到 Notepad 进程的编辑窗口中
通过该程序,你可以查看,在一个窗口中创建过程中会接收到哪些消息,
移动鼠标到窗体上,看看看有哪些消息没有经过消息循环,直接发送到窗口过程中了。
然后查看一下当点击关闭按钮时,窗口会接收到哪些消息。
想知道TranslateMessage函数倒底起什么作用,不妨修改程序注释之。
直观的理解Windows窗体消息机制就是这样的,是不是很简单?
*/
#include <windows.h>
//消息索引表
UINT dwMsgTable[] = {WM_NULL, WM_CREATE, WM_DESTROY, WM_MOVE, WM_SIZE,
WM_ACTIVATE, WM_SETFOCUS, WM_KILLFOCUS,WM_ENABLE,WM_SETREDRAW,
WM_SETTEXT,WM_GETTEXT,WM_GETTEXTLENGTH,WM_PAINT,WM_CLOSE,
WM_QUERYENDSESSION,WM_QUIT,WM_QUERYOPEN,WM_ERASEBKGND,WM_SYSCOLORCHANGE,
WM_ENDSESSION,WM_SHOWWINDOW,WM_WININICHANGE,WM_DEVMODECHANGE,WM_ACTIVATEAPP,
WM_FONTCHANGE,WM_TIMECHANGE,WM_CANCELMODE,WM_SETCURSOR,WM_MOUSEACTIVATE,
WM_CHILDACTIVATE,WM_QUEUESYNC,WM_GETMINMAXINFO,WM_PAINTICON,WM_ICONERASEBKGND,
WM_NEXTDLGCTL,WM_SPOOLERSTATUS,WM_DRAWITEM,WM_MEASUREITEM,WM_DELETEITEM,
WM_VKEYTOITEM,WM_CHARTOITEM,WM_SETFONT,WM_GETFONT,WM_SETHOTKEY,WM_GETHOTKEY,
WM_QUERYDRAGICON,WM_COMPAREITEM,WM_GETOBJECT,WM_COMPACTING,/*WM_OTHERWINDOWCREATED,*/
/*WM_OTHERWINDOWDESTROYED,*/WM_COMMNOTIFY,WM_WINDOWPOSCHANGING,WM_WINDOWPOSCHANGED,WM_POWER,
WM_COPYDATA,WM_CANCELJOURNAL,WM_NOTIFY,WM_INPUTLANGCHANGEREQUEST,WM_INPUTLANGCHANGE,
WM_TCARD,WM_HELP,WM_USERCHANGED,WM_NOTIFYFORMAT,WM_CONTEXTMENU,
WM_STYLECHANGING,WM_STYLECHANGED,WM_DISPLAYCHANGE,WM_GETICON,WM_SETICON,
WM_NCCREATE,WM_NCDESTROY,WM_NCCALCSIZE,WM_NCHITTEST,WM_NCPAINT,
WM_NCACTIVATE,WM_GETDLGCODE,WM_SYNCPAINT,WM_NCMOUSEMOVE,WM_NCLBUTTONDOWN,
WM_NCLBUTTONUP,WM_NCLBUTTONDBLCLK,WM_NCRBUTTONDOWN,WM_NCRBUTTONUP,WM_NCRBUTTONDBLCLK,
WM_NCMBUTTONDOWN,WM_NCMBUTTONUP,WM_NCMBUTTONDBLCLK,WM_KEYDOWN,WM_KEYUP,
WM_CHAR,WM_DEADCHAR,WM_SYSKEYDOWN,WM_SYSKEYUP,WM_SYSCHAR,
WM_SYSDEADCHAR,WM_KEYLAST,WM_INITDIALOG,WM_COMMAND,WM_SYSCOMMAND,
WM_TIMER,WM_HSCROLL,WM_VSCROLL,WM_INITMENU,WM_INITMENUPOPUP,
WM_MENUSELECT,WM_MENUCHAR,WM_ENTERIDLE,WM_CTLCOLORMSGBOX,WM_CTLCOLOREDIT,
WM_CTLCOLORLISTBOX,WM_CTLCOLORBTN,WM_CTLCOLORDLG,WM_CTLCOLORSCROLLBAR,WM_CTLCOLORSTATIC,
WM_MOUSEMOVE,WM_LBUTTONDOWN,WM_LBUTTONUP,WM_LBUTTONDBLCLK,WM_RBUTTONDOWN,
WM_RBUTTONUP,WM_RBUTTONDBLCLK,WM_MBUTTONDOWN,WM_MBUTTONUP,WM_MBUTTONDBLCLK,
WM_MOUSELAST,WM_PARENTNOTIFY,WM_ENTERMENULOOP,WM_EXITMENULOOP,WM_MDICREATE,
WM_MDIDESTROY,WM_MDIACTIVATE,WM_MDIRESTORE,WM_MDINEXT,WM_MDIMAXIMIZE,
WM_MDITILE,WM_MDICASCADE,WM_MDIICONARRANGE,WM_MDIGETACTIVE,WM_MDISETMENU,
WM_DROPFILES,WM_MDIREFRESHMENU,WM_CUT,WM_COPY,WM_PASTE,
WM_CLEAR,WM_UNDO,WM_RENDERFORMAT,WM_RENDERALLFORMATS,WM_DESTROYCLIPBOARD,
WM_DRAWCLIPBOARD,WM_PAINTCLIPBOARD,WM_VSCROLLCLIPBOARD,WM_SIZECLIPBOARD,WM_ASKCBFORMATNAME,
WM_CHANGECBCHAIN,WM_HSCROLLCLIPBOARD,WM_QUERYNEWPALETTE,WM_PALETTEISCHANGING,WM_PALETTECHANGED,
WM_HOTKEY,WM_PRINT,WM_PRINTCLIENT,WM_PENWINFIRST,WM_PENWINLAST,
WM_MENURBUTTONUP,WM_MENUDRAG,WM_MENUGETOBJECT,WM_UNINITMENUPOPUP,WM_MENUCOMMAND,
WM_NEXTMENU,WM_SIZING,WM_CAPTURECHANGED,WM_MOVING,WM_POWERBROADCAST,
WM_DEVICECHANGE,WM_ENTERSIZEMOVE,WM_EXITSIZEMOVE};
int MSG_TABLE_LEN = sizeof(dwMsgTable) / sizeof(UINT);
//消息字符串表
char *szStringTable[] = {
"WM_NULL ",
"WM_CREATE ",
"WM_DESTROY ",
"WM_MOVE ",
"WM_SIZE ",
"WM_ACTIVATE ",
"WM_SETFOCUS ",
"WM_KILLFOCUS ",
"WM_ENABLE ",
"WM_SETREDRAW ",
"WM_SETTEXT ",
"WM_GETTEXT ",
"WM_GETTEXTLENGTH ",
"WM_PAINT ",
"WM_CLOSE ",
"WM_QUERYENDSESSION ",
"WM_QUIT ",
"WM_QUERYOPEN ",
"WM_ERASEBKGND ",
"WM_SYSCOLORCHANGE ",
"WM_ENDSESSION ",
"WM_SHOWWINDOW ",
"WM_WININICHANGE ",
"WM_DEVMODECHANGE ",
"WM_ACTIVATEAPP ",
"WM_FONTCHANGE ",
"WM_TIMECHANGE ",
"WM_CANCELMODE ",
"WM_SETCURSOR ",
"WM_MOUSEACTIVATE ",
"WM_CHILDACTIVATE ",
"WM_QUEUESYNC ",
"WM_GETMINMAXINFO ",
"WM_PAINTICON ",
"WM_ICONERASEBKGND ",
"WM_NEXTDLGCTL ",
"WM_SPOOLERSTATUS ",
"WM_DRAWITEM ",
"WM_MEASUREITEM ",
"WM_DELETEITEM ",
"WM_VKEYTOITEM ",
"WM_CHARTOITEM ",
"WM_SETFONT ",
"WM_GETFONT ",
"WM_SETHOTKEY ",
"WM_GETHOTKEY ",
"WM_QUERYDRAGICON ",
"WM_COMPAREITEM ",
"WM_GETOBJECT ",
"WM_COMPACTING ",
/*"WM_OTHERWINDOWCREATED ",*/
/*"WM_OTHERWINDOWDESTROYED ",*/
"WM_COMMNOTIFY ",
"WM_WINDOWPOSCHANGING ",
"WM_WINDOWPOSCHANGED ",
"WM_POWER ",
"WM_COPYDATA ",
"WM_CANCELJOURNAL ",
"WM_NOTIFY ",
"WM_INPUTLANGCHANGEREQUEST",
"WM_INPUTLANGCHANGE ",
"WM_TCARD ",
"WM_HELP ",
"WM_USERCHANGED ",
"WM_NOTIFYFORMAT ",
"WM_CONTEXTMENU ",
"WM_STYLECHANGING ",
"WM_STYLECHANGED ",
"WM_DISPLAYCHANGE ",
"WM_GETICON ",
"WM_SETICON ",
"WM_NCCREATE ",
"WM_NCDESTROY ",
"WM_NCCALCSIZE ",
"WM_NCHITTEST ",
"WM_NCPAINT ",
"WM_NCACTIVATE ",
"WM_GETDLGCODE ",
"WM_SYNCPAINT ",
"WM_NCMOUSEMOVE ",
"WM_NCLBUTTONDOWN ",
"WM_NCLBUTTONUP ",
"WM_NCLBUTTONDBLCLK ",
"WM_NCRBUTTONDOWN ",
"WM_NCRBUTTONUP ",
"WM_NCRBUTTONDBLCLK ",
"WM_NCMBUTTONDOWN ",
"WM_NCMBUTTONUP ",
"WM_NCMBUTTONDBLCLK ",
"WM_KEYDOWN ",
"WM_KEYUP ",
"WM_CHAR ",
"WM_DEADCHAR ",
"WM_SYSKEYDOWN ",
"WM_SYSKEYUP ",
"WM_SYSCHAR ",
"WM_SYSDEADCHAR ",
"WM_KEYLAST ",
"WM_INITDIALOG ",
"WM_COMMAND ",
"WM_SYSCOMMAND ",
"WM_TIMER ",
"WM_HSCROLL ",
"WM_VSCROLL ",
"WM_INITMENU ",
"WM_INITMENUPOPUP ",
"WM_MENUSELECT ",
"WM_MENUCHAR ",
"WM_ENTERIDLE ",
"WM_CTLCOLORMSGBOX ",
"WM_CTLCOLOREDIT ",
"WM_CTLCOLORLISTBOX ",
"WM_CTLCOLORBTN ",
"WM_CTLCOLORDLG ",
"WM_CTLCOLORSCROLLBAR ",
"WM_CTLCOLORSTATIC ",
"WM_MOUSEMOVE ",
"WM_LBUTTONDOWN ",
"WM_LBUTTONUP ",
"WM_LBUTTONDBLCLK ",
"WM_RBUTTONDOWN ",
"WM_RBUTTONUP ",
"WM_RBUTTONDBLCLK ",
"WM_MBUTTONDOWN ",
"WM_MBUTTONUP ",
"WM_MBUTTONDBLCLK ",
"WM_MOUSELAST ",
"WM_PARENTNOTIFY ",
"WM_ENTERMENULOOP ",
"WM_EXITMENULOOP ",
"WM_MDICREATE ",
"WM_MDIDESTROY ",
"WM_MDIACTIVATE ",
"WM_MDIRESTORE ",
"WM_MDINEXT ",
"WM_MDIMAXIMIZE ",
"WM_MDITILE ",
"WM_MDICASCADE ",
"WM_MDIICONARRANGE ",
"WM_MDIGETACTIVE ",
"WM_MDISETMENU ",
"WM_DROPFILES ",
"WM_MDIREFRESHMENU ",
"WM_CUT ",
"WM_COPY ",
"WM_PASTE ",
"WM_CLEAR ",
"WM_UNDO ",
"WM_RENDERFORMAT ",
"WM_RENDERALLFORMATS ",
"WM_DESTROYCLIPBOARD ",
"WM_DRAWCLIPBOARD ",
"WM_PAINTCLIPBOARD ",
"WM_VSCROLLCLIPBOARD ",
"WM_SIZECLIPBOARD ",
"WM_ASKCBFORMATNAME ",
"WM_CHANGECBCHAIN ",
"WM_HSCROLLCLIPBOARD ",
"WM_QUERYNEWPALETTE ",
"WM_PALETTEISCHANGING ",
"WM_PALETTECHANGED ",
"WM_HOTKEY ",
"WM_PRINT ",
"WM_PRINTCLIENT ",
"WM_PENWINFIRST ",
"WM_PENWINLAST ",
"WM_MENURBUTTONUP ",
"WM_MENUDRAG ",
"WM_MENUGETOBJECT ",
"WM_UNINITMENUPOPUP ",
"WM_MENUCOMMAND ",
"WM_NEXTMENU ",
"WM_SIZING ",
"WM_CAPTURECHANGED ",
"WM_MOVING ",
"WM_POWERBROADCAST ",
"WM_DEVICECHANGE ",
"WM_ENTERSIZEMOVE ",
"WM_EXITSIZEMOVE ",
};
const char* szClassName = "MyClass";
const char* szCaptionMain = "Message Tester";
const char* szDestClass = "Notepad";
const char* szFormat = "WndProc: [%04x]%s %08x %08x\n";
const char* szCreateWindow1 = "Creating Window...\n";
const char* szCreateWindow2 = "CreateWindow end\n";
const char* szShowWindow1 = "Showing Window...\n";
const char* szShowWindow2 = "ShowWindow end\n";
const char* szUpdateWindow1 = "Updating Window...\n";
const char* szUpdateWindow2 = "UpdateWindow end\n";
const char* szGetMsg1 = "Getting Message...\n";
const char* szGetMsg2 = "[%04x]Message gotten\n";
const char* szDispatchMsg1 = "Dispatching Message...\n";
const char* szDispatchMsg2 = "DispatchMessage end\n";
////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK ProcWinMain(HWND, UINT, WPARAM, LPARAM);
void SendtoNotepad(const char *);
void ShowMessage(UINT, WPARAM, LPARAM);
////////////////////////////////////////////////////////////////////////
//主程序入口
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hpre,
LPSTR linecmd, int nShow)
{
char szBuffer[128];
WNDCLASSEX wnd;
MSG msg;
HWND hwnd;
memset(&wnd, 0, sizeof(WNDCLASSEX));
wnd.cbSize = sizeof(WNDCLASSEX);
wnd.hInstance = hinst;
wnd.style = CS_HREDRAW | CS_VREDRAW;
wnd.lpfnWndProc = ProcWinMain;
wnd.hbrBackground = (HBRUSH) 1;
wnd.lpszClassName = szClassName;
wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClassEx(&wnd);
SendtoNotepad(szCreateWindow1);
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
szClassName, szCaptionMain,
WS_OVERLAPPEDWINDOW,
50,50,100,100,
0, 0, hinst, 0);
SendtoNotepad(szCreateWindow2);
SendtoNotepad(szShowWindow1);
ShowWindow(hwnd, SW_SHOWNORMAL);
SendtoNotepad(szShowWindow2);
SendtoNotepad(szUpdateWindow1);
UpdateWindow(hwnd);
SendtoNotepad(szUpdateWindow2);
//消息循环
while(TRUE)
{
int ret;
SendtoNotepad(szGetMsg1);
ret = GetMessage(&msg, NULL, 0, 0);
wsprintf(szBuffer, szGetMsg2, msg.message);
SendtoNotepad(szBuffer);
if ( ret == 0 ) break;
TranslateMessage(&msg);
SendtoNotepad(szDispatchMsg1);
DispatchMessage(&msg);
SendtoNotepad(szDispatchMsg2);
}
return (int)msg.wParam;
}
//窗口过程
LRESULT CALLBACK ProcWinMain(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
ShowMessage(uMsg, wParam, lParam);
switch(uMsg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
//查找消息说明字符串,并翻译格式发送到 Notepad 窗口
void ShowMessage(UINT _uMsg, WPARAM _wParam, LPARAM _lParam)
{
char szBuffer[128];
int i;
for(i = 0; i < MSG_TABLE_LEN; i++)
{
if(_uMsg == dwMsgTable[i])
{
wsprintf(szBuffer, szFormat, _uMsg, szStringTable[i], _wParam, _lParam);
SendtoNotepad(szBuffer);
}
}
}
//查找 NotePad 窗口中的Edit控件句柄,然后把字符串中的字符以WM_CHAR消息发送到Edit中。
void SendtoNotepad(const char *_lpsz)
{
HWND hWinNodepad;
hWinNodepad = FindWindow(szDestClass, NULL);
if(hWinNodepad)
{
POINT pt = {20, 20};
hWinNodepad = ChildWindowFromPoint(hWinNodepad, pt);
if(hWinNodepad)
{
int slen, i;
slen = strlen(_lpsz);
for(i = 0; i < slen; i++)
{
PostMessage(hWinNodepad, WM_CHAR, _lpsz[i], 1);
}
}
}
}
附全部工程及汇编源代码:
C工程:
汇编工程:


