有容兄请进,关于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工程:
MsgWindow.rar
(17.65 KB)
汇编工程:
MsgWindow01.rar
(4.07 KB)