《Windows环境下32位汇编语言程序设计(第2版)》-chapter5-基本框架
2016-07-24 20:11
330 查看
第五章开始创建一个带菜单的窗口,自己把代码打出来又做了注释,只是粘贴到代码段后格式有点乱,对齐什么的,强迫症飘过,暂时没找到好办法整理或者避免……
菜单的资源文件(资源文件的后缀是rs,只是CSDN无法识别这个,就改成txt了)
主程序文件
菜单的资源文件(资源文件的后缀是rs,只是CSDN无法识别这个,就改成txt了)
# include # define IDM_MAIN 0x2000 # define IDA_MAIN 0x2000 # define IDM_OPEN 0x4101 # define IDM_OPTION 0x4102 # define IDM_EXIT 0x4103 # define IDM_SETFONT 0x4201 # define IDM_SETCOLOR 0x4202 # define IDM_INACT 0x4203 # define IDM_GRAY 0x4204 # define IDM_BIG 0x4205 # define IDM_SAMLL 0x4206 # define IDM_LIST 0x4207 # define IDM_DETAIL 0x4208 # define IDM_TOOLBAR 0x4209 # define IDM_TOOLBARTEXT 0x4210 # define IDM_INPUTBAR 0x4211 # define IDM_STATUSBAR 0x4212 # define IDM_HELP 0x4301 # define IDM_ABOUT 0x4302 IDM_MAIN menu discardable BEGIN popup "文件(&F)" BEGIN menuitem "打开文件(&O)", IDM_OPEN menuitem "关闭文件(&C)", IDM_OPTION menuitem separator menuitem "退出(&X)", IDM_EXIT END popup "查看(&V)" BEGIN menuitem "字体(&F)\tAlt+F", IDM_SETFONT //&表示在字母下面添加下划线,默认为快捷键 menuitem "背景色(&B)\tCtrl+Alt+B", IDM_SETCOLOR //\t会使后面的字符串右对齐 menuitem separator menuitem "被禁用的菜单项", IDM_INACT, INACTIVE //CHECKED,GRAYED,INACTIVE,MENUBREAK,MENUBARBREAK(以下部分另起一列) menuitem "被灰化的菜单项", IDM_GRAY, GRAYED menuitem separator menuitem "大图标(&G)", IDM_BIG menuitem "小图标(&M)", IDM_SAMLL menuitem "列表(&L)", IDM_LIST menuitem "详细资料(&D)", IDM_DETAIL menuitem separator popup "工具栏(&T)" BEGIN menuitem "标准按钮(&S)", IDM_TOOLBAR menuitem "文字标签(&C)", IDM_TOOLBARTEXT menuitem "命令栏(&T)", IDM_INPUTBAR menuitem "状态栏(&U)", IDM_STATUSBAR END END popup "帮助(&H)" //popup ”” [,GRAYED][,INACTIVE][,HELP(右对齐)] BEGIN menuitem "帮助主题(&H)", IDM_HELP menuitem separator menuitem "关于本程序(&A)", IDM_ABOUT END END IDA_MAIN accelerators BEGIN VK_F1, IDM_HELP, VIRTKEY //"^X" = ctrl + X "B", IDM_SETCOLOR, VIRTKEY, CONTROL, ALT //"X" = X, VIRTKEY "F", IDM_SETFONT, VIRTKEY, ALT //数值 表示Ascii为该数值的字母,ASCII //[,CONTROL][,ALT][,SHIFT] //VK_F1 = F1 //VK_BACK //VK_ESCAPE //VK_DELETE //VK_RETURN END
主程序文件
.386 .model flat, stdcall option casemap: none ;----------------------------------------------------------------------- include windows.inc include gdi32.inc includelib gdi32.lib include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib ;----------------------------------------------------------------------- IDM_MAIN equ 2000h IDA_MAIN equ 2000h IDM_OPEN equ 4101h IDM_OPTION equ 4102h IDM_EXIT equ 4103h IDM_SETFONT equ 4201h IDM_SETCOLOR equ 4202h IDM_INACT equ 4203h IDM_GRAY equ 4204h IDM_BIG equ 4205h IDM_SAMLL equ 4206h IDM_LIST equ 4207h IDM_DETAIL equ 4208h IDM_TOOLBAR equ 4209h IDM_TOOLBARTEXT equ 4210h IDM_INPUTBAR equ 4211h IDM_STATUSBAR equ 4212h IDM_HELP equ 4301h IDM_ABOUT equ 4302h ;----------------------------------------------------------------------- .data hInstance dd ? hWinMain dd ? hMenu dd ? hSubMenu dd ? .const szClassName db 'MyClass', 0 szCaptionMain db 'My first window', 0 szText db 'Win32 Assemply, Simple and powerful!', 0 szMenuHelp db '帮助主题(&H)', 0 szMenuAbout db '关于本程序(&A)', 0 szCaption db 'MenuDisply', 0 szFormat db 'what you choose is:%08x', 0 ;@08x最少8位的16进制 ;----------------------------------------------------------------------- .code ;----------------------------------------------------------------------- ;_DisplayMenuItem实现弹出一个指定格式内容的窗口 ;----------------------------------------------------------------------- _DisplayMenuItem proc _dwCommandID ;_dwCommandID是形式参数,此处未指明类型 local @szBuffer[256]: byte pushad ;保护现场 invoke wsprintf, addr @szBuffer, addr szFormat,\ ;wsprintf(szBuffer, szFormat, _dwCommandID); _dwCommandID ;wParam有32位,低16位是命令id(资源ID),高16位是通知码,全0为菜单消息,全1为快捷键消息 invoke MessageBox, hWinMain, addr @szBuffer, \ ;MessageBox(hWinMain, szBuffer, szCaption, MB_OK); offset szCaption, MB_OK ; 模块句柄,显示内容,窗口标题,窗口模式 popad ;保护现场 ret ;相当于return,自动实现堆栈平衡 _DisplayMenuItem endp ;----------------------------------------------------------------------- ;_Quit单独实现了退出功能,可以再加上一些判断。利用call调用即可 ;----------------------------------------------------------------------- _Quit proc invoke DestroyWindow, hWinMain ;DestroyWindow(hWndMain);销毁窗口 invoke PostQuitMessage, 0 ;PostQuitMessage(0); 终止进程 ret _Quit endp ;----------------------------------------------------------------------- _ProcWinMain proc uses ebx edi esi, hWnd, uMsg, wParam, lParam local @stPs: PAINTSTRUCT local @stRect: RECT local @hDc local @stPos: POINT local @hSysMenu mov eax, uMsg ;载入消息 ;----------------------------------------------------------- .if eax == WM_PAINT ;感兴趣的自己处理 invoke BeginPaint, hWnd, addr @stPs mov @hDc, eax invoke GetClientRect, hWnd, addr @stRect invoke DrawText, @hDc, addr szText, -1,\ addr @stRect,\ DT_SINGLELINE or DT_CENTER or DT_VCENTER invoke EndPaint, hWnd, addr @stPs ;----------------------------------------------------------- .elseif eax == WM_CREATE ;为了右键菜单使用,实际上应该自己定义一个 invoke GetSubMenu, hMenu, 1 mov hSubMenu, eax ;在系统菜单中添加自己的菜单(右键标题栏) ;此菜单发送WM_SYSCOMMAND ;invoke GetSystemMenu, hWnd, FALSE ;mov @hSysMenu, eax ;invoke AppendMenu, @hSysMenu, MF_SEPARATOR, 0, NULL ;invoke AppendMenu, @hSysMenu, 0, IDM_HELP, offset szMenuHelp ;invoke AppendMenu, @hSysMenu, 0, IDM_ABOUT, offset szMenuAbout ;----------------------------------------------------------- .elseif eax == WM_COMMAND ;用户选择一个菜单项(非系统菜单),用户按下一个快捷键(非系统键),都处理成返回到主窗口处理 ;通知用户按下菜单的ID---------------------------- invoke _DisplayMenuItem, wParam ;wParam里保存着通知码和ID值(菜单项和对应的快捷键返回同一个wParam) ;WM_COMMAND就是这样定义的 ;取出ID,进行判断---------------------------------- mov eax, wParam movzx eax, ax .if eax == IDM_EXIT call _Quit .endif ;----------------------------------------------------------- .elseif eax == WM_SYSCOMMAND ;用户选择一个系统菜单,用户按下一个系统快捷键,都处理成返回到主窗口处理 ;取出ID,进行判断---------------------------------- mov eax, wParam movzx eax, ax .if eax == IDM_HELP || eax == IDM_ABOUT invoke _DisplayMenuItem, wParam .else ;除了系统快捷键和自己定义的系统菜单外,其他交给系统去处理,一下为套路 invoke DefWindowProc, hWnd, uMsg, wParam, lParam ret .endif ;----------------------------------------------------------- .elseif eax == WM_RBUTTONDOWN ;BOOL GetCursorPos(LPPOINT lpPoint); ;把光标所在坐标存入POINT中 invoke GetCursorPos, addr @stPos ;BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWND hWnd, CONST RECT* prcRect); ;hMenu:此句柄可为调用CreatePopupMenu创建的新快捷菜单的句柄,也可以为调用GetSubMenu取得的与一个已存在菜单项相联系的子菜单的句柄。 ;uFlags:TPM_CENTERALIGN:x居中放置,TPM_LEFTALIGN:左边界与X对齐,TPM_RIGHTALIGN:右边界与X对齐 ;NReserved:保留值,必须为零 ;HWnd:拥有快捷菜单的窗口的句柄,hInstance,在_ProcWinMain中是hWnd ;prcRect:NULL,在菜单外单击菜单消失 invoke TrackPopupMenu, hSubMenu, TPM_LEFTALIGN, @stPos.x, @stPos.y, 0, hWnd, NULL ;----------------------------------------------------------- .elseif eax == WM_CLOSE ;套路 ;invoke DestroyWindow, hWinMain ;invoke PostQuitMessage, NULL call _Quit ;----------------------------------------------------------- .else invoke DefWindowProc, hWnd, uMsg, wParam, lParam ;不感兴趣交给系统处理 ret .endif ;----------------------------------------------------------- xor eax, eax ;清零返回 ret _ProcWinMain endp ;----------------------------------------------------------------------- _WinMain proc local @stWndClass: WNDCLASSEX local @stMsg: MSG local @hAccelerator ;注册窗口类----------------------------------------------- ;获取本模块句柄------------------------------------------- invoke GetModuleHandle, NULL ;获取本模块句柄存入eax中 mov hInstance, eax ;存入全局变量hInstance中 ;获取菜单句柄--------------------------------------------- ;HMENU LoadMenu(HINSTANCE hlnstance,LPCTSTR lpMenuName); ;若函数调用成功,则返回所加载的菜单句柄,若函数调用失败,则返回值为NULL ;hlnstance:含有被加载菜单资源的实例模块的句柄 ;LpMenuName:低位字16bit资源标识符,高位字16bit全零 ;----------------------------------------------------------- invoke LoadMenu, hInstance, IDM_MAIN ;必须获取菜单句柄 mov hMenu, eax ;获取快捷键句柄------------------------------------------- ;HACCEL LoadAccelerators(HINSTANCE hlnstance,LPCTSTR lpTableName); ;lpTableName:低位字16bit资源标识符,高位字16bit全零 ;----------------------------------------------------------- invoke LoadAccelerators, hInstance, IDA_MAIN ;必须获取快捷键句柄 mov @hAccelerator, eax ;必须改写消息循环 ;----------------------------------------------------------- invoke RtlZeroMemory, addr @stWndClass, sizeof @stWndClass ;必须初始化局部变量 ; ;hIcon!!! ; ;hCursor!!! ; ;lpszMenuName!!! push hInstance ;hInstance pop @stWndClass.hInstance mov @stWndClass.cbSize, sizeof WNDCLASSEX ;cbsize mov @stWndClass.style, CS_HREDRAW or CS_VREDRAW ;style!!! mov @stWndClass.lpfnWndProc, offset _ProcWinMain ;lpfnWndProc mov @stWndClass.hbrBackground, COLOR_WINDOW + 1 ;hbrBackground!!! mov @stWndClass.lpszClassName, offset szClassName ;lpszClassName ; ;cbWndExtra ; ;cbClsExtra invoke RegisterClassEx, addr @stWndClass ;stWndClass是一个结构体 ;----------------------------------------------------------- ;创建窗口-------------------------------------------------- invoke CreateWindowEx, WS_EX_CLIENTEDGE,\ ;dwExStyle!!! offset szClassName, offset szCaptionMain,\ ;lpClassName, lpWindowMain WS_OVERLAPPEDWINDOW,\ ;dwStyle!!! 100, 100, 600, 400,\ ;x, y, nWight, nHeight NULL, hMenu, hInstance, NULL ;hWndParent!!!, hMenu!!!, hInstance, lpParam!!! mov hWinMain, eax ;显示窗口-------------------------------------------------- invoke ShowWindow, hWinMain, SW_SHOWNORMAL ;SW!!! ;更新窗口-------------------------------------------------- invoke UpdateWindow, hWinMain ;----------------------------------------------------------- ;消息循环-------------------------------------------------- ;|--------------------------------------------------------------------------------------------------------------| ;|.while TRUE | ;| invoke GetMessage, addr @stMsg, NULL, 0, 0 ;lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax | ;| ;addr @stMsg | ;| ;hWnd NULL 本程序所属窗口 | ;| ;wMsgFilterMax = wMsgFilterMin = 0 获取所有消息 | ;| .break .if eax == 0 ;WM_QUIT eax = 0, 退出消息循环 | ;| invoke TranslateMessage, addr @stMsg ;WM_CHAR, WM_SYSCHAR, 键盘消息转换 | ;| invoke DispatchMessage, addr @stMsg ;发送到窗口过程函数 | ;|.endw | ;|--------------------------------------------------------------------------------------------------------------| .while TRUE invoke GetMessage, addr @stMsg, NULL, 0, 0 .break .if eax == 0 ;系统自动完成快捷键检测功能---------------------- ;int TranslateAccelerator(HWND hWnd,HACCEL hAccTable,LPMSG IpMsg); ;若函数调用成功,则返回非零值;若函数调用失败,则返回值为零(没找到快捷键的消息) ;hWnd:消息被发送到这个窗口处理 ;hAccTable:快捷键表句柄 ;lpMsg:从GetMessage或PeekMessage从消息队列获取的消息 ;--------------------------------------------------- invoke TranslateAccelerator, hWinMain, @hAccelerator, addr @stMsg .if eax == 0 invoke TranslateMessage, addr @stMsg invoke DispatchMessage, addr @stMsg .endif .endw ret _WinMain endp ;----------------------------------------------------------------------- start: call _WinMain invoke ExitProcess, NULL end start ;-----------------------------------------------------------------------
相关文章推荐
- 如何重装TCP/IP协议
- Windows 8 官方高清壁纸欣赏与下载
- 谁是桌面王者?Win PK Linux三大镇山之宝
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows Clang开发环境备忘
- 从Windows系统下访问Linux分区相关软件
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows下搭建本地SVN服务器
- 使用Windows原生命令一键清空剪贴板
- windows用windeployqt发布qt quick application程序
- 利用开源软件打造自己的全功能远程工具
- Windows 8虚拟机不能全屏的解决方法
- 虚拟化基础架构Windows 2008篇之1-虚拟化基础服务概述
- 虚拟化基础架构Windows 2008篇之5-安装Windows部署服务
- 虚拟化基础架构Windows 2008篇之7-添加其他操作系统的安装镜像
- 虚拟化基础架构Windows 2008篇之9-配置Windows部署服务
- 虚拟化基础架构Windows 2008篇之12-WSUS工作站端配置
- Visual Studio 2012 示例代码浏览器 - 数以千计的开发示例近在手边,唾手可得