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

 

 

 

posted @ 2013-05-08 22:49  阳光守望者  阅读(405)  评论(0编辑  收藏  举报