1
第 7章 资源在 Windows编程中
的应用
加速键
对话框
位图
资源
光标
菜单
工具条
字符串
2
7.1菜单和加速键资源及其应用
菜单由以下组成部分:
(1) 窗口主菜单条
(2) 下拉式菜单框
(3) 菜单项热键标识
(4) 菜单项加速键标识
(5) 菜单项分隔线
3
7.1.1菜单的创建过程
(1)定义菜单
菜单在资源描述文件中的定义形式为:
menuID MENU [,载入特性 选项 ]{菜单项列表 }
字符串,或
1~65535之
间的整数
选 项 说 明
DISCARDABLE 当不再需要菜单时可丢弃
FIXED 将菜单保存在内存中的固定位置
LOADONCALL 需要时加载菜单
MOVEABLE 菜单在内存中可移动
PRELOAD 立即加载菜单
POPUP语句
MENUITEM语句
4
POPUP语句定义弹出式菜单, 其形式为:
POPUP "菜单项名 "[,选项 ];
在菜单项名中加入符号, &”,以定义热键
定义弹出式菜单项, 编辑, 的形式如下:
POPUP,编辑( &E), ;
选 项 说 明
MENUBARBREAK 菜单项纵向分隔标志
CHECKED 显示选中标志
INACTIVE 禁止一个菜单项
GRAYED 禁止并变灰显示
5
MENUITEM用于定义菜单项, 其形式为:
MENUITEM "菜单项名 " 菜单项标识 ( ID) [,
选项 ]
ID为菜单项标识, 在 WM_COMMAND消息
中字参数 wParam中包含选中菜单项的标识 。
每个菜单项的标识必须唯一, 标识值常在
头文件中定义 。
如:创建菜单中的水平分隔符:
MENUITEM SEPARATOR
6
该菜单在资源描述文件中的定义如下:
#include <windows.h>
#include "Menu.h"
∥ 菜单定义
My_menu MENU MOVEABLE
{ POPUP "文件 ( &F) "
{ MENUITEM "新建 ( &N) ",IDM_NEW
MENUITEM "打开 ( &O) ",IDM_OPEN
MENUITEM "关闭 ( &C) ",IDM_CLOSE
MENUITEM "保存 ( &S) ",IDM_SAVE
MENUITEM "另存为 ( &A) ",IDM_SAVEAS
MENUITEM SEPARATOR
MENUITEM,退出 ( &X),, IDM_EXIT


7
menu.h 文件中定义了菜单项标识所对应的数值:
……
#define IDM_NEW 10
#define IDM_OPEN 11
#define IDM_CLOSE 12
#define IDM_SAVE 13
#define IDM_SAVEAS 14
#define IDM_EXIT 15

8
(2)加载菜单资源
在窗口类中加载菜单
在创建窗口时加载菜单
动态加载菜单
WNDCLASS wndclass;

wndclass.lpszMenuName=lpszMenuName;
HWND hwnd; HMENU hmenu;

hmenu=LoadMenu(hlnstance,"My_menu");
hwnd=CreateWindow( …, hmenu,… );
hmenu2=LoadMenu(hlnstance,"Menu2");
SetMenu(hwnd,hmenu2);

9
7.1.2操作菜单项
1.禁止或激活菜单项
BOOL EnableMenuItem
(HMENU hmenu,
UlNT wIDEnableItem,//被禁止或激活的菜单项标识
UINT dwEnable
)
据 dwEnable的取值,可为
菜单项的 ID值,也为该菜
单项在菜单中位置
标 识 说 明
MF_BYCOMMAND以 ID值标识菜单项
MF_ENABLED 激活菜单项
MF_BYPOSITION 表明以位置标识菜单项
MF_GRAYED 禁止菜单项并使其变灰显示
MF_DISABLED 禁止菜单项
10
2.设置或取消选中标志
DWORD CheckMenuItem
(
HMENU hmenu,
UINT wIDCheckItem,//菜单项标识
UINT dwCheck //操作标识
)
标 识 说 明
MF_CHECKED 添加选中标志
MF_UNCHECKED 删除选中标志
11
3.增加菜单项
(1)在菜单的尾部增加菜单项
BOOL AppendMenu
( HMENU hmenu,
UINT dwFlags,// 新加入的菜单项类型标识
UINT dwIDNewItem,// 新加入菜单项的 ID
LPCTSTR lpNewItem // 新加入的菜单项内容
)
例如在, 文件, 菜单的末尾增加一项, 关于,,
AppendMenu (hmenu,MF_ENABLED,IDM_ABOUT,“关于 (&A)“);
12
(2)在菜单中插入菜单项
调用函数 InsertMenu 在菜单中插入新的菜单
BOOL InsertMenu
(HMENU hmenu,//菜单句柄
UINT wPosition,//指定新菜单项插入的位置
UINT dwFlag,//新加入的菜单项的信息
UINT dwIDNweItem,//新加入的菜单项的标识
LPCTSTR lpNewItem //新插入的菜单项的内容
)
例如, 在, 文件, 菜单的, 退出, 项之前加入, 打
印, 菜单项;
InsertMenu (hmenu,IDM_EXIT,
MF_BYCOMMAND|MF_ENABLED,
IDM_PRINT,"打印 ( &P) ");
13
4.删除菜单项
调用函数 DeleteMenu 删除菜单项:
BOOL DeleteMenu
(
HMENU hmenu,
UINT wPosition,//要删除的菜单项的位置
UINT dwFlag //对 wPosition的解释
)
例如, 删除, 文件, 菜单中的, 另存为, 菜单项:
DeleteMenu (hmenu,IDM_SAVEAS,MF_BYCOMMAND)
14
5.修改菜单项
调用函数 ModifyMenu 修改菜单中的某个项;
BOOL ModifyMenu
(HMENU hmenu,
UINT wPosition,//指定需修改的菜单项位置
UINT dwFlag,
UINT dwIDNweItem,//修改后菜单项的标识
LPCTSTR lpNewItem //修改后的菜单项名
)
例如:修改, 文件, 菜单中, 打开, 项为, 加载,
项:
ModifyMenu(hmenu,IDM_OPEN,MF_BYCOMMAND,
IDM_LOAD,"加载 (&L) ");
15
7.1.3 动态地创建菜单
动态地创建菜单可以使系统资源更加节省,
在应用程序中动态创建菜单分两个步骤:
1,调用函数 CreateMenu创建空的弹出式菜单
HMENU CreateMenu(void)
2,调用函数 AppendMenu或 InsertMenu在该
菜单中加入菜单项 。
16
7.1.4加速键资源
加速键资源是常伴随菜单使用的一种非常有用
的资源
(1)在资源描述文件中定义加速键资源
加速键名 ACCELERATORS
加速键标识( ID),
[类型 ]
[NOINVERT] //使用加速键时,菜单项不高亮显示
[ALT][SHIFT][CONTROL] //组合键的组合方式
17
常用的加速键有两种形式:
①,^char”,id
例如:, 文件, 菜单中, 保存, 项的加速键可定义
为:
,^S”,IDM_SAVE
② nCode,id VIRTKEY
使用虚拟键作为加速键 。
例如将 F1键定义为, 帮助, 菜单项的加速键, 其
ID标识为 IDM_HELP,其形式如下:
VK_F1,IDM_HELP,VIRTKEY
18
2.加载加速键资源
调用函数 LoadAccelerators加载加速键资源:

HACCEL hAccel;

hAccel=LoadAccelerators
(
hInstance,// 当前程序实例句柄
lpAcceIName // lpAccelName为加速键表名
);
19
3.翻译加速键
翻译操作经常在应用程序的消息循环中进行,
while(GetMessage(&Msg,NULL,0,0))
{ if(!TranslateAccelerator(hwnd,hAccel,&Mag))
{ TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
函数 TranslateAccelerator是翻译操作的
核心 。 其 作用是对照加速键表, 将相关的
按键消息 WM_KEYDOWN和 WM_KEYUP 翻译成
WM_COMMAND 或 WM_SYSCOMMAND消息 。 其特
点是将翻译后的消息直接发往窗口, 不在
消息队列中等待 。
20
7.1.5 创建菜单资源实例
【 例 7-1】 创建一个窗口菜单的构架,单击,创
建统计计算菜单项” 动态地创建,统计计算”
菜单,之后,“创建统计计算菜单项”变成
不可操作,而原先不可操作的,删除统计计
算菜单 项”变成可操作,执行,删
除统计计算菜单项” 菜单
命令删除,统计计算” 菜
单。
21
#include "windows.h"
#include "7_1.h"
HMENU hmenu,haddmenu; //定义菜单句柄
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(……)
{……
ShowWindow( hwnd,nCmdShow) ;
UpdateWindow(hwnd);
hAccel=LoadAccelerators(hInstance,lpszMenuName);
while( GetMessage(&Msg,NULL,0,0))
{ //在消息循环中截获加速键消息
if (!TranslateAccelerator(hwnd,hAccel,&Msg))
{ TranslateMessage( &Msg) ;
DispatchMessage( &Msg) ;
}
}
return Msg.wParam;}
22
LRESULT CALLBACK WndProc(……)
{switch(message)
{case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_ADDMENU,//在主菜单中添加弹出式菜单
hmenu=GetMenu(hwnd); //获取主菜单句柄
haddmenu=CreateMenu(); //动态创建菜单
//在创建的菜单中增加菜单项
AppendMenu(haddmenu,MF_ENABLED,IDM_qiuhe,"求和 ");
AppendMenu(haddmenu,MF_ENABLED,IDM_fangcha,“方差” );
AppendMenu(haddmenu,MF_ENABLED,IDM_pinjunzhi,"平均值 ");
AppendMenu(haddmenu,MF_ENABLED,IDM_junfanggen,"均方根 ");
//将创建的弹出式菜单插入主菜单中
InsertMenu(hmenu,2,MF_POPUP|MF_BYPOSITION,
(UINT)haddmenu,"统计计算 (&C)");
//相应改变菜单中有关绘图统计计算菜单项的属性
EnableMenuItem(hmenu,IDM_ADDMENU,MF_GRAYED);
EnableMenuItem(hmenu,IDM_DELMENU,MF_ENABLED);
DrawMenuBar(hwnd); //重新显示窗口菜单
break;
23
case IDM_DELMENU:
DeleteMenu(hmenu,2,MF_BYPOSITION); //删除统计计算菜单项
//相应改变“文件”菜单中有关统计计算菜单项的属性
EnableMenuItem(hmenu,IDM_ADDMENU,MF_ENABLED);
EnableMenuItem(hmenu,IDM_DELMENU,MF_GRAYED);
DrawMenuBar(hwnd); //重新显示窗口菜单
break;
case IDM_EXIT:
SendMessage(hwnd,WM_DESTROY,0,0);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default,return DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}
24
本例程的头文件如下:
#define IDM_ADDMENU 15
#define IDM_DELMENU 16
#define IDM_EXIT 17
#define IDM_HELP 22
#define IDM_qiuhe 23
#define IDM_fangcha 24
#define IDM_pinjunzhi 25
#define IDM_junfanggen 26
25
本例程用到的资源文件源代码如下:
#include "c:\prog_book\7_1\7_1.h"
#include "windows.h"
MENU MENU DISCARDABLE
BEGIN
POPUP "文件 (&F)"
BEGIN
MENUITEM "创建统计计算菜单项 (&P)\t Ctrl+P",IDM_ADDMENU
MENUITEM "删除统计计算菜单项 (&D)\t Ctrl+D",IDM_DELMENU,GRAYED
MENUITEM SEPARATOR
MENUITEM "退出 (&X)",IDM_EXIT
END
MENUITEM "帮助 (&H)",IDM_HELP
END
MENU ACCELERATORS MOVEABLE PURE
BEGIN
"^P",IDM_ADDMENU,ASCII
"^D",IDM_DELMENU,ASCII
END
26
7.2 位图资源及其应用
27
7.2.1 位图概念
位图是一种数字化的图形表示形
式, 位图中的每个像素点由位图文件
中的一位或多位数据表示 。 整个位图
的信息被细化为每个像素点的属性值 。
位图数据量一般较大, 为了提高
显示刷新速度, 位图操作须在内存中
进行 。
28
7.2.2 位图的操作过程
位图操作过程:
? 定义位图句柄,HBITMAP hBm;
? 加载 或 创建
hBm=LoadBitmap(hInstance,lpszName)
hBm=CreateCompatibleBitmap(hdc,nWidth,nHeight)
? 选入内存设备环境
SelectObject(hdcmem,hBm);
? 输出
BOOL BitBlt
( HDC hdcDest,//目的设备环境句柄
int XDest,int YDest,int nWidth,int nHeitght,//位图基点及高宽
HDC hdcSrc,int nXSrc,int nYsrc,//源设备环境句柄及位图基点
DWORD dwRop //标识位图显示方式
)
29
在输出位图之前, 经常需调用函数 GetObject
获取位图的尺寸:
GetObject
(hBitmap,//为位图句柄
sizeof(BITMAP),//BITMAP结构的大小
(LPVOID)&bm //BITMAP结构的地址
)
应用程序调用函数 GetObject后, 将指定位图的
信息写入 BITMAP结构中 ( 结构见教材 )
30
7.2.3 位图操作实例
【 例 7-2】 本例调用一幅坦克的图片,并在用户窗口区上显示
LRESULT CALLBACK WndProc(……)
{ PAINTSTRUCT ps;
switch(message)
{case WM_CREATE:
hdc=GetDC(hwnd); //获取设备环境句柄
hdcmem=CreateCompatibleDC(hdc);//内存设备环境句柄
ReleaseDC(hwnd,hdc); //释放设备环境句柄
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
SelectObject(hdcmem,hBm); //将位图选入内存设备环境
31
//将内存设备环境中的位图拷贝到设备环境中
BitBlt(hdc,180,80,bm.bmWidth,bm.bmHeight,hdcmem,0,0,SRCCOPY);
EndPaint(hwnd,&ps); //释放设备环境句柄
break;
case WM_DESTROY:
DeleteObject(hBm); //释放位图
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}
本例的资源文件如下:
pic7 BITMAP pic7_2.bmp //定义位图资源
32
7.3 对话框资源及其应用
对话框是一个弹出式窗口,它一般用于
用户输入或与用户进行交互活动的场合



模式
非模式
允许 用户在该对话框与应用程
序其他窗口之间的切换,非模
式对话框从 WinMain函数的消
息循环中接收输入
不允许 用户在关闭对话框
之前切换到应用程序的其
他窗口
33
7.3.1 模式对话框的编程方法
1.定义对话框资源
一般的形式为:
对话框名 DIALOG [载入特性选项 ]
X,Y,
Width,Height
[设置选项 ]
{
对话框的控件定义
}
样式选项决定了对话框的外
型特点,样式见表 7-6
CHECKBOX,ICON,COMBOBOX
LISTBOX,DEFPUSHBUTTON、
PUSHBUTTON,RADIOBUTTON、
GROUPBOX,EDIT,SCROLLBAR
静态文本控件
34
2.调用函数 DialogBox显示对话框
调用 DialogBox函数在窗口中显示对话框:
int DialogBox
( HINSTANCE hInstance,
LPCTSTR lpszDialogName,//对话框资源的名称
HWND hwndParent,//拥有该对话框的窗口句柄
DLGPROC lpDialogFunc //对话框处理函数的地址
)
35
3.构造对话框消息处理函数
对话框消息处理函数的一般形式为:
BOOL CALLBACK DlgProc(HWND hDlg,…,…,…)
{switch( message)
{case WM_INITDIALOG:
return 1;
case WM_COMMAND
switch (LOWORD (wParam ))
{ case …

break;

}
break;
}
return 0;
}
36
在对话框消息处理函数中主要常处理以下两
类消息:
( a) WM_ INITDIALOG 消息
对话框在响应消息 WM_ INITDIALOG 消息
时完成其初始化操作, 在功能上与主窗口
函数的 WM_COMMAND消息相似 。
( b) WM_COMMAND消息
对话框在响应消息 WM_COMMAND时,
通过查看消息字参数( wParam)中的低位
字节,与控件标识( ID)相比较,以确定
产生交互请求的控件并据此转入相应的处
理过程进行处理。
37
4.关闭对话框
调用函数 EndDialog可以关闭对话框:
BOOL EndDialog(HWND hdlg,INT_PTR nResult)
Windows消息框是模态对话框的一种特殊形式,应
用程序可通过调用函数 MessageBox生成一些简单但
又常用的消息框:
int MessageBox
( HWND hwnd,//拥有消息框的窗口
LPCTSTR lpszText,//消息框中显示的字符串
LPCTSTR lpszCaption,//作为标题的字符串
DWORD dwType //指定消息框的内容
)
38
dwType常用标识及其说明
MB_CANCELTRYCONTINUE
含有 Cancel,Try Again和 Continue按钮的消息框
MB_ICONEXCLAMATION,MB_ICONWARNING
含有惊叹号图标的消息框
MB_ICONQUESTION 含有问号图标的消息框
MB_ICONSTOP,MB_ICONERROR,MB_ICONHAND
含有停止图标的消息框
MB_OK 含有一个 OK按钮的消息框
MB_OKCANCEL 含有 OK和 CANCEL按钮的消息框
MB_RETRYCANCEL 含有 RETRY和 CANCEL按钮的消息框
MB_YESNO 含有 YES和 NO按钮的消息框
MB_YESNOCANCEL 含 YES,NO和 CANCEL按钮的消息框
39
7.3.2 模态对话框应用实例
40
LRESULT CALLBACK WndProc(…,…,…,…)
{switch(message)
{case WM_COMMAND:
switch(LOWORD(wParam))
{case IDM_OPEN:
MessageBox(hwnd,"文件已经打开 ! ","文件打开 ",MB_OK);
break;
case IDM_SAVE:
MessageBox(hwnd,"文件保存成功 ! ","文件保存 ",MB_OK);
break;
case IDM_EXIT:
SendMessage(hwnd,WM_DESTROY,0,0); break;
case IDM_ABOUT,//创建对话框
DialogBox(hInst,"About",hwnd,(DLGPROC)DlgProc); break;
}
break;
case WM_DESTROY,PostQuitMessage(0); break;
default,return DefWindowProc(hwnd,message,wParam,lParam);
}
return 0; }
41
BOOL CALLBACK DlgProc(HWND hdlg,…,…,…)
{switch(message)
{ case WM_INITDIALOG,//初始化对话框
return 1;
case WM_COMMAND,//处理对话框消息
switch (LOWORD(wParam))
{ case IDOK,//关闭对话框
EndDialog( hdlg,0) ; return 1;
}
break ;
case WM_CLOSE:
EndDialog( hdlg,0) ; return 1;
}
return 0;
}
42
本例的资源程序代码如下:
#include <windows.h>
#include "7_3.h"
Menu MENU DISCARDABLE
{
POPUP "文件 (&F)"
{ MENUITEM "打开 (&O)\t Ctrl+O",IDM_OPEN
MENUITEM SEPARATOR
MENUITEM "保存 (&S)\t Ctrl+S",IDM_SAVE
MENUITEM SEPARATOR
MENUITEM "退出 (&X)",IDM_EXIT
}
POPUP "帮助 (&H)"
{
MENUITEM "关于 (&A)...",IDM_ABOUT
}
}
43
Menu ACCELERATORS
{
"^O",IDM_OPEN
"^S",IDM_SAVE
}
About DIALOG 10,10,100,50
STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "关于 "
FONT 18,"楷体 " //对话框中的文本字体类型及大小
{
CTEXT "Windows模态对话框 ",-1,13,10,80,10
DEFPUSHBUTTON "确定 ",IDOK,35,30,30,12
}
44
7.3.3 非模态对话框的编程方法
非模态对话框在对话框的定义, 对话框的创建及消息
处理上与模态对话框略有差别, 方法如下,
1,定义对话框样式
非模态对话框的定义一般形式如下:
STYLE WS_POPUP | WS_CAPTION | WS_VISIBLE
样式中应包含 WS_VISIBLE,否则无法在屏幕上显示
2,创建对话框函数
非模态对话框的创建由函数 CreateDialog完成,
HWND CreateDialog
( HINSTANCE hInstance,//当前应用程序实例句柄
LPCTSTR lpszDialogName,//对话框名
HWND hwndParent,//拥有该对话框的窗口句柄
DLGPROC lpDialogFunc ) //对话框处理函数地址
45
3,消息循环部分的处理
由于非模态对话框并不禁止应用程序向其他窗口发
送消息, 因此, 在 WinMain函数的消息循环中必须
包含截获发往非模态对话框的消息, 并将其发往相
应的对话框处理函数进行处理 。 其消息循环过程的
一般形式为:
while (GetMessage(&Msg,NULL,0,0))
{ if (! IsDialogMessage(hdlg,&Msg))
{
TranslateMessage (&Msg);
DispatchMessage (&Msg);
}
}
46
7.3.4 非模态对话框应用实例
【 例 7-4】 在“关于”窗口不关闭的前提下,
仍可以对“文件”下拉菜单进行操作,如选
“文件”菜单中的“创建”选项,即可弹出
“创建”窗口
47
LRESULT CALLBACK WndProc(…,…,…,…)
{ switch(message)
{ case WM_COMMAND:
switch(LOWORD(wParam))
{ case IDM_NEW:
MessageBox(hwnd,"文件创建成功 ! ","文件创建 ",MB_OK);
break;
case IDM_OPEN:
MessageBox(hwnd,"文件打开成功 ! ","文件打开 ",MB_OK);
break;
case IDM_SAVE:
MessageBox(hwnd,"文件保存成功 ! ","文件保存 ",MB_OK);
break;
case IDM_EXIT:
SendMessage(hwnd,WM_DESTROY,0,0); break;
case IDM_ABOUT:
hdlg=CreateDialog(hInst,"About",hwnd,(DLGPROC)DlgProc);
break;
}
……
48
BOOL CALLBACK DlgProc(HWND hdlg,…,…,…)
{ switch(message)
{ case WM_INITDIALOG,//初始化消息框
return 1;
case WM_COMMAND,//处理消息框消息
switch (LOWORD(wParam))
{ case IDOK:
DestroyWindow( hdlg) ; //关闭消息框
return 1 ;
}
break;
case WM_CLOSE:
DestroyWindow( hdlg) ; return 1;
}
return 0;
}
本例题的资源文件与
上例类似,请见教材
49
7.4 图标资源的应用
图标是代表应用程序的特殊
的最小位图。在图标上双击鼠标
就可以执行该应用程序,图标资
源可以由 VC自带的图标资源编辑
器来创建
50
7.4.1 图标资源的操作
图标资源的操作包括创建、定义和加载等过程
1.图标资源的创建
用户可通过图形编辑器自定义图标形式, 并保存在
扩展名为,ico的文件中 。 Windows系统也提供了
标准图标 。
标识 形状
IDI_APPLICATION 缺省图标
IDI_ASTERISK 信息图标
IDI_EXCLAMATION 惊叹号图标
IDI_HAND 停止图标
IDI_QUESTION 问号图标
51
2,在资源文件中定义图标资源
若采用自定义图标, 要在资源文件中定义该图标:
图标名 ICON 图标文件名 (.ico)
3,在应用程序中加载图标
调用函数 LoadIcon进行图标资源的加载的, 此过程
经常是在定义窗口类时进行, 其形式为:
WNDCLASS wndclass;
…………
wndclass.hIcon=LoadIcon(hThisInst,lpszIconName);
…………
图标名
52
7.4.2图标资源应用举例
【 例 7-5】 程序所使用的图标文件名为 tree.ico,
在为本例程序指定了这个图标后,在资源管
理器中就可以看到在可执行文件的文件名
53
本例程序中使用的图标资源文件如下:
TREE ICON d:\prog_book\7_5\tree.ico
在初始化窗口类时加载图标资源
BOOL InitWindowsClass(HINSTANCE hInstance)
{ WNDCLASS WndClass;
……
WndClass.hIcon=LoadIcon(NULL,"TREE");
//加载图标资源
……
return RegisterClass(&WndClass);
}