在
windows
应用程序中有几种不同类型的资源,如加速键,位图,光标,对话框,菜单,工具条和字符串等。在最初的
API
编程阶段,程序员可以用文本编辑器来编写资源脚本,这种方式比较灵活,但代码量很大。
在
Winodws
的可执行文件中,资源是独立于代码的,使用单独的
Resource Compiler
来编译,并嵌入到可执行文件中。在编程过程中,代码是可重用的,资源文件也可重用的,通过资源的“导入”和“导出”功能来实现资源的可复用。此外,程序的国际化也是通过资源来实现的。
术语“资源文件”可以指若干文件类型,包括:
·
程序的资源脚本 (.rc) 文件。
·
资源模板 (.rct) 文件。
·
作为独立文件存在的个别资源,如从 .rc 文件引用的位图、图标或光标文件。
·
由开发环境生成的头文件(如 Resource.h),它从 .rc 文件中引用。
其他类型的文件(如
.exe
、
.dll
和
.res
文件)中也可以作为资源。
资源的操作一般过程为:资源的创建,在资源文件中定义,资源的加载等。
不同类型的资源定义方式不太相同,一般都是使用一种“描述”类的语言来说明该资源的各种属性。资源通过
ID
号来进行标识,
ID
是资源名,用以标识特定和资源,应用程序也是通过
ID
来加载指定的资源。一般使用一个
1~65535
之间的整数来表示。
图标资源
一个图标就是代表一个应用程序的特殊最小位图。在图标上双击鼠标就可以执行该应用程序。
1.
图标的创建
用户可以使用系统提供的默认图标也可以自定义扩展名为
ico
的文件。
系统提供的一些图标标识为:
IDI_APPLICATION
默认图标
IDI_QUESTION
问号图标
IDI_EXCLAMATION
惊叹号图标
2.
在资源文件中定义图标
其形式如下:
图标名
ICON
图标文件名(
.ico
)
3.
加载图标
在应用程序中通过
LoadIcon
函数加载图标
,
此过程常在定义窗口类时进行
,
如:
wndClass.hIcon = LoadIcon(hInst, lpszIconName);
位图资源
对于绘画或照片一类位图数据量一般都较大,因此为了提高显示刷新速度,位图操作必须在内存中进行。因此程序首先要通过
CreateCompatibleDC
向系统申请内在设备环境。
与其它资源的加载类似,位图也可以使用
LoadBitmap
函数来加载,并使用
BitBlt
函数来进行输出。
BOOL BitBlt
(
HDC hdcDest, //
目地设备环境
int nXDest, int nYDest, //
目地设备显示位图的基点
int nWidth, int nHeight, //
显示区域的高宽
HDC hdcSrc, //
源设备环境
int nXSrc, int nYSrc, //
源设备中位图的左上角坐标
DWORD dwRop //
位图的显示方式
)
菜单
1.
定义菜单
定义形式为:
ID MENU [
载入特性选项
]
{
菜单项列表
}
其中菜单项列表用于说明菜单的各个组成部分。
2.
加载菜单
一般的
Windows
程序中加载菜单有三种方法:
(1)
在窗口类中加载
(2)
在创建窗口时加载
(
CreateWindow
函数)
(3)
动态加载
获得菜单句柄后通过
SetMenu
动态地加载菜单,以提高程序灵活性。
3.
菜单项操作
(1)
禁止或激活菜单项
(2)
设置或取消选中标志
(3)
增加菜单项
(4)
删除菜单项
(5)
修改菜单项
菜单项里方法较,不一一罗列出来,需要可以参见
MSDN
。
加速键
加速键是经常与菜单一同使用的资源,通过加速键可以使程序使用起来更加方便快捷。
1.
资源定义
加速键格式为:
加速键名
ACCELERATORS ID [
类型
] [NOINVERT] [ALT] [SHIFT] [CONTROL]
后面的一些可选项表示加速键的组合方式。
2.
加载
通过
LoadAccelerators
即可加载定义好的加速键
3.
翻译加速键
想要加速键产生效果还必须响应加速键按下后产生的消息,翻译加速键的工作一般在应用程序的消息循环中进行。
TranslateAccelerator
函数是翻译过程的核心,它对照加速键表将
WM_KEYDOWN
和
WM_KEYUP
翻译成
WM_COMMAND
和
WM_SYSCOMMAND
消息。
应用示例
这次使用资源脚本(rc文件)和resource.h头文件来描述程序里的资源,头文件内容如下:
//
菜单
#define
IDM_OPEN 1000
#define
IDM_CLOSE 1001
#define
IDM_EXIT 1002
#define
IDM_ABOUT 1003
#define
IDM_PIC1 1004
#define
IDM_PIC2 1005
在这里定义了六个菜单的ID,其实直接在描述文件里使用数字也可以,不过失去了字面意义,不方便编写复杂程序。
资源脚本其实是一个可以用文本编辑器打开的文本文件,不过为了方便一般都使用VS提供的可视化工具。这里为了了解资源定义
加载的原理,使用了手工编写的方式。
#include "resource.h"
VSICON ICON res\vs.ico
PIC1 BITMAP res\pic1.bmp
PIC2 BITMAP res\pic2.bmp
MENUOPEN MENU MOVEABLE
BEGIN
POPUP "文件(&F)"
BEGIN
MENUITEM "打开(&O)", IDM_OPEN //虽可以直接定义数字ID,但由于数字没有字面意义
MENUITEM "关闭(&C)", IDM_CLOSE //故一般不使用这种方式,而使用define方式
MENUITEM SEPARATOR
MENUITEM "退出(&X)", IDM_EXIT
END
POPUP "关于(&A)"
BEGIN
MENUITEM "关于程序", IDM_ABOUT
END
END
MENUPIC MENU MOVEABLE
BEGIN
POPUP "位图"
BEGIN
MENUITEM "位图一", IDM_PIC1
MENUITEM "位图二", IDM_PIC2
END
END 这里的资源文件包括:一个程序图标(ico文件),两张位图文件(pic1.bmp和pic2.bmp)全部放于程序目录的res文件夹内。其它
部分是定义了一系列的菜单资源。
在这次的程序里。程序把一个图标资源加载为最后生成程序的图标(不用再使用原来那种恶心的默认图标了),程序加载了一个文件
菜单,里面有“打开”和“关闭”两项。打开按下后,动态产生一个新的菜单组,按下里面的菜单项选择在用户区显示两个位图。
//首先需要在InitWindowClass方法里改变这两行内容
wndClass.hIcon = LoadIcon(NULL, "VSICON");//加载一个程序图标vs.ico
wndClass.lpszMenuName = "MENUOPEN";//加载程序菜单
//然后是全局定义变量
HDC hdc, hdcMem;
HBITMAP hBmp;
BITMAP bmp;
HMENU hmenu, haddMenu;
HINSTANCE hCurInst;//当前应用程序句柄
//最后程序的消息处理函数作为结束
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg,
UINT wParam,
LONG lParam)
{
PAINTSTRUCT ps;
switch(iMsg)
{
case WM_CREATE://获取设备环境
hdc = GetDC(hWnd);
hdcMem = CreateCompatibleDC(hdc);
break;
case WM_COMMAND://处理菜单消息
switch (LOWORD(wParam))
{
case IDM_OPEN://处理打开菜单按下的消息
hmenu = GetMenu(hWnd);//获取主菜单句柄
haddMenu = CreateMenu();//创建动态菜单
//动态增加菜单中项
AppendMenu(haddMenu, MF_ENABLED, IDM_PIC1, "位图一");
AppendMenu(haddMenu, MF_ENABLED, IDM_PIC2, "位图二");
//将创建的菜单插入到主菜单中
InsertMenu(hmenu, 1, MF_POPUP|MF_BYPOSITION
, (UINT)haddMenu, "打开图片");
//相应改变“文件”菜单中相关菜单项属性
EnableMenuItem(hmenu, IDM_OPEN, MF_GRAYED);//打开菜单变灰不可用
EnableMenuItem(hmenu, IDM_CLOSE, MF_ENABLED);//关闭菜单变可用
DrawMenuBar(hWnd);//重新显示窗口菜单
break;
case IDM_CLOSE://关闭菜单消息
DeleteMenu(hmenu, 1, MF_BYPOSITION);//删除加入的菜单项
//相应改变“文件”菜单中相关菜单项属性
EnableMenuItem(hmenu, IDM_OPEN, MF_ENABLED);//打开变可用
EnableMenuItem(hmenu, IDM_CLOSE, MF_GRAYED);//关闭变不可用
DrawMenuBar(hWnd);
break;
case IDM_PIC1://在用户区加入一个位图并进行显示
SelectObject(hdc, (HPEN)GetStockObject(WHITE_PEN));
Rectangle(hdc, 0,0, 1000, 1000);
hBmp = LoadBitmap(hCurInst, "PIC1");
GetObject(hBmp, sizeof(BITMAP), (LPVOID)&bmp);//获取位图尺寸
SelectObject(hdcMem, hBmp);
BitBlt(GetDC(hWnd), 0, 0, bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY);
EnableMenuItem(hmenu, IDM_PIC1, MF_GRAYED);//位图二变不可用
EnableMenuItem(hmenu, IDM_PIC2, MF_ENABLED);
break;
case IDM_PIC2://显示图片二
SelectObject(hdc, (HPEN)GetStockObject(WHITE_PEN));
Rectangle(hdc, 0,0, 1000, 1000);
hBmp = LoadBitmap(hCurInst, "PIC2");
GetObject(hBmp, sizeof(BITMAP), (LPVOID)&bmp);//获取位图尺寸
SelectObject(hdcMem, hBmp);
BitBlt(GetDC(hWnd), 0, 0, bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY);
EnableMenuItem(hmenu, IDM_PIC2, MF_GRAYED);//位图一变不可用
EnableMenuItem(hmenu, IDM_PIC1, MF_ENABLED);
break;
case IDM_EXIT://退出被按下,发送一个WM_DESTROY消息退出程序
SendMessage(hWnd, WM_DESTROY, 0, 0);
break;
default:
break;
}
break;
case WM_DESTROY://在窗口退出后释放所有资源
DeleteObject(hBmp);
ReleaseDC(hWnd, hdc);
DeleteDC(hdcMem);
PostQuitMessage(0);
return 0;
default:
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
}
return 0;
}