📄 005.txt
字号:
● 选项——可以是Alt,Control或Shift中的单个或多个,如果指定多个,则中间用逗号隔开,表示加速键是按键加上这些控制键的组合键。这些选项只能在类型是VIRTKEY的情况下才能使用。
在键名的定义中,系统按键如F1,F2,BackSpace和Esc等都是用虚拟键的方法定义的,Resource.h中已经包括所有的预定义,它们是以VK_带头的一些值,如VK_BACK,VK_TAB,VK_RETURN,VK_ESCAPE,VK_DELETE,VK_F1和VK_F2等,读者可以查看Resource.h文件。下面是加速键定义的一些例子:
"^C", ID ;Ctrl+C
"K", ID ;Shift+K
"k", ID,ALT ;Alt+k
98, ID,ASCII ;b(字符b的ASCII码为98)
66, ID,ASCII ;B (Shift b)
"g", ID ;g
VK_F1, ID,VIRTKEY ;F1
VK_F1, ID,VIRTKEY,CONTROL ;Ctrl+F1
VK_F2, ID,VIRTKEY,ALT,SHIFT ;Alt+Shift+F2
在一个资源脚本文件中,可以定义多个菜单和多个加速键表,当然也有其他各式各样的资源,有位图、图标与对话框等,这就涉及为这些资源取ID值的问题,取值的时候要掌握的原则是:
(1)对于同类别的多个资源,资源ID必须为不同的值,如定义了两个菜单,那么它们的ID就必须用不同的数值表示,否则将无法分辨。
(2)对于不同类别的资源,资源ID在数值上可以是相同的,如可以将菜单和加速键的ID都定义为1,同时也可以有ID为1的位图或图标等,Windows并不会把它们搞混。
5.1.3 使用菜单和加速键
在完成资源文件所示的编写后,来看看如何在程序中使用菜单和加速键,例子程序的运行界面如图5.1所示,这里先列出程序的功能说明,读者可以先尝试一下,以便在以下的程序分析中有所印象。程序功能如下:
● 程序在用户选择了任何一个菜单项以后,会弹出一个对话框,将接收到的菜单命令ID显示出来。
● 选择“大图标”、“小图标”、“列表”和“详细资料”菜单项后,选中的菜单项前面会出现一个圆点选中标记,4个菜单项的选择是互斥的。
● 在“状态栏”及“工具栏”菜单的3个菜单项中选择后,选中的菜单项前面会出现对钩标记,它们是不互斥的。
● 在窗口的客户区单击鼠标右键会弹出和“查看”菜单一致的弹出式菜单。
● 在标题栏图标上单击鼠标左键,会弹出系统菜单,注意上面比默认的菜单多了两项:“帮助主题”和“关于本程序”。
接下来,将逐步分析这些功能是如何实现的。下面是Menu.asm源代码,代码是在第4章的FirstWindow程序的基础上改写的,这是编写Win32汇编程序的一个常用方法——拷贝一个模板程序再进行修改会节省很多的时间。
.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
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance dd ?
hWinMain dd ?
hMenu dd ?
hSubMenu dd ?
.const
szClassName db ~Menu Example~,0
szCaptionMain db ~Menu~,0
szMenuHelp db ~帮助主题(&H)~,0
szMenuAbout db ~关于本程序(&A)...~,0
szCaption db ~菜单选择~,0
szFormat db ~您选择了菜单命令:%08x~,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_DisplayMenuItem proc _dwCommandID
local @szBuffer[256]:byte
pushad
invoke wsprintf,addr @szBuffer,addr szFormat,_dwCommandID
invoke MessageBox,hWinMain,addr @szBuffer,\
offset szCaption,MB_OK
popad
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
local @hSysMenu
mov eax,uMsg
.if eax == WM_CREATE
invoke GetSubMenu,hMenu,1
mov hSubMenu,eax
;********************************************************************
;在系统菜单中添加菜单项
;********************************************************************
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
invoke _DisplayMenuItem,wParam
mov eax,wParam
movzx eax,ax
.if eax == IDM_EXIT
call _Quit
.elseif eax >= IDM_TOOLBAR && eax <= IDM_STATUSBAR
mov ebx,eax
invoke GetMenuState,hMenu,ebx,MF_BYCOMMAND
.if eax == MF_CHECKED
mov eax,MF_UNCHECKED
.else
mov eax,MF_CHECKED
.endif
invoke CheckMenuItem,hMenu,ebx,eax
.elseif eax >= IDM_BIG && eax <= IDM_DETAIL
invoke CheckMenuRadioItem,hMenu,\
IDM_BIG,IDM_DETAIL,eax,MF_BYCOMMAND
.endif
;********************************************************************
; 处理系统菜单消息
;********************************************************************
.elseif eax == WM_SYSCOMMAND
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
;********************************************************************
; 单击鼠标右键时弹出一个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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -