第3章 启程——Windows编程基础(上)

来源:互联网 发布:淘宝琴行哪个好 编辑:程序博客网 时间:2024/06/10 08:28

3.1 高瞻远瞩——Windows 编程体系与游戏编程

Windows 平台游戏编写铁三角——C++、 Windows API与图形库(DirectX或者OpenGL)。

想要在Windows 下编写出绚丽的游戏程序,除了对某种图形库驾轻就熟之外,必要的Windows编程基础是不可少的。
而在Visual Studio 中,如果采用C++编程语言来进行开发的话,我们需要知道通常有这3 种基本的创建交互式Windows 应用程序的方式:

• 方式一,使用Windows API 来进行开发。 Windows API 是Windows 操作系统与应用程序之间的通信的基本接口。

• 方式二,使用MFC 来进行开发。MFC 也就是Microsoft Foundation Classes ,微软基础类库,也就是一组封装了Windows API 

    的C++类而已。

• 方式三,使用Windows Forms。相对于传统的Windows API 与MFC 开发方式,这是一种基于窗口的新的开发机制, Windows Forms 是微软的.NET 开发框架的图形用户界面部分,该组件通过将现有的Windows API 封装为托管代码提供了对Windows 本地(native)组件的访问方式。我们通常可以把这套纽件看做是孔MFC 的替代品。

在开发游戏程序时,最需要关注的地方就是执行效率。因为游戏程序中往往在每一个瞬间都有大量的图形需要绘制,如果绘制效率不高,图形数量变多,计算量变大的时候就会特别卡。一款成功的游戏最基本的特点就是具有流畅的用户体验,这个要求达不到的话, 其他方面就不用考虑了。

而C++引以为豪的执行效率与生俱来,配上Windows API 能直接与操作系统打交道的高效率特性,强强联合,再配上能直接与显卡打交道的图形库(DirectX 或者OpenGL ),这样,在Windows平台上编写游戏的铁三角配置就诞生了。

3.2 理解两个术语——API 与SDK

API——应用程序编程接口, SDK——软件开发包

3.2.1 何为API

微软公司为了方便我们开发基于Windows 的应用程序,为我们提供了各种各样的函数。这些函数是Windows 操作系统提供给应用程序编程的接口,即Application Programming Interface ,简称为API。

我们在编写Windows 程序中所说的API 函数, 就是指系统提供的函数,主要的Windows 函数都在Windows.h 头文件中进行声明了。

3.2.2 什么是SDK

SDK 的全称是Software Development Kit , 中文译为软件开发包。SDK 说白了就是一个开发所需资源的一个集合。
DirectX SDK 就是用DirectX 进行开发的一个资源的打包集合。这里需要注意API 和SDK 都是IT 业界广泛使用的术语,并不是专指某种特定的API 或者SDK 。

3.3 Windows 程序的“心脏”——WinMain 函数

WinMain——Windows 程序的入口点函数。

当Windows 操作系统启动一个程序时,它最先调用的就是这个程序的WinMain 函数(实际是由插入到可执行文件中的启动代码调用的)。WinMain 是Windows 程序的入口点函数,与之前我们学C++时写的那些黑洞洞的DOS 程序的入口点函数main 的作用相同。当WinMain 函数结束或返回时, Windows 应用程序也就结束了。

3.3.1 WinMain 函数

可以在MSDN 中查到它有如下的原型:
int WINAPI WinMain(  __in  HINSTANCE hInstance,  __in  HINSTANCE hPrevInstance,  __in  LPSTR lpCmdLine,  __in  int nCmdShow);

3.3.2 MessageBox 函数

MessageBox { NULL, L ”你好, Visual St udio !”, L ” 消息窗口”, 0 ) ;
它用于显示一个消息框。可以通过一些参数来设置这个消息框的样式。
在MSDN 中查到这个函数有如下原型:
int MessageBox(  __in  HWND hWnd,  __in  LPCTSTR lpText,  __in  LPCTSTR lpCaption,  __in  UINT uType);

3.3.3 PlaySound 函数

实现音效播放的核心API 函数PlaySound,可以在MSDN 中查阅到PlaySound 函数的定义如下:

BOOL PlaySound(    LPCTSTR pszSound,    HMODULE hmod,    DWORD fdwSound);
如果要使用PlaySound 函数的话,必须在编译之前连接winmm.lib 库文件;

3.3.4 示例程序Firstblood !

现在,我们就来实现一个短小精悍的播放获取一血后的FirstBlood 音效示例程序。
#include <Windows.h>#pragma comment(lib,"winmm.lib")int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){ PlaySound(L"FirstBlood.wav", NULL, SND_FILENAME | SND_ASYNC);   //播放音效MessageBox( NULL, L"First blood! 你好,游戏开发的世界,我们来征服你了!", L"First blood! 消息窗口", 0 );//显示一个消息框return 0; } 

接着我们逐行详细来讲解一下这短小精悍的8 行代码的含义:
第1 行代码解析:包含一下Windows.h 头文件,如果我们要编写基于Windows API 的程序,这个头文件一般都要include 一下。包含了Windows.h 头文件后,我们在编写程序中用到的那些API函数就像是有了“户口”,政府(编译器〉才会认为他们是合法居民。不然任我们调用什么API函数,我们的编译器都不会买账的。
第2 行代码解析:后面会用到PlaySound 函数来播放音效,这里就必须在程序中链接使用PlaySound 函数所需的winmm.lib 库文件。我们经常在编译源代码时,会出现“无法解析的外部符号”系列的错误,这一般都是lib库文件没添加或者添加不正确造成的。

在工程中包含库文件有两种方式,任选一种就可以了:

  • 第一种方式,就是用我们这里使用的#pragma comment(lib, "winrnm.lib”)语句,在双引号“”之间填我们需要链接的库文件。一般我们把#pragma comment 语句放在包含头文件的include 语句之后。
  • 第二种方式,在工程配直中添加库文件的包含。具体做法是在Visual Studio中依次单击菜单栏的【项目】→ 【属性】(或者按快捷键【Alt+F7] ),在弹出的工程属性管理页面依次单击【配置属性】→【链接器】→【输入】。然后接着在附加依赖项一
    栏单击向下的箭头,并单击弹出的【编辑】字样;这时,会弹出一个【附加依赖项】对话框,我们在这个对话框的编辑框中填上要加入的库文件(比如这里用到的winmm.Lib ),并单击【确定】按钮就可以了。

第3-4 行代码解析:也就是写一下WinMain 函数的标准原型,可以直接从MSDN 中把WinMain函数的标准写法拷贝过来贴到这里,我们平常写程序时经常可以这样做,无形中大大提高了效率。
第5 行代码解析: 调用一下PlaySound 函数来播放音效,其中第一个参数我们这样写L”FirstBlood.wav”,其中的L表示我们要把字符串“FirstBlood.wav ”转化为宽字符版。因为在Visual Studio 中默认使用的是Unicode 字符集。如果我们不写L而

直接写“FirstBlood. wav”的话,就会报出“不能将参数1 从const char [15 ] 转换为LPCWSTR ” 系列的错误。
因为我们把FirstBlood.wav 这个音频文件放在了工程文件夹中与程序源文件相同的路径下了,所以直接写L”FirstBlood.wav”, 程序就会在程序源文件所在的目录找到FirstBlood.wav 音频文件并载入进来。

关于工程中使用的字符集, 我们可以在工程属性页中更改。即在Visual Studio 中依次单击菜单栏的【项目】→【属性】(或者按快捷键【Alt+F7 】),在弹出的工程属性管理页面依次单击【配置属性】→【常规】, 在【字符集】一栏中进行更改。

第6 行代码解析: 调用一下MessageBox 函数来显示一个对话框,其中第一个参数填NULL 就行了,第二个参数填对话框中的内容,第三个参数填对话框的标题,注意也都要用L 将宇符串转化为宽字符版。
第7~8 行代码解析: 第7 行我们给上WinMai n 函数的返回值,因为WinMain 函数的返回值类型为int,这里返回0 就可以了。第8 行给上WinMain 函数的回括号,表示WinMain 函数的内容到这里就结束了。

3.4 Windows 程序的“外貌”——窗口

窗口( Window )可谓是Windows 操作系统的应用程序中非常重要的一个元素。每一个Windows 应用程序至少要有一个窗口,称之为主窗口。窗口一般为屏幕上呈现的一块矩形区域,是Windows 运用程序与用户进行交互的接口。利用窗口,运用程序可以接受用户的输入以及对输出进行显示。
窗口又可以分为客户区和非客户区。其中客户区为窗口的一部分,游戏软件通常都在客户区完成游戏中各种画面、功能与效果的实现。标题栏、菜单栏、系统菜单、最小化、最大化框统称为窗口的非客户区,他们主要由Windows 系统来管理,而应用程序则主要管理客户区的外观及其操作。

3.5 Winodows 资源的“身份证”——句柄

句柄——每个Windows 资源都有且都独特的“身份证”。
在Windows应用程序中,窗口都是通过窗口句柄(HWND )来标识的。我们要对某个窗口进行操作的话,首先就是要得到这个窗口的句柄。

句柄(HANDLE)是Windows 程序中极其重要的一个概念,我们经常需要与其打交道。在Window s 程序中,有各种各样的资源,比如窗口、图标、光标等。系统创建这些资源时会为它们分配内存,并返回标识这些资源的标识号,这些标识号就是句柄。

3.6 Windows 程序的“邮局”——消息与消息队列

消息——Windows 应用程序与操作系统间的“信使“ 。
首先我们要牢记一个概念, Windows 程序设计是一种基于事件驱动方式的程序设计模式,Windows 程序与操作系统间的通信主要是基于消息的。
我们每单击一次鼠标,每按键盘上的一个键,就会有这样的一个过程进行,操作系统感知事件,将事件包装成消息,投递到消息队列中, 然后程序从消息队列中取出消息并响应。其实在这个处理过程中,操作系统也会给游戏程序“发送消息”。所谓的发送消息, 就是操作系统调用程序代码中专门负责处理消息的函数,而这个函数,就是大名鼎鼎的“ 窗口过程函数”。

3.6.1 消息的表示形式——MSG 结构体

Windows 程序中,消息是由MSG 结构体来表示的。我们可以在MSDN 中查到MSG的结构体定义如下:
typedef struct tagMSG {     // msg     HWND hwnd;   UINT message;   WPARAM wParam;   LPARAM lParam;   DWORD time;   POINT pt;} MSG;

3.6.2 关于消息队列

每个Wndows 应用程序开始执行后,系统都会为该程序创建一个消息队列。这个消息队列用于存放该程序创建的窗口的消息。Windows 将产生的消息依次放到消息队列中,而应用程序则通过一个消息循环不断地从消息队列中取出消息并进行响应。这种消息机制,就是Windows 程序运行的机制。




原创粉丝点击