标题:发一个罗云斌menu代码的详细解释,由于自己是一个不小的菜鸟,如果有不足和 ...
只看楼主
daxiajzs
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2010-10-19
结帖率:0
已结贴  问题点数:20 回复次数:5 
发一个罗云斌menu代码的详细解释,由于自己是一个不小的菜鸟,如果有不足和错误之处还望指正,感激不尽
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 2nd Edition>
; by 罗云彬, http://asm.
;程序详细注释:by 塘鱼
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Menu.asm
; 菜单资源的使用例子
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Menu.asm
; rc Menu.rc
; Link /subsystem:windows Menu.obj Menu.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .386
        .model flat, stdcall
        option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include        windows.inc
include        user32.inc
includelib    user32.lib
include        kernel32.inc
includelib    kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN    equ        1000h    ;图标
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_SMALL    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
IDM_APP        equ        4303h            ;塘鱼定义的测试参数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .data?
hInstance    dd        ?            ;实例句柄
hWinMain    dd        ?            ;主程序句柄
hMenu        dd        ?            ;主菜单句柄
hSubMenu    dd        ?            ;子菜单句柄,注意这里的子菜单也必须是一个顶层菜单不能是二级菜单即;popup类型的
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .const
szClassName    db    'Menu Example',0            ;定义程序窗口类名
szCaptionMain    db    'Menu',0                ;定义程序名字
szMenuHelp    db    '帮助主题(&H)',0            ;定义菜单窗口HELP
szMenuAbout    db    '关于本程序(&A)...',0
szCaption    db    '菜单选择',0               
szFormat    db    '您选择了菜单命令:%08x',0        ;窗口格式定义
szApp        db    '塘鱼',0                ;塘鱼定义的一个测试参数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_DisplayMenuItem    proc    _dwCommandID            ;显示窗口菜单ID的函数,读者可以比较,是否和资源文件中的定义一致
            local    @szBuffer[256]:byte        ;预定义一个256字节的区域作为缓冲区;buffer
               
        pushad                        ;函数开始时,保护好现场
        invoke    wsprintf,addr @szBuffer,addr szFormat,_dwCommandID        ;调用wsprintf函数格式化字符串format
        invoke    MessageBox,hWinMain,addr @szBuffer,offset szCaption,MB_OK    ;调用窗口函数,显示格式化好了的字符串,其在buffer去中
        popad                        ;函数结束后还原现场,pop掉所有被保护的参数
        ret                        ;程序从此地返回

_DisplayMenuItem    endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Quit        proc                        ;退出程序
               
        invoke    DestroyWindow,hWinMain            ;销毁程序窗口
        invoke    PostQuitMessage,NULL            ;发送结束消息循环指令,从此退出循环,这个过程不可更改
        ret                        ;程序从此地返回

_Quit        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain    proc    uses ebx edi esi hWnd,uMsg,wParam,lParam        ;过程处理程序的初始化定义
        local    @stPos:POINT                        ;定义了一个结构体:POINT,用来获取鼠标光标的信息
        local    @hSysMenu                        ;定义了系统菜单的句柄

        mov    eax,uMsg                        ;将消息结构体Msg的值放到eax中,分支处理eax
        .if    eax ==    WM_CREATE                    ;发出创建窗口命令
            invoke    GetSubMenu,hMenu,1                ;获得子菜单句柄,这里是查看菜单,因为:npos被指定为1
            mov    hSubMenu,eax
;********************************************************************
;    在系统菜单中添加菜单项
;********************************************************************
            invoke    GetSystemMenu,hWnd,FALSE            ;获取系统菜单句柄,并用AppendMenu函数添加命令
            mov    @hSysMenu,eax
            invoke    AppendMenu,@hSysMenu,MF_SEPARATOR,0,NULL        
            ;调用添加菜单函数,添加HELP和ABOUT菜单到系统菜单上
            invoke    AppendMenu,@hSysMenu,0,IDM_HELP,offset szMenuHelp        
            invoke    AppendMenu,@hSysMenu,0,IDM_ABOUT,offset szMenuAbout
            ;这时候你可以做个小实验尝试一下即取消我注释掉的自己添加的菜单,编译连接。
            ;invoke    AppendMenu,@hSysMenu,0,IDM_APP,offset    szApp
            
;********************************************************************
; 处理菜单及加速键消息
;********************************************************************
        .elseif    eax ==    WM_COMMAND                    
            invoke    _DisplayMenuItem,wParam                ;调用显示菜单函数显示菜单命令ID读者可以和资源文件中的定义比较,呵呵一定是一模一样的
            mov    eax,wParam                    ;wParam中间存放的是通知码和命令ID
            movzx    eax,ax                        ;将ax扩展成32位,这里的作用是忽视掉由加速键发送的命令,将其一并处理,这样做的好处是精简代码,把高16位扩展成了0
            .if    eax ==    IDM_EXIT                ;分支判断程序是否结束
                call    _Quit                    ;如果结束,调用退出函数_quit
            .elseif    eax >=    IDM_TOOLBAR && eax <= IDM_STATUSBAR    ;程序检查,IDM_TOORBAR到IDM_STATUSBAR之间的命令是否被选中
                mov    ebx,eax                    ;如果被选中,用ebx保存被选定的命令ID
                invoke    GetMenuState,hMenu,ebx,MF_BYCOMMAND    ;调用getmenustate函数检查菜单的状态,由于uflag中定义的是me_bycommand所以使用的是命令ID形式
                .if    eax ==    MF_CHECKED            ;检测命令ID是否被选中,如果选中则撤销选中
                    mov    eax,MF_UNCHECKED
                .else
                    mov    eax,MF_CHECKED            ;检测命令ID是否被选中,如果未被选中则选中
                .endif
                invoke    CheckMenuItem,hMenu,ebx,eax        ;调用checkmenuitem函数,将IMD_BIG和IDM_DETAIL定义为互斥空间,在此区间内永远只有一个被选中
            .elseif    eax >=    IDM_BIG && eax <= IDM_DETAIL
                invoke    CheckMenuRadioItem,hMenu,IDM_BIG,IDM_DETAIL,eax,MF_BYCOMMAND    ;调用checkmenuradioitem函数检测互斥空间,eax中是被选中的命令ID其余的将被撤销
            .endif
;********************************************************************
; 处理系统菜单消息
;********************************************************************
        .elseif    eax == WM_SYSCOMMAND                        ;调用WM_SYSCOMMAND命令处理系统命令
            mov    eax,wParam                        ;这一步主要是为了把wparam的高字节扩展成0
            movzx    eax,ax                            ;可以方便程序一并处理加速键和菜单命令,可以简化程序
            .if    eax == IDM_HELP || eax == IDM_ABOUT || eax == IDM_APP    ;这是我们自己添加修改的系统菜单,我们调用_displaymenutiem函数
                invoke    _DisplayMenuItem,wParam                ;可以让她显示出命令ID这是会和我们资源中的定义是一样的
            .else                                
                invoke    DefWindowProc,hWnd,uMsg,wParam,lParam        ;调用DefWindowProc函数是为了处理默认的系统消息,如放大移动缩小还原
                ret                            ;程序从此地返回
            .endif
;********************************************************************
; 按下右键时弹出一个POPUP菜单
;********************************************************************
        .elseif eax == WM_RBUTTONDOWN                        ;右键菜单需要调用消息,WM_RBUTTONDOWN
            invoke    GetCursorPos,addr @stPos                ;首先获取鼠标信息,存入以定义的结构体:@stPos
            invoke    TrackPopupMenu,hSubMenu,TPM_LEFTALIGN,@stPos.x,@stPos.y,NULL,hWnd,NULL        ;调用函数TrackPopupMenu从客服区单击鼠标的方式弹出右键菜单@stPos.x,@stPos.y是结构体,@stPos中存放鼠标位置的参数
;********************************************************************
        .elseif    eax ==    WM_CLOSE                        ;收到关闭窗口的命令,调用QUTI函数销毁窗口,这一过程不可逆转
            call    _Quit
;********************************************************************
        .else
            invoke    DefWindowProc,hWnd,uMsg,wParam,lParam            ;否则按照默认方式处理窗口
            ret
        .endif
;********************************************************************
        xor    eax,eax                                ;清空eax的值并返回
        ret

_ProcWinMain    endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain    proc
        local    @stWndClass:WNDCLASSEX            ;定义WNDCLASSEX结构体用来存储窗口风格
        local    @stMsg:MSG                ;定义消息结构体,用来给过程处理函数执行
        local    @hAccelerator                ;定义参数用来保存加速键句柄,以备后面使用

        invoke    GetModuleHandle,NULL            ;获取实例句柄
        mov    hInstance,eax
        invoke    LoadMenu,hInstance,IDM_MAIN        ;调用loadmenu函数,获取菜单句柄,和要加载资源的命令ID这里是:IDM_MAIN   
        mov    hMenu,eax
        invoke    LoadAccelerators,hInstance,IDA_MAIN    ;获取加速键句柄
        mov    @hAccelerator,eax
;********************************************************************
; 注册窗口类
;********************************************************************
        invoke    RtlZeroMemory,addr @stWndClass,sizeof @stWndClass    ;将结构体参数清0
        invoke    LoadIcon,hInstance,ICO_MAIN                ;获取默认窗口图标和程序图标
        mov    @stWndClass.hIcon,eax
        mov    @stWndClass.hIconSm,eax
        invoke    LoadCursor,0,IDC_ARROW                    ;获取默认鼠标指针
        mov    @stWndClass.hCursor,eax
        push    hInstance
        pop    @stWndClass.hInstance                    ;传递句柄,由于两个操作数都在内存中,所以要用PUSH和POP指令
        mov    @stWndClass.cbSize,sizeof WNDCLASSEX            ;定义结构体的大小,以方便微软对版本的区别
        mov    @stWndClass.style,CS_HREDRAW or CS_VREDRAW        ;定义窗口风格
        mov    @stWndClass.lpfnWndProc,offset _ProcWinMain        ;最重要的一个参数,用来确定调用窗口过程的地址
        mov    @stWndClass.hbrBackground,COLOR_WINDOW + 1        ;定义窗口的背景,注意的是需要在参数后+1
        mov    @stWndClass.lpszClassName,offset szClassName        ;要创建窗口类的名称
        invoke    RegisterClassEx,addr @stWndClass            ;注册窗口函数其中Ex,是又16位扩展的风格
;********************************************************************
; 建立并显示窗口
;********************************************************************
        invoke    CreateWindowEx,WS_EX_CLIENTEDGE,\            ;建立窗口函数
            offset szClassName,offset szCaptionMain,\
            WS_OVERLAPPEDWINDOW,\
            100,100,400,300,\
            NULL,hMenu,hInstance,NULL
        mov    hWinMain,eax
        invoke    ShowWindow,hWinMain,SW_SHOWNORMAL            ;显示窗口和刷新客服区
        invoke    UpdateWindow,hWinMain
;********************************************************************
; 消息循环
;********************************************************************
        .while    TRUE                        
            invoke    GetMessage,addr @stMsg,NULL,0,0            ;从消息队列中获取消息
            .break    .if eax    == 0
            invoke    TranslateAccelerator,hWinMain,@hAccelerator,addr @stMsg        ;加速键消息处理(注:加速键即快捷键)
            .if    eax == 0                            ;处理完毕后检查eax的值,如果返回值为0,即处理完毕就继续消息的转换和分配,这样做的好处就是,不会把加速键交给DISPATH函数分配执行
                invoke    TranslateMessage,addr @stMsg            
                invoke    DispatchMessage,addr @stMsg                ;分配消息给过程处理函数
            .endif
        .endw
        ret

_WinMain    endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:                                            ;程序入口点
        call    _WinMain
        invoke    ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        end    start
搜索更多相关主题的帖子: 罗云斌 menu 感激不尽 代码 
2010-12-10 22:11
xiaomarn
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:5
帖 子:348
专家分:2026
注 册:2009-3-18
得分:10 
哦,恩,看看!
2010-12-17 11:02
Alar30
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:10
帖 子:988
专家分:1627
注 册:2009-9-8
得分:10 
好长
洗澡了回头再来看
2010-12-19 20:28
jackieruo
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2010-12-26
得分:0 
真的好长,吃饭再看看
2010-12-26 19:39
csdn2006
Rank: 1
来 自:四川成都
等 级:新手上路
帖 子:14
专家分:0
注 册:2015-4-4
得分:0 
真心感谢楼主 你太好了 谢谢 对我们新手帮助太大了 辛苦了 望多发这样的帖

学习win32汇编   Assembly  Language 强势崛起
2015-04-04 23:05
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:0 
~~~~~~~~~~~

能编个毛线衣吗?
2015-04-04 23:07



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-328662-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.742322 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved