程序架构说明
在“构建游戏设计的舞台”这一随笔中,建立的项目便是一个标准Windows API的程序架构,主程序文件“canvas.cpp”由下表中几个重要的函数所构成:
2.MyRegisterClass函数
3.InitInstance函数
4.WndPro函数
下载源代码: canvas.rar(文件上传在Windows live空间,可能需要有msn账号进行登录)
PS:如想获得更多关于Visual C++游戏开发的内容,可点击随笔 :《Visual C++游戏编程基础》学习笔记——索引随笔。
函数名称 |
说明 |
WinMain |
主程序,程序起始点 |
WndProc |
自定义函数,处理程序消息 |
MyRegisterClass |
自定义函数,注册窗口类别 |
InitInstance |
自定义函数,建立及显示窗口的初始化函数 |
下面来说说这些函数的内容与功能。
1.WinMain函数
主程序,也就是整个项目程序开始运行的地方,如同Console程序中的main()函数。
//
****主程序***********************************
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
/**//**********************************************************
* 自定义函数,注册窗口类别
* 调用MyRegisterClass()函数,向系统注册窗口类别,输入参数
* “hInstance”是目前程序运行个体的对象代码
**********************************************************/
MyRegisterClass(hInstance);
// 运行初始化函数,调用InitInstance()函数,进行初始化操作
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
/**//******************************************************************
* 消息循环
* 程序通过此消息循环来获取消息,并进行必要的键盘消息转换,
* 而后将控制权交给操作系统,由操作系统决定该由哪个程序的
* 消息处理函数处理消息。这个循环使用了3个API函数
* GetMessage 获取程序消息
* TranslateMessage 转换伪码及字符
* DispatchMessage 将控制权交给系统,再由系统决定负责处理消息的程序
******************************************************************/
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
/**//**********************************************************
* 自定义函数,注册窗口类别
* 调用MyRegisterClass()函数,向系统注册窗口类别,输入参数
* “hInstance”是目前程序运行个体的对象代码
**********************************************************/
MyRegisterClass(hInstance);
// 运行初始化函数,调用InitInstance()函数,进行初始化操作
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
/**//******************************************************************
* 消息循环
* 程序通过此消息循环来获取消息,并进行必要的键盘消息转换,
* 而后将控制权交给操作系统,由操作系统决定该由哪个程序的
* 消息处理函数处理消息。这个循环使用了3个API函数
* GetMessage 获取程序消息
* TranslateMessage 转换伪码及字符
* DispatchMessage 将控制权交给系统,再由系统决定负责处理消息的程序
******************************************************************/
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
2.MyRegisterClass函数
/**/
/*****************************************************************
* 在建立程序窗口的实体之前,必须先定义一个窗口类别,其中包含所要
* 建立窗口的相关信息,并向系统注册。这里的MyRegisterClass()函数
* 就是进行定义及注册窗口类别的函数
*****************************************************************/
ATOM MyRegisterClass(HINSTANCE hInstance)
{
//声明一个窗口类别“WNDCLASSEX”和结构“wcex”
WNDCLASSEX wcex;
/**//***************************Begin***********************************/
// 定义“wcex”结构的各项信息,其中设定消息处理函数(IpfnWndProc)为
// “WndProc”,类别名称(lpszClassName)为“canvas”。
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
// 设定消息处理函数
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
//类别名称
wcex.lpszClassName = "canvas";
wcex.hIconSm = NULL;
/**//****************************End************************************/
// 调用RegisterClassEx()函数注册类别,返回一个“ATOM”形态的字符串,此字符串即为类别名称“canvas”
return RegisterClassEx(&wcex);
}
* 在建立程序窗口的实体之前,必须先定义一个窗口类别,其中包含所要
* 建立窗口的相关信息,并向系统注册。这里的MyRegisterClass()函数
* 就是进行定义及注册窗口类别的函数
*****************************************************************/
ATOM MyRegisterClass(HINSTANCE hInstance)
{
//声明一个窗口类别“WNDCLASSEX”和结构“wcex”
WNDCLASSEX wcex;
/**//***************************Begin***********************************/
// 定义“wcex”结构的各项信息,其中设定消息处理函数(IpfnWndProc)为
// “WndProc”,类别名称(lpszClassName)为“canvas”。
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
// 设定消息处理函数
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
//类别名称
wcex.lpszClassName = "canvas";
wcex.hIconSm = NULL;
/**//****************************End************************************/
// 调用RegisterClassEx()函数注册类别,返回一个“ATOM”形态的字符串,此字符串即为类别名称“canvas”
return RegisterClassEx(&wcex);
}
3.InitInstance函数
//
在这一初始函数中,按照前面所定义的窗口类别来建立并显示实际的程序窗口
// *****初始化函数*******************************
// 1.存储instance handle于全局变量中
// 2.建立并显示主窗口
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance;
// 调用CreateWindow()函数来建立一个窗口对象,所输入的第1个参数
// 就是窗口建立所依据的类别名称,也就是前面程序所定义的“canvas”
hWnd = CreateWindow("canvas", "绘图窗口" , WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
// 下面三条语句,设定窗口的显示位置及窗口大小,然后绘制在显示设备上
// 设定窗口显示的位置及窗口大小
MoveWindow(hWnd,10,10,600,450,true);
// 设定窗口显示时的状态
ShowWindow(hWnd, nCmdShow);
// 将窗口绘制于显示设备上
UpdateWindow(hWnd);
return TRUE;
}
// *****初始化函数*******************************
// 1.存储instance handle于全局变量中
// 2.建立并显示主窗口
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance;
// 调用CreateWindow()函数来建立一个窗口对象,所输入的第1个参数
// 就是窗口建立所依据的类别名称,也就是前面程序所定义的“canvas”
hWnd = CreateWindow("canvas", "绘图窗口" , WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
// 下面三条语句,设定窗口的显示位置及窗口大小,然后绘制在显示设备上
// 设定窗口显示的位置及窗口大小
MoveWindow(hWnd,10,10,600,450,true);
// 设定窗口显示时的状态
ShowWindow(hWnd, nCmdShow);
// 将窗口绘制于显示设备上
UpdateWindow(hWnd);
return TRUE;
}
4.WndPro函数
/**/
/********************************************************************************
* 在前面定义类别的时候把WndPro定义为消息处理函数,也就是当某些外部消息发生时,会
* 按照消息的类型来决定该如何进行处理。
* 此外,WndPro函数也是一个所谓的“回调函数(CALLBACK)”,简单地说,回调函数是属于
* Windows操作系统所调用的函数,而非程序本身所调用的函数,这是因为Windows是一个多任
* 务的作业环境,在同一时刻可能会有多个程序正在运行,而当某一事件发生时,有可能每一
* 个程序都会接受到此消息,因此系统必须去判断该由哪个程序进行处理,然后再调用该程序
* 的消息处理函数。
********************************************************************************/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
// 判断消息类型
switch (message)
{
case WM_PAINT: //窗口重绘消息
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY: //窗口结束消息
/**//***********************************************************
* 调用PostQuitMessage()函数发送窗口结束消息给系统,通知
* 系统结束目前程序的运行,然后由系统处理程序结束的后续操作
***********************************************************/
PostQuitMessage(0);
break;
default: //其他消息
// DefWindowProc()函数调用预设的系统函数来处理程序本身不处理的消息
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
* 在前面定义类别的时候把WndPro定义为消息处理函数,也就是当某些外部消息发生时,会
* 按照消息的类型来决定该如何进行处理。
* 此外,WndPro函数也是一个所谓的“回调函数(CALLBACK)”,简单地说,回调函数是属于
* Windows操作系统所调用的函数,而非程序本身所调用的函数,这是因为Windows是一个多任
* 务的作业环境,在同一时刻可能会有多个程序正在运行,而当某一事件发生时,有可能每一
* 个程序都会接受到此消息,因此系统必须去判断该由哪个程序进行处理,然后再调用该程序
* 的消息处理函数。
********************************************************************************/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
// 判断消息类型
switch (message)
{
case WM_PAINT: //窗口重绘消息
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY: //窗口结束消息
/**//***********************************************************
* 调用PostQuitMessage()函数发送窗口结束消息给系统,通知
* 系统结束目前程序的运行,然后由系统处理程序结束的后续操作
***********************************************************/
PostQuitMessage(0);
break;
default: //其他消息
// DefWindowProc()函数调用预设的系统函数来处理程序本身不处理的消息
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
下载源代码: canvas.rar(文件上传在Windows live空间,可能需要有msn账号进行登录)
PS:如想获得更多关于Visual C++游戏开发的内容,可点击随笔 :《Visual C++游戏编程基础》学习笔记——索引随笔。