C++游戏之创建第一个窗体程序(一)

来源:互联网 发布:linux 驱动 培训 编辑:程序博客网 时间:2024/04/20 11:51

       说起游戏,大家都不陌生,大家很快就能想到LOL,DNF,QQ炫舞啊等一系列热门网游,那么它们是如何开发出来的呢?不得不说,这里面涉及到的东西太多太多,其中有:计算机图形学,计算机物理,计算机碰撞检测,计算机多媒体处理,计算机网络技术等。那么如今游戏开发都用什么语言呢?当然非C++莫属,为什么呢?不解释,好了,我们就从最简单的图形GDI开始吧(什么是GDI?下一章介绍)。 (PS:本文内容均为个人理解学习,获取有误 - - !)

   

        做游戏首先得有一个窗体吧,那么这节我们就简单的来创建一个窗体吧,怎么创建呢?可能你会想到MFC,但是这里我们不用它,为什么呢?因为它包含了很多对于游戏来说没有用的东西,影响效率。那么我们该怎么创建呢?


        我们先来认识一下主函数吧,你可能马上会想到int main(){}函数,但是这里不是,他是windows窗体,所以主函数为WinMain函数,该函数的功能是被系统调用,作为一个32位应用程序的入口点。

//WinMain入口函数 //第一个参数为当前窗体实列//第二窗体为父窗体实列//第三个参数为传递给应用程序的命令行参数//第四个参数指明窗口如何显示int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrivInstance,LPSTR lpCmdLine,int nShowCmd){}



创建一个窗口的步骤如下:
第一步:设计窗体
第二步:注册窗体
第三步:创建窗体
第四步:显示与更新
第五步:窗体消息队列
第六步:窗体过程函数


一,设计窗体:

WNDCLASSEX wndClass = {0};//描述窗口的结构体,{}表示初始化这个结构体的一个参数,就像创建一个对象需要new一样,不然就变成声明了wndClass.style = CS_HREDRAW | CS_VREDRAW;//窗体被上下左右拉伸时重新绘制wndClass.cbSize = sizeof(WNDCLASSEX);//结构体大小wndClass.cbClsExtra = 0;//类的附加内存,一般为0wndClass.cbWndExtra = 0;//窗体的附加内存,一般为0wndClass.hInstance = hInstance;//窗体的实列wndClass.hIcon = (HICON)LoadImage(NULL,L"icon.ico",IMAGE_ICON,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE);//窗体的图标文件,必须为ico格式的wndClass.hCursor = LoadCursor(NULL,IDC_ARROW);//窗体的光标wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);//窗体的背景颜色wndClass.lpszClassName = L"wndClass";//结构体名称wndClass.lpszMenuName = 0;//指定菜单资源的名字wndClass.lpfnWndProc = WndProc;//窗体的过程函数


二,注册窗体

        通过RegisterClassEx函数来注册我们已经设计好的窗体,注册成功返回true,失败时,返回false

//注册窗体,如果注册失败,返回-1if (!RegisterClassEx(&wndClass)){return -1;}


三,创建窗体

       通过CreateWindow函数来创建窗体,创建成功,返回HWND窗口句柄,失败,返回NULL

HWND hWnd = CreateWindow(L"wndClass",//结构体的名称,也就是Name属性L"This is a Windows!",//窗体的标题WS_OVERLAPPEDWINDOW,//窗体的层叠样式,通常为<span style="font-family: Arial, Helvetica, sans-serif;">WS_OVERLAPPEDWINDOW</span>CW_USEDEFAULT,//窗口位置,X坐标,可以给具体的的值,一般为CW_USEDFAULT即可CW_USEDEFAULT,//窗口位置,Y坐标,可以给具体的的值,一般为<span style="font-family: Arial, Helvetica, sans-serif;">CW_USEDFAULT即可</span>800,//窗口的宽600,//窗口的高NULL,//窗体的父窗体,为NULL,意思就是如果一个窗体打开两次,那么第一次的就是父窗体NULL,//<span style="font-family: Arial, Helvetica, sans-serif;">窗体的菜单资源,这里给NULL,表示没有</span>hInstance,//窗体的实列,直接给WinMain函数里面的参数就行了NULL);//附加参数,为NULL就好了

四,显示与更新

       通过前面的步骤,我们已经可以显示窗体了,通过ShowWindow函数,它有两个参数,第一个是窗体的句柄HWND,第二个也就是显示状态,这个参数直接给WinMain函数里面的参数就行了。通过UpdateWindow更新窗体,它有一个参数,即窗体句柄HWND

<pre name="code" class="cpp">//显示与更新ShowWindow(hWnd,nShowCmd);UpdateWindow(hWnd);

五,窗口消息队列

        顾名思义,它是用来获取窗体的操作信息的,比如拖动,重绘,键盘,鼠标的操作等信息。通过PeekMessage函数读取消息队列,它有5个参数

//读取窗体消息队列MSG msg = {0};//描述消息队列的结构体while (msg.message!=WM_QUIT)//判断是否退出程序,如果没有退出,就一直循环读取消息{if (PeekMessage(&msg,//存消息信息的结构体0,//窗体的句柄,0表示获取所有消息0,//消息最小值,为0即可0,//消息最大值,为0即可PM_REMOVE)//读取后,如果存在,发送消息,并移除该条信息)//读取消息{TranslateMessage(&msg);//将虚拟键消息转换为字符消息DispatchMessage(&msg);//把这个消息发给窗口程序}}


六,窗口过程函数

        前面有了消息队列,那么读取的消息在哪里处理呢?比如拖动,重绘,键盘按下,鼠标点击等,对,就是这个过程函数,它是负责处理消息队列发送过来的消息的。


//窗口过程函数处理//第一个参数,窗体的句柄//第二参数,消息ID(比如重绘,键盘按下等)//第三个参数与第四个参数为附加消息//通常我们通过第三个参数可以知道用户按下了某个键,或抬起某个键//第四个参数通常用作取鼠标的XY坐标LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wparam,LPARAM lparam){switch(message)//根据消息ID判断需要处理的消息{case WM_PAINT://重绘窗体ValidateRect(hWnd,NULL);//使整个窗体的无效区变成有效区,第一参数为窗体句柄                        //第二参数为NULL,表示所有区域,也可以是Rect的一个结构体,来限定窗体的有效区的区域break;case WM_DESTROY://窗口的关闭消息PostQuitMessage(0);//退出程序break;default://如果没有需要处理的消息,就调用默认的过程函数return DefWindowProc(hWnd,message,wparam,lparam);}return 0;}

有了以上步骤,一个窗体就算是完成创建了。下面是完整代码:


#include <Windows.h>//过程函数的声明LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wparam,LPARAM lparam);//入口函数 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrivInstance,LPSTR lpCmdLine,int nShowCmd){//设计窗体WNDCLASSEX wndClass = {0};wndClass.style = CS_HREDRAW | CS_VREDRAW;wndClass.cbSize = sizeof(WNDCLASSEX);wndClass.cbClsExtra = 0;wndClass.cbWndExtra = 0;wndClass.hInstance = hInstance;wndClass.hIcon = (HICON)LoadImage(NULL,L"icon.ico",IMAGE_ICON,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE);wndClass.hCursor = LoadCursor(NULL,IDC_ARROW);wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);wndClass.lpszClassName = L"wndClass";wndClass.lpszMenuName = 0;wndClass.lpfnWndProc = WndProc;//注册窗体if (!RegisterClassEx(&wndClass)){return -1;}//创建窗体HWND hWnd = CreateWindow(L"wndClass",L"This is a Windows!",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,800,600,NULL,NULL,hInstance,NULL);//显示与更新ShowWindow(hWnd,nShowCmd);UpdateWindow(hWnd);//读取窗体消息队列MSG msg = {0};//描述消息队列的结构体while (msg.message!=WM_QUIT)//判断是否退出程序,如果没有退出,就一直循环读取消息{if (PeekMessage(&msg,//存消息信息的结构体0,//窗体的句柄,0表示获取所有消息0,//消息最小值,为0即可0,//消息最大值,为0即可PM_REMOVE)//读取后,如果存在,发送消息,并移除该条信息)//读取消息{TranslateMessage(&msg);//将虚拟键消息转换为字符消息DispatchMessage(&msg);//把这个消息发给窗口程序}}UnregisterClass(L"wndClass",hInstance);}//窗口过程函数处理LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wparam,LPARAM lparam){switch(message)//根据消息ID判断需要处理的消息{case WM_PAINT://重绘窗体ValidateRect(hWnd,NULL);break;case WM_DESTROY://窗口的关闭消息PostQuitMessage(0);break;default://如果没有需要处理的消息,就调用默认的过程函数return DefWindowProc(hWnd,message,wparam,lparam);}return 0;}


运行效果图:







0 0
原创粉丝点击