| 网站首页 | 资讯 | Hack | 漏洞 | 网管 | 编程 | 培训 | 品黑页 | 软件 | 论坛 | 动画 | 视频 | 经典 | 教学站 | 黑客点睛 | 
服务导航 我要发布 主力频道 空间域名 精华收集 服务器出租 黑客培训 光盘刻录 特色服务 解决方案 我要投诉
您现在的位置: 华夏黑客同盟 >> 编程 >> 其它编程 >> 正文 用户登录 新用户注册
Win32汇编教程五           ★★★ 【字体:
Win32汇编教程五
作者:不详 文章来源:华盟收集 点击数: 更新时间:2007-7-9

有关菜单和加速键
    菜单是Windows标准界面的最重要的组成部分,窗口的菜单条位于标题栏的下方,这个菜单通常被称为主菜单,列在主菜单下面的菜单项被称为下拉式菜单,或弹出式菜单、子菜单等,而在标题栏左边的图标上点击也会弹出一个菜单,叫做系统菜单。加速键实际上是菜单项的快捷键,应用程序常在菜单项的右边标出激活这个菜单项的快捷键,这就是加速键。菜单的结构是可嵌套的,也就是说,你可以在选择一个菜单项时弹出另一个菜单。菜单项的种类有正常的、被禁用的、灰化的、水平分隔线等。本节的示范程序演示了各种类型的菜单:你可以在主菜单中看到正常的和禁用的、灰化的菜单,可以用右键单击窗口的任一部分弹出一个“弹出式菜单”,也可以看到我在系统菜单中添加了几项新的内容。
    在编程的处理中,菜单是在资源文件中定义的(当然,你可以不用资源文件,而在程序中用AppendMenu一项一项的添加,但使用资源文件无疑是最简单的办法),然后在程序中用LoadMenu来获得菜单句柄再使用。在资源文件中定义菜单的语法如下:

以下是代码片段:
菜单ID menu discardable
BEGIN
 popup "主菜单项一"
 BEGIN
  menuitem "弹出式菜单项一", 命令ID [,OPTION]
  menuitem "弹出式菜单项二", 命令ID [,OPTION]
  menuitem separator
  menuitem "弹出式菜单项三", 命令ID [,OPTION]
  ...
 END
 popup "主菜单项二"
 BEGIN
  menuitem "弹出式菜单项一", 命令ID [,OPTION]
  menuitem "弹出式菜单项二", 命令ID [,OPTION]
  menuitem "弹出式菜单项三", 命令ID [,OPTION]
  ...
  popup  "嵌套的菜单项"
  BEGIN
  menuitem "弹出式菜单项一", 命令ID [,OPTION]
  menuitem "弹出式菜单项二", 命令ID [,OPTION]
  menuitem "弹出式菜单项三", 命令ID [,OPTION]
  ...
  END
 END
 ...
END
菜单ID就是我们在程序中用LoadMenu装入菜单用到的资源编号,menuitem separator 定义了分隔菜单项用的水平线,菜单项定义中的option是属性,如GRAYED是灰化的,INACTIVE是被禁用的等等。而加速键实际上就是定义了对应于各个菜单项的热键,定义方法如下:

加速键ID accelerators
BEGIN
  VK_F1, 对应的菜单命令ID, VIRTKEY
  VK_F2, 对应的菜单命令ID, VIRTKEY
  ...
  "A", 对应的菜单命令ID, VIRTKEY,CONTROL
  "B", 对应的菜单命令ID, VIRTKEY,CONTROL
END
其中,加速键ID是我们在程序中用LoadAccelerator装入加速键的资源编号,下面的每一项定义了一个键,VK_F1表示用F1,“A”表示键A,下面的VIRTKEY是必需的,再下面的CONTROL“或SHIFT、ALT”表示用CONTROL键组合,也就是说,如果你定义了:"C",IDM_COPY,VIRTKEY,CONTROL 而且在菜单定义中定义了 menuitem "拷贝",IDM_COPY,那么,你在程序中按下Ctrl-C实际上就是执行了菜单项“拷贝”。
    菜单和加速键的编程是很简单的,初始化的部分你需要做以下事情:

取得程序的实例句柄(hInstance)
用LoadMenu装入菜单,得到菜单句柄
用LoadAccelerator装入加速键,得到加速键句柄
注册窗口类
创建窗口时在参数中制定菜单句柄
显示窗口
然后进入消息循环,在消息循环中用TranslateAccelerator来进行加速键的检测(详见源程序)
当窗口显示后,当一个菜单项或一个加速键被按下时,Windows向窗口过程发送WM_COMMAND消息,而当一个系统菜单中的菜单项被按下时,Windows 向窗口过程发送WM_SYSCOMMAND,菜单项命令的ID就包括在wParam的低16位中,在一般的编程中,如果我们不对系统菜单消息进行处理,那么只需在WM_COMMAND消息的处理中建立一段 .if/.elseif/.elseif .../.endif的语句对各个菜单命令ID进行处理就行了。

使用菜单和加速键的源程序

 
以下是代码片段:
.386
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Programmed by 罗云彬, bigluo@telekbird.com.cn
; Website: http://asm.yeah.net
; LuoYunBin's Win32 ASM page (罗云彬的编程乐园)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  .model flat, stdcall
  option casemap :none   ; case sensitive

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

include  windows.inc
include  user32.inc
include  kernel32.inc
include  comctl32.inc
include  comdlg32.inc
include  shell32.inc
include  gdi32.inc

includelib user32.lib
includelib kernel32.lib
includelib comctl32.lib
includelib comdlg32.lib
includelib shell32.lib
includelib gdi32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

IDI_MAIN equ  1000  ;icon
IDA_MAIN equ  2000  ;Accelerator

IDM_MAIN equ  4000
IDM_OPEN equ  4101
IDM_OPTION equ  4102
IDM_EXIT equ  4103
IDM_SETFONT equ  4201
IDM_SETCOLOR equ  4202
IDM_FIND equ  4203
IDM_FINDPREV equ  4204
IDM_FINDNEXT equ  4205
IDM_TOOLBAR equ  4206
IDM_TOOLBARTEXT equ  4207
IDM_INPUTBAR equ  4208
IDM_STATUSBAR equ  4209
IDM_HELP equ  4301
IDM_ABOUT equ  4302

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  .data?

hIcon  dd  ?
hInstance dd  ?
hWinMain dd  ?
hMenu  dd  ?
hSubMenu dd  ?
szBuffer db 256 dup (?)
dwFlag  dd  ?
;********************************************************************
; 标志位定义
F_TOOLBAR equ 00000001b
F_TOOLBARTEXT equ 00000010b
F_INPUTBAR equ 00000100b
F_STATUSBAR equ 00001000b

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  .data

szClassName db "Menu Example",0
szCaptionMain db '菜单应用示例',0
szMenuHelp db "帮助主题(&H)",0
szMenuAbout db "关于本程序(&A)...",0

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  .code

include  Debug.asm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 程序开始
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
  call _WinMain
  invoke ExitProcess,NULL

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 主窗口程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain proc
  local @stWcMain:WNDCLASSEX
  local @stMsg:MSG
  local @hAccelerator

  invoke InitCommonControls
  invoke GetModuleHandle,NULL
  mov hInstance,eax
  invoke LoadIcon,hInstance,IDI_MAIN
  mov hIcon,eax
  invoke 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使用。

责任编辑:郭瑞  联系方式  Email:郭瑞
电话:51228163
  • 上一篇编程:

  • 下一篇编程:
  • (只显示最新5条。评论内容只代表网友观点,与本站立场无关!)
    姓 名:
    * 游客填写  ·注册用户
    主 页:
    评 分:
    1分 2分 3分 4分 5分
    评论内容:
    验证码: *
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  • 最新hack更新
    最新推荐资讯
    相关编程
    学习汇编基础入门知识
    学习汇编基础入门知识
    学习汇编基础入门知识
    修改特征码掌握的知识
    Win32平台下Rootkit习作
    汇编ring3实现HOOKAPI
    汇编创建简单的窗口
    学习汇编基础入门知识
    MD5算法汇编代码[着重优化]
    安全探讨之用Win32汇编写双进程守
    最新会员软件
    最新推荐视频
    最新推荐动画

    Copyright @ 2005 77169.Net Inc. All rights reserved. 华夏黑客同盟 版权所有
    北京市电信通提供网络带宽

    mailto:webmaster@77169.net
    咨询QQ号:836982 / 59280880
    联系站长 QQ38588913
    热线电话: 86-10-67634029/676229433
    京ICP证041431号