在“构建游戏设计的舞台”这一随笔中,建立的项目便是一个标准Windows API的程序架构,主程序文件“canvas.cpp”由下表中几个重要的函数所构成:
函数名称
|
说明
|
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; }
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); }
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; }
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; }
下载源代码: canvas.rar(文件上传在Windows live空间,可能需要有msn账号进行登录) PS:如想获得更多关于Visual C++游戏开发的内容,可点击随笔 :《Visual C++游戏编程基础》学习笔记——索引随笔。
|