Windows游戏开发学习笔记之三
本章主要学习下Windows开发中如何使用资源。
我们希望Windows开发中除程序代码外还能存储更多的资源,即在.EXE文件中除了代码之外,还包含其他称之为资源的东西。在Windows中预定义了几种资源类型。如图标(.ico)、光标资源(.cur)、字符串、声音(.wav)、位图(.bmp)、对话框、图元文件等。
在vs2010中,我们可以在资源文件中添加扩展名为.rc的ASCII文本资源文件作为输入,如下图1。之后VS2010的资源编译器装载所有的资源,并将所有的资源放置在一个具有.res扩展名的大数据文件中,Windows编译及链接时的资源数据流程如图2所示。
图1
图2
总结下Windows如何处理资源:可以向应用程序中添加许多数据类型和对象,然后它们以资源的形式和实际程序代码一起驻留在.EXE文件中(一般在文件的尾端)。在程序运行过程中,可以访问这个资源数据库,并且可以从程序本身(而不是作为一个单独的文件从磁盘中)装载资源文件。
下面的demo将展示如何使用图标资源、光标资源、.wav声音资源、菜单。
使用的文件如下:
Demo3_4.cpp:C++主文件
Demo3_4RES.h:定义符号的头文件
Demo3_4.rc:资源脚本
t3dx.ico:图标的位图数据
crosshair.cur:光标的位图数据
create.wav、techno.wav:声音资源
以上的资源均放在工程的工作目录下。
Demo3_4RES.h代码如下:
1 //定义声音资源ID 2 #define SOUND_ID_CREATE 1 3 #define SOUND_ID_MUSIC 2 4 5 //定义图标资源ID 6 #define ICON_T3DX 100 7 8 //定义光标资源ID 9 #define CURSOR_CROSSHAIR 200 10 11 //定义菜单资源ID 12 #define MENU_FILE_ID_OPEN 1000 13 #define MENU_FILE_ID_CLOSE 1001 14 #define MENU_FILE_ID_SAVE 1002 15 #define MENU_FILE_ID_EXIT 1003 16 17 #define MENU_HELP_ABOUT 2000
Demo3_4.rc资源脚本代码如下:
1 #include "Demo3_4RES.h" 2 3 //声音资源 4 SOUND_ID_CREATE WAVE create.wav 5 SOUND_ID_MUSIC WAVE techno.wav 6 7 //图标资源 8 ICON_T3DX ICON t3dx.ico 9 10 //光标资源 11 CURSOR_CROSSHAIR CURSOR crosshair.cur 12 13 //菜单资源 14 MainMenu MENU DISCARDABLE 15 { 16 POPUP "File" 17 { 18 MENUITEM "Open", MENU_FILE_ID_OPEN 19 MENUITEM "Close", MENU_FILE_ID_CLOSE 20 MENUITEM "Save", MENU_FILE_ID_SAVE 21 MENUITEM "Exit", MENU_FILE_ID_EXIT 22 } 23 POPUP "Help" 24 { 25 MENUITEM "About", MENU_HELP_ABOUT 26 } 27 }
Demo3_4.cpp C++主文件代码:
注意:
1、
winclass.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(ICON_T3DX)); //装载应用程序图标资源,注意这里是hinstance,不是NULL!!!
winclass.hCursor = LoadCursor(hinstance, MAKEINTRESOURCE(CURSOR_CROSSHAIR)); //装载光标资源,注意这里是hinstance,不是NULL!!!
2、装载菜单:通过传递菜单句柄将一个菜单指定给一个窗口。要使用菜单句柄,必须使用LoadMenu()装载菜单资源
LoadMenu(hinstance,"MainMenu")
3、选择菜单时,是将一个WM_COMMAND消息发送到与该菜单关联的窗口的WinProc()函数中。
WM_COMMAND和WM_NOTIFY消息:
即控件通知消息,是指这样一种消息,一个窗口内的控件发生了一些事情,需要通知父窗口。当用户与控件窗口交互时,控件通知消息就会从控件窗口发送到它的主窗口,这种消息一般不是为了处理用户命令,而是为了让主窗口能够改变控件。
WM_COMMAND和WM_NOTIFY都是控件通知消息。
在最初的Windows 3.x中,还没有WM_NOTIFY,只存在WM_COMMAND消息,wParam参数中包含一个通知码和控件ID。
在程序中,利用LOWORD()宏从wParam中提取低位的WORD,即菜单资源的ID。
1 /******************************************* 2 * 文件名称:Windows游戏编程大师:demo3_3 3 * 完成作者:JackyLiu 4 * 完成时间:2013.5.8 5 *******************************************/ 6 7 //头文件 8 #include <Windows.h> 9 #include <WindowsX.h> 10 #include <stdio.h> 11 #include <math.h> 12 #include "Demo3_4RES.h" 13 14 //链接相应的库 15 #pragma comment(lib, "WINMM.LIB") //Windows多媒体库扩展 16 #pragma comment(lib, "user32.lib") 17 #pragma comment(lib, "gdi32.lib") 18 19 //宏定义 20 #define WINDOWS_CLASS_NAME "WINCLASS1" 21 22 //保存应用程序实例句柄的全局变量 23 HINSTANCE g_hInstance; 24 25 /** 26 * 函数功能:回调函数,即事件处理程序,当事件发生时,Windows从主事件循环中调用的回调函数 27 * @param HWND hwnd: 窗口句柄,只有当使用同一个窗口类建立多个窗口时才会用到 28 * UINT msg: WinProc处理的消息标识符 29 * WPARAM wparam: 进一步匹配或分类发送到msg参数中的消息 30 * LPARAM lparam: 同上 31 */ 32 LRESULT CALLBACK WindowProc(HWND hwnd, 33 UINT msg, WPARAM wparam, LPARAM lparam) 34 { 35 PAINTSTRUCT ps; //用于窗口重绘的结构体 36 HDC hdc; //图形设备环境句柄 37 38 switch(msg) 39 { 40 case WM_CREATE: 41 { 42 //在这里放置初始化代码 43 //创建窗口时播放音乐 44 PlaySound(MAKEINTRESOURCE(SOUND_ID_CREATE), 45 g_hInstance, SND_RESOURCE | SND_SYNC); 46 47 //声音事件异步播放,即开始播放后PlaySound()立即放回,并循环播放声音 48 PlaySound(MAKEINTRESOURCE(SOUND_ID_MUSIC), 49 g_hInstance, SND_RESOURCE | SND_ASYNC | SND_LOOP); 50 51 return 0; 52 }break; 53 case WM_COMMAND: 54 { 55 switch(LOWORD(wparam)) 56 { 57 case MENU_FILE_ID_OPEN: 58 { 59 60 }break; 61 case MENU_FILE_ID_CLOSE: 62 { 63 64 }break; 65 case MENU_FILE_ID_SAVE: 66 { 67 68 }break; 69 case MENU_FILE_ID_EXIT: 70 { 71 72 }break; 73 case MENU_HELP_ABOUT: 74 { 75 76 }break; 77 } 78 }break; 79 case WM_PAINT: 80 { 81 hdc = BeginPaint(hwnd, &ps); //激活窗口的客户区 82 //在这里可以进行窗口重绘 83 EndPaint(hwnd, &ps); 84 return 0; 85 }break; 86 case WM_DESTROY: 87 { 88 PostQuitMessage(0); //发送终止应用程序的消息WM_QUIT 89 return 0; 90 }break; 91 default: 92 break; 93 } 94 //缺省函数处理不关心的消息 95 return (DefWindowProc(hwnd, msg, wparam, lparam)); 96 } 97 98 /** 99 * 函数功能:WinMain函数,Windows程序的入口函数 100 */ 101 int WINAPI WinMain( HINSTANCE hinstance, 102 HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) 103 { 104 WNDCLASSEX winclass; //定义Windows窗口类 105 HWND hwnd; //定义一般窗口句柄 106 MSG msg; //定义一般消息结构体 107 108 ///////////////设计窗口类/////////////// 109 winclass.cbSize = sizeof(WNDCLASSEX); //WNDCLASSEX结构体本身的大小 110 winclass.style = CS_DBLCLKS | CS_OWNDC //描述窗口一般属性的样式信息标志 111 | CS_HREDRAW | CS_VREDRAW; 112 winclass.lpfnWndProc = WindowProc; //指向事件处理程序的函数指针,即回调函数 113 winclass.cbClsExtra = 0; 114 winclass.cbWndExtra = 0; 115 winclass.hInstance = hinstance; //启动时传给WinMain()函数的hInstance 116 117 winclass.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(ICON_T3DX)); //装载应用程序图标资源,注意这里是hinstance,不是NULL!!! 118 winclass.hCursor = LoadCursor(hinstance, MAKEINTRESOURCE(CURSOR_CROSSHAIR)); //装载光标资源,注意这里是hinstance,不是NULL!!! 119 120 winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //获取Windows系统画刷句柄,用于绘制或刷新一个窗口 121 winclass.lpszMenuName = NULL; 122 winclass.lpszClassName = (WINDOWS_CLASS_NAME); 123 winclass.hIconSm = LoadIcon(hinstance, MAKEINTRESOURCE(ICON_T3DX)); //装载一个自定义最小应用程序图标 124 125 g_hInstance = hinstance; //保存应用程序实例句柄到全局变量 126 127 ///////////注册窗口类////////////// 128 if(!RegisterClassEx(&winclass)) 129 return 0; 130 131 ///////////创建窗口/////////////// 132 if(!(hwnd = CreateWindowEx(NULL, //扩展样式 133 WINDOWS_CLASS_NAME, //所创建窗口的基础类名 134 ("Demo of Custom Cursor and Icon"),//窗口标题的空值终止字符串 135 WS_OVERLAPPEDWINDOW | WS_VISIBLE, //窗口外观和行为的通用窗口标志 136 0,0, //窗口左上角位置的像素坐标 137 400,400, //窗口的宽度和高度 138 NULL, //指向父窗口的句柄 139 LoadMenu(hinstance,"MainMenu"), //指向附属于该窗口菜单的句柄 140 hinstance, //应用程序的实例 141 NULL))) //其他高级特性 142 return 0; 143 144 ///////////主事件循环///////////// 145 while(true) 146 { 147 //从应用程序线程消息队列中取走下一个消息 148 //与GetMessage()不同,它执行后会立即返回,消息队列有消息时,返回True,没有消息时,返回false 149 if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 150 { 151 //检测消息队列中是否有WM_QUIT消息 152 if(msg.message == WM_QUIT) 153 break; 154 155 //虚拟加速键翻译 156 TranslateMessage(&msg); 157 158 //将消息回传给系统,由操作系统调用窗口过程函数对消息进行处理(将消息结构体MSG中的前四个参数作为一个参数传递给函数) 159 DispatchMessage(&msg); 160 } 161 } 162 163 return msg.wParam; 164 }
运行结果图:注:光标的图标没有显示出来,创建时将会播放一段音乐。
资源下载:http://download.csdn.net/detail/liu_jun66/5346587