《Windows游戏编程大师技巧》学习笔记(二)
多任务和多线程
Windows允许不同的应用程序以轮询的方式“同时”执行,每一个应用程序都占用一段很短的时间片来运行,而后轮到下一个应用程序运行,如下图所示,CPU由几个不同的应用程序以循环的方式共享,而负责判断出下一个运行的程序、给每个程序分配运行时间的是调度程序的工作:
- 简单的调度策略:给每个应用程序分配固定的运行时间;
- 复杂的调度策略:将应用程序设定为不同的优先级和抢先性或低优先级的事件;
在大部分情况下,我们是不需要对Windows调度程序过度关注。
深入接触Windows,会发现其不仅是多任务的,还是多线程的,程序可以有许多较为简单的执行线程构成;这些线程被视为具有较重的权值的进程,从而如程序一样被调度;程序可以有一个主线程和几个工作线程构成,如下图:
事件模型
Windows是一个事件驱动的操作系统,和DOS程序不同的是,Windows程序都是等待用户去触发事件,然后系统对该事件发生响应,进行动作;如下图所示,每个程序都向Windows发送待处理的事件和消息,Windows对其中的一些进行处理,大部分消息和事件都被传递给应用程序来处理:
微软编程风格:匈牙利命名法
1. 前缀
前缀在大多数情况下用于变量名,并且因数据类型不同而不同,见下图:
2. 变量
变量由 “(一个或多个)前缀 + (一个或多个)子名” 构成,每一个子名都要以大写字母开头,如:char* szFileName;
,int lpiData;
;
一般来说,对于函数内的局部变量没有特殊的命名要求,但是对于全局变量,则必须以g_
或g
开头,如:int g_iXPos;
;
3. 函数
函数命名使用大驼峰命名法,与变量命名规则相似,但是没有前缀,但是需要注意的是,函数名中不能使用下划线,如:int PlotPixel(int ix, int iy, int ic);
;
4. 类型和常量
所有类型和常量都是大写字母,但是名字中可以使用下划线,如:const LONG NUM_SECTORS = 100;
,#define MAX_CELLS 64
,typedef unsigned char UCHAR;
;
5. 类
所有的类必须以大写C
为前缀,后续子名遵循大驼峰命名法,如:class CVector { ... };
;开发者可以在此基础上独立地补充更多规则;
6. 参数
参数命名与标准的变量命名相同,但是也可以容忍不使用前缀,如:UCHAR GetPixel(int ix, int iy);
或UCHAR GetPixel(int x, int y);
;
最简单的Windows程序
1 |
|
如果使用VS进行编译,那么则需要确保使用的子系统为窗口,也就是在自动生成的编译指令中存在
/SUBSYSTEM:WINDOWS
,控制台程序会以main
作为程序入口,如果找不到程序入口则会在链接阶段报错;
另外,如果是在Unicode环境下,tchar.h
头文件和_T()
宏是必要的,而在非Unicode环境下则可以省去。
程序运行截图:
程序分析:
- 定义
WIN32_LEAN_AND_MEAN
确保不会将Windows.h
中的MFC部分引入程序; WINAPI
一般会被定义成__stdcall
,强制参数从左向右传递;WinMain
函数的参数分析:HINSTANCE hinstance
:本程序实例句柄,与地址类似,用于追踪应用程序自身;HINSTANCE hprevinstance
:已废弃,Windows旧版本中用于追踪应用程序之前的实例,即产生当前实例的应用程序实例;LPSTR lpcmdline
:与标准C/C++入口程序main(int argc, char** argv)
;中的命令行参数类似,只不过它没有一个单独的参数像argc
那样指出参数个数,例如:使用如下参数运行TEST.EXE one two three
,lpcmdline
将变成如下值"one two three"
;int ncmdshow
:这个整数在启动过程中被传递给应用程序,带有如何打开主应用程序窗口的信息,常见的参数值如下图;在大部分情况下,只会用到SW_SHOW
、SW_SHOWNORMAL
和SW_HIDE
;
- 在Unicode环境下,
MessageBoxW
被定义为MessageBox
,函数原型如下:其中,当1
2
3
4
5int WINAPI MessageBoxW(
HWND hWnd, // 父窗口句柄
LPCWSTR lpText, // 内容
LPCWSTR lpCaption, // 标题
UINT uType); // 样式hwnd
为空时,Windows桌面被用作父窗口,此时的信息框为非模态弹窗;utype
可以通过或运算设置多重样式,常见的值如下:
我们可以通过MessageBox
函数的返回值来确定用户选中的选项,所有可能的返回值如下:
与MessageBox
函数相似,MessageBeep
函数可以发出简单的提示音,函数原型如下:
1 | BOOL MessageBeep(UINT utype); |
utype
可能的参数值如下:
《Windows游戏编程大师技巧》学习笔记(二)