nvoke LoadMenu,hInstance,IDM_MAIN mov hMenu,eax ;*************** 注册窗口类 ***************************************** invoke LoadCursor,0,IDC_ARROW mov @stWcMain.hCursor,eax mov @stWcMain.cbSize,sizeof WNDCLASSEX mov @stWcMain.hIconSm,0 mov @stWcMain.style,CS_HREDRAW or CS_VREDRAW mov @stWcMain.lpfnWndProc,offset WndMainProc mov @stWcMain.cbClsExtra,0 mov @stWcMain.cbWndExtra,0 mov eax,hInstance mov @stWcMain.hInstance,eax mov @stWcMain.hIcon,0 mov @stWcMain.hbrBackground,COLOR_WINDOW + 1 mov @stWcMain.lpszClassName,offset szClassName mov @stWcMain.lpszMenuName,0 invoke RegisterClassEx,addr @stWcMain ;*************** 建立输出窗口 *************************************** invoke CreateWindowEx,WS_EX_CLIENTEDGE,\ offset szClassName,offset szCaptionMain,\ WS_OVERLAPPEDWINDOW OR WS_VSCROLL OR WS_HSCROLL,\ 100,100,550,300,\ NULL,hMenu,hInstance,NULL
invoke ShowWindow,hWinMain,SW_SHOWNORMAL invoke UpdateWindow,hWinMain ;*************** 消息循环 ******************************************* invoke LoadAccelerators,hInstance,IDA_MAIN mov @hAccelerator,eax .while TRUE invoke GetMessage,addr @stMsg,NULL,0,0 .break .if eax == 0 invoke TranslateAccelerator,hWinMain,@hAccelerator,addr @stMsg .if eax == 0 invoke TranslateMessage,addr @stMsg invoke DispatchMessage,addr @stMsg .endif .endw ret
_WinMain endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> WndMainProc proc uses ebx edi esi, \ hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD local @stPos:POINT
mov eax,uMsg .if eax == WM_CREATE mov eax,hWnd mov hWinMain,eax call _Init ;******************************************************************** .elseif eax == WM_COMMAND .if lParam == 0 mov eax,wParam movzx eax,ax .if eax == IDM_EXIT call _Quit .elseif eax == IDM_TOOLBAR xor dwFlag,F_TOOLBAR call _MenuStatus .elseif eax == IDM_TOOLBARTEXT xor dwFlag,F_TOOLBARTEXT call _MenuStatus .elseif eax == IDM_INPUTBAR xor dwFlag,F_INPUTBAR call _MenuStatus .elseif eax == IDM_STATUSBAR xor dwFlag,F_STATUSBAR call _MenuStatus .else _Debug "菜单命令","命令ID",eax .endif .endif ;******************************************************************** .elseif eax == WM_SYSCOMMAND mov eax,wParam movzx eax,ax .if eax == IDM_HELP || eax == IDM_ABOUT _Debug "菜单命令","命令ID",eax .else invoke DefWindowProc,hWnd,uMsg,wParam,lParam ret .endif ;******************************************************************** ; 按下右键时弹出一个POPUP菜单 ;******************************************************************** .elseif eax == WM_RBUTTONDOWN invoke GetCursorPos,addr @stPos invoke TrackPopupMenu,hSubMenu,TPM_LEFTALIGN,@stPos.x,@stPos.y,NULL,hWnd,NULL ;******************************************************************** .elseif eax == WM_CLOSE call _Quit ;******************************************************************** .else invoke DefWindowProc,hWnd,uMsg,wParam,lParam ret .endif ;******************************************************************** ; 注意:WndProc 处理 Windows 消息后,必须在 Eax 中返回 0 ; 但是由 DefWindowProc 处理后的返回值不能改变,否则窗口 ; 将无法显示!
以下是代码片段: ;******************************************************************** xor eax,eax ret
WndMainProc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 主窗口控制子程序 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _Init proc local @hSysMenu
invoke SendMessage,hWinMain,WM_SETICON,ICON_SMALL,hIcon ;******************************************************************** ; POPUP菜单要用到子菜单才能实现 ;******************************************************************** invoke GetSubMenu,hMenu,1 mov hSubMenu,eax call _MenuStatus ;******************************************************************** ; 在系统菜单中添加菜单项 ;******************************************************************** invoke GetSystemMenu,hWinMain,FALSE mov @hSysMenu,eax invoke AppendMenu,@hSysMenu,MF_SEPARATOR,0,NULL invoke AppendMenu,@hSysMenu,MF_STRING,IDM_HELP,offset szMenuHelp invoke AppendMenu,@hSysMenu,MF_STRING,IDM_ABOUT,offset szMenuAbout
ret
_Init endp ;******************************************************************** ; 根据标志位设置相应菜单项的状态 ;******************************************************************** _MenuStatus proc
test dwFlag,F_INPUTBAR .if ZERO? invoke CheckMenuItem,hMenu,IDM_INPUTBAR,MF_UNCHECKED .else invoke CheckMenuItem,hMenu,IDM_INPUTBAR,MF_CHECKED .endif test dwFlag,F_TOOLBAR .if ZERO? invoke CheckMenuItem,hMenu,IDM_TOOLBAR,MF_UNCHECKED .else invoke CheckMenuItem,hMenu,IDM_TOOLBAR,MF_CHECKED .endif test dwFlag,F_TOOLBARTEXT .if ZERO? invoke CheckMenuItem,hMenu,IDM_TOOLBARTEXT,MF_UNCHECKED .else invoke CheckMenuItem,hMenu,IDM_TOOLBARTEXT,MF_CHECKED .endif test dwFlag,F_STATUSBAR .if ZERO? invoke CheckMenuItem,hMenu,IDM_STATUSBAR,MF_UNCHECKED .else invoke CheckMenuItem,hMenu,IDM_STATUSBAR,MF_CHECKED .endif ret
_MenuStatus endp ;******************************************************************** _Quit proc
invoke DestroyWindow,hWinMain invoke PostQuitMessage,NULL ret
_Quit endp ;******************************************************************** end start 程序的分析
让我们来简单分析一下这个程序,首先这个程序和上一节的最简单的窗口程序的不同之处就是消息循环,如下:
以下是代码片段: while TRUE invoke GetMessage,addr @stMsg,NULL,0,0 .break .if eax == 0 invoke TranslateAccelerator,hWinMain,@hAccelerator,addr @stMsg .if eax == 0 invoke TranslateMessage,addr @stMsg invoke DispatchMessage,addr @stMsg .endif .endw .在循环中的TranslateAccelerator用来确定存放在MSG结构中的消息是不是键盘消息,如果是,它查找句柄@hAccelerator对应的加速键表,如果找到了一个匹配项,那么它将用命令ID向窗口发送WM_COMMAND消息,同时返回非0值,这时候表示消息已经被处理,不用再调用下面的TranslateMessage 和 DispatchMessage 了,如果不是,那么它将返回0,消息循环继续。 另外,要说明的是弹出式菜单,在程序中我们响应WM_RBUTTONDOWN消息对按下右键进行处理, 然后调用GetCursorPos取得当前鼠标坐标,然后使用TrackPopupMenu在鼠标位置上弹出一个菜单,但是在资源文件中,“弹出式菜单”是无法直接定义的,所以在初始化部分,我们使用GetSubMenu 取出弹出式子菜单的句柄供TrackPopupMenu使用。 上一页 [1] [2] |