菜单及其他资源

使用资源的好处之一在于程序的许多组件能连编进程序的.exe文件。作为资源,它被存储在开发者计算机上的单独的可编辑文件中,但在编译中被连进.exe文件中。

将图标添加到程序。对于图标,可以使用ImageEditor来绘制图标的图像。它被存储在.ico文件中Developer Studio还生成了一个资源描述文件,它列出了所有资源和一个程序引用资源的头文件。

图标

得到图标的句柄使用LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));获得图标的大小使用GetSystemMetrics(SM_CXICON)GetSystemMetrics(SM_CYICON)

显示图标使用DrawIcon,其中位置时被显示图标左上角的坐标。LoadIcon的第二个参数实际上被定义为指向字符串的指针而不是用数字的指针。其实图标的标识符可以为字符串。可以使用两者之一的方式引用图标。

在程序中使用图标

RegisterClass有一个改进版叫做RegisterClassEx,它使用WNDCLASSEX结构。WNDCLASSEX有两个附加字段,cbSizehIconSm。这样可以设置两个图标文件,一个用于标准大小图标,另一个用于小图标。

如果希望程序运行时动态的更改程序图标,可以使用SetClassLongGCL_HICON来达到目的。同样可以在程序的其他位置使用GetClassLong来获得句柄。

Windows的某些文档中,LoadIcon被称为“过时的”,并推荐使用LoadImage,当然LoadImage更灵活,但它没有LoadIcon简单。LoadIcon是获取句柄不用释放的少数几个函数之一。

使用子定义光标

可以在类中通过LoadCursor设置自定义光标。当鼠标位于根据这个类创建的窗口时,就会显示类中定义的光标。也可以改变窗口类的hCursor,使用SetClassLongGCL_HCURSOR。如果将客户区划分为较小的区域而不使用子窗口。可以使用SetCursor来改变鼠标光标。在Windows处理WM_MOUSEMOVE消息期间,应该调用SetCursor否则,当光标移动时,Windows使用窗口类中定义的光标来重画光标。文档指出,如果没有改变光标,SetCursor速度很快。

字符串资源

字符串资源主要是为了使程序转换成其他语言的过程更加方便。如果创建程序的另一个版本,只需要重新连接,这样比重新组织代码安全的多。然而,字符串表使代码看起来更模糊和复杂。

程序可以使用LoadString把字符串赋值到程序数据段的缓冲。所有资源文本,包括字符串表中的文本,都以Unicode格式存储在.RES编译资源文件,及最终的.exe文件中。

定制资源

Windows还可以“定制资源”也叫用户定义的资源。定制资源为连接.exe文件中各种数据提供了方便,对获取程序中的数据也是如此。程序用于访问定制资源的Windows函数促使Windows将数据加载到内存中,并返回指向它的指针。然后就可以对程序做任何操作。对于存储和访问各种私有数据,比把数据存储在外部文件中,再使用文件输入函数访问它方便的多。

通过hResource = LoadResource( hInstance, FindResource( hInstance, “rs”, MAKEINTERSOURCE( IDR_BINTYPE)));得到指向内存块的句柄。LoadResource 不会将资源立即加载到内存。联合使用LoadResourceFindResource函数实质上类似LoadIconLoadCursor函数,其实LoadIconLoadCursor用到了他们。

当需要访问文本使用LockResourceLockResource将资源加载到内存返回一个指向资源的指针。当结束时,可以从内存释放它FreeResource

菜单

可以想成顶层菜单和每个弹出菜单是独立的。顶层菜单有一个菜单句柄,每个弹出菜单也有它自己的菜单句柄。系统菜单也有菜单句柄。

菜单中每项都有三个特性。
第一个特性是菜单中显示什么,是字符串还是位图。
第二个特性是WM_COMMAND消息发送给程序的菜单ID
第三个特性是菜单项的属性,包括是否被禁用、灰化或被选中。

引用菜单

大多数Windows应用程序在资源描述文件中只有一个菜单。也可以使用其他方法。Windows程序可以使用LoadMenu函数将菜单资源加载到内存,如同LoadIconLoadCursor函数。

LoadMenu返回一个菜单句柄,然会可以将这个菜单句柄作为CreatWindow的参数。这是CreateWindow指定的菜单可以把窗口类中菜单看作基于这个窗口类的默认菜单。窗口创建后也可以使用SetMenu给窗口指定一个菜单,这种方式可以动态的修改菜单。

当窗口被消除时,同窗口相关的菜单都将被消除。同窗口不相关的菜单在程序结束前通过调用DestroyMenu显式地清除。

菜单和消息

当用户选择一个菜单项时,Windows发送WN_INTMENU消息。它地wParam是主菜单句柄,即使用户选择的是系统菜单的项。可以通过这个消息来修改菜单。

WM_MENUSELECT消息是用户在菜单项中移动光标或鼠标,WM_MENUSELECT是一个菜单跟踪消息,wParam的低位表明了当前选中的是菜单的哪一项。高位是选择标志。lParam是选中项的菜单按钮。

Windows准备显示一个弹出菜单时,它给窗口过程发送一个WM_INITMENUPOPUP消息,其中wParam为弹出菜单句柄,lParam地位为弹出菜单索引,高位为1时表明是系统菜单,0表示其他。

最重要的是WM_COMMAND消息,它也可以由子窗口产生。如果为菜单和子窗口使用同一ID可以通过lParam来区分他们。

WM_SYSCOMMAND消息类似WM_COMMAND消息,只是WM_SYSCOMMAND表示用户从系统菜单中选择一个启用的选项。wParam为菜单IDlParam0

定义菜单复杂的方法

CreateMenu把一个句柄返回给新菜单,菜单一开始为空。AppendMenu将菜单插入菜单中,必须为顶层菜单项和每个弹出菜单使用不同的菜单句柄。

还可以使用Windows定义菜单的第三种方法。LoadMenuIndirect函数,它接受一个MENUITEMTEMPLATE类型结构指针,并返回菜单句柄。

系统菜单

使用WS_SYSMENU风格创建的父窗口在其标题栏左侧由一个系统菜单框。可以修改它。在系统菜单添加命令ID必须小于0xF000,否则它们将会同Windows系统菜单命令使用ID值冲突。

通过GetSystemMenu得到系统菜单句柄,然后使用AppendMenu添加菜单。

更改菜单

Win3.0之前,只能使用ChangeMenu函数来修改菜单。现在它被分解为5个函数:
AppendMenu
DeleteMenuInsertMenuModifyMenuRemoveMenu
如果是弹出菜单DeleteMenu清除弹出菜单,RemoveMenu不清除它。

菜单相关的操作

CheckMenuItem取消或选中当前选中的项。
EnableMenuItem
灰化或激活菜单项。
TrackPopupMenu
显示弹出菜单
DrawMenuBar
强制菜单刷新
GetSubMenu
获得弹出菜单句柄
GetMenuItemCount
获得菜单当前项数
HiliteMenuItem
反显加亮菜单
GetMenuString
获得菜单中字符串
GetMenuState
获得菜单项当前属性
DestroyMenu
清除菜单

键盘加速键

加速键是产生WM_COMMAND消息的组合。许多时候,程序使用加速键来重复菜单项动作。或许通过WM_KEYDOWN或者WM_CHAR消息也能实现菜单功能,但只适用于单窗口应用程序。加速键还有一个好处,不需要复制菜单和加速键逻辑。

通过LoadAccelerators加载键盘加速键表。

加速键原理是使用Windows函数TranslateAccelerator在接收到消息后对消息进行判断,如果是键盘消息,查找句柄为hAccel的加速键表。如果找到匹配,则调用句柄为hWnd的窗口过程。如果ID与系统菜单项一致,则消息是WM_SYSCOMMAND否则消息为WM_COMMANDTranslateAccelerator的第三个参数是hWnd,它被用来替换消息中的hWnd字段,确保键盘加速消息发送给同一窗口过程。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭