C++游戏之GDI的初步认识与使用(二)

来源:互联网 发布:冬天肌肤问题 知乎 编辑:程序博客网 时间:2024/06/06 09:32
       上一章,我们已经知道了如何创建一个窗体,窗体是有了,接下来就是如何在上面绘图呢?下面我们就来介绍和使用GDI吧,很简单的一个东西。(奋斗以下内容均为个人理解与学习经验奋斗)

        GDI,什么是GDI,GDI是windows有生俱来绘图接口,全称:GraphicsDeviceInterface(图形设备接口),windows的三大核心组件之一,负责处理所有的windows程序的图形输出,利用它,我们可以很轻松的在屏幕上绘制图形了。我们能利用它开发一些绘制要求不高的游戏,比如小时候玩的魂斗罗,超级玛丽啊等小游戏,或一些RPG(角色扮演类)小游戏,我们都是可以用GDI制作的。那么LOL,DNF,QQ炫舞等这些游戏是用什么图形接口呢?当然是DirectX或OpenGL,什么是DirectX和OpenGL呢?后面我们会讲DirectX,这里不做了解。还是从最简单的GDI开始吧。

       准备一张背景图片,要求是BMP格式的,然后创建一个窗体,在窗体上进行绘制。

       如何绘制呢?我们知道窗体是有了,接下来就是获取窗体的作图区域,那么这个作图区域是什么呢?它就是设备环境DC,为了便于理解,可以理解为画布(反正我是这么想的,呵呵),我们通过GetDC函数来获取窗体的设备环境DC,该函数只需要一个参数,即窗体的句柄,返回设备环境的指针HDC,代码很简单,就一句话。

HDC g_hdc = GetDC(hwnd);//获取设备环境DC

       获取设备环境后,我们还不能直接作图,我们还需要在内存中创建一个设备环境,我们在内存中画图,画好以后,直接拷贝到窗体的设备环境上就行了,那么如何在内存中创建一个与窗体设备环境相等的内存设备环境呢?通过CreateCompatibleDC函数即可,它有一个参数,那就是要创建的设备环境的指针,一看这函数的名称就知道了以上,创建兼容设备环境,它也返回设备环境的指针HDC,代码也很简单,还是一句话。

HDC m_hdc = CreateCompatibleDC(g_hdc);//建立兼容的设备环境

         好了,绘图环境我们已经有了,那么如何绘制呢?比如绘制字符串和图片,下面我们就依依道来,先说绘制字符串吧,我们要绘制字符串,很简单,通过TextOut这个函数就行了,这个函数有5个参数。

//第一个参数,绘制的HDC(画布)//第二个和第三个参数为绘制的XY窗口坐标//第四个参数为绘制的字符串,wchar_t类型的//第五个参数为字符串的长度TextOut(m_hdc,10,10,test.c_str(),wcslen(test.c_str()));//绘制文本

         通过TextOut绘制的字符串,我们发现很难看,如图我们发现,不光很难看,而且还不透明。那么我们如何来美化它呢?比如透明,我们可以通过SetBkMode函数即可,它有两个参数,第一个是设备环境,比如这里,我们在m_hdc上绘制文本,所以第一参数是m_hdc,第二个参数是TRANSPARENT,它已经被定义好了的,我们直接用就行了。然后我们就看到了这样的效果,虽然是透明了,但是还是很难看,我们想设置字体颜色和字体大小可不可以呢?当然可以,我们可以通过SetTextColor函数来设置绘制颜色,这个函数有两个参数,第一是设备环境,与TextOut的第一参数一样,第二个参数是颜色,即RGB(50,50,255),红,绿,蓝,这里50,50,225是蓝色,颜色有了,如何设置字体呢?通过CreateFont函数创建一个字体,这个函数返回字体指针HFont,参数嘛,比较长,这里就记住以下即可,CreateFont(30,0,0,0,0,0,0,0,GB2312_CHARSET,0,0,0,0,L"微软雅黑"),参数30为字体高,第二个参数为字体的宽,GB2312_CHARSET为字符编码,L"微软雅黑"为字符字体,其它给0就行了。然后我们把这个字体指针HFont放到设备环境上就行了,通过SelectObject即可,这个函数两个参数,第一个是设备环境,第二个是放入的指针,这里为字体指针。上面说了一大堆,其实也就四句话:

HFont hfont = CreateFont(30,0,0,0,0,0,0,0,GB2312_CHARSET,0,0,0,0,L"微软雅黑");//创建字体SetBkMode(m_hdc,TRANSPARENT);//设置文字背景透明SetTextColor(m_hdc,RGB(50,50,255));//设置文本绘制颜色为蓝色SelectObject(m_hdc,hfont);//将字体放到m_hdc

        绘制文字就这些,那么如何绘制一张图片呢?在绘制图片之前,我们是不是要把绘制的图片加载到内存中来呢?
通过LoadImage函数加载一张图片,这个函数有六个参数。该函数返回位图句柄,需强制转换为HBITMAP。比如加载一张背景图。

//第一个参数,为窗体实列,这里给NULL,因为我们从本地加载//第二个参数,文件路径//第三个参数,获取文件的类型,这里是IMAGE_BITMAP即图片位图//第四个参数,图片的宽//第五个参数,图片的高//第六个参数为组合参数,LR_LOADFROMFILE标示这个文件来自硬盘//如果第四个参数与第五个参数为0,那么最后一参数还需一个标示LR_DEFAULTSIZE//表示默认大小,即把最后一参数改为LR_LOADFROMFILE|LR_DEFAULTSIZEHBITMAP bg = (HBITMAP)LoadImage(NULL,L"bg.bmp",IMAGE_BITMAP,800,600,LR_LOADFROMFILE);

          图片我们也获取了,那么如何绘制呢?它和字体一样,通过SelectObject即可,比如我们把他绘制到内存环境中,SelectObject(m_hdc,bg);就行了。

          通过上面的介绍,这里就只剩下一个问题了,那就是如何把内存环境拷贝到设备环境上,很简单,通过BitBlt函数即可,这个函数有九个参数。

//第一个参数,接收结果的环境,即窗口环境g_hdc//第二个参数,窗口绘制的X坐标//第三个参数,窗口绘制的Y坐标//第四个参数,窗口绘制的宽//第五个参数,窗口绘制的高//第六个参数,被拷贝的环境,即内存环境m_hdc//第七个参数,从被拷贝的环境的X坐标开始//第八个参数,从被拷贝的环境的Y坐标开始//第九个参数,为处理标示,这里SRCCOPY告诉通过复制的方式BitBlt(g_hdc,0,0,800,600,m_hdc,0,0,SRCCOPY);//BitBlt函数

           好了,介绍也就这么多,下面我们就来开始正式绘制吧,首先声明如下:
HDC g_hdc;//设备环境HDC m_hdc;//兼容的设备环境HBITMAP bg;//绘制的背景图指针wstring test=L"Hello Word";//绘制的字符串HFONT hfont;//字体对象指针//初始化资源,用于初始化设备环境和加载背景图片void Game_Init(HWND hwnd);//绘制图形,正式绘制void Game_Paint(HWND hwnd);//清理资源,程序退出时,释放资源void Game_Clear(HWND hwnd);

三个函数的实现
//初始化资源void Game_Init(HWND hwnd){g_hdc = GetDC(hwnd);//获取设备环境DCm_hdc = CreateCompatibleDC(g_hdc);//建立兼容的设备环境hfont = CreateFont(30,0,0,0,0,0,0,0,GB2312_CHARSET,0,0,0,0,L"微软雅黑");//创建字体SetBkMode(m_hdc,TRANSPARENT);//设置文字背景透明SetTextColor(m_hdc,RGB(50,50,255));//设置文本绘制颜色SelectObject(m_hdc,hfont);//将字符串放到m_hdc//加载背景图片bg = (HBITMAP)LoadImage(NULL,L"bg.bmp",IMAGE_BITMAP,800,600,LR_LOADFROMFILE);}//绘制图形void Game_Paint(HWND hwnd){SelectObject(m_hdc,bg);//将图片放到HDC上TextOut(m_hdc,10,10,test.c_str(),wcslen(test.c_str()));//绘制文本BitBlt(g_hdc,0,0,800,600,m_hdc,0,0,SRCCOPY);//拷贝到设备环境上}//清理内存void Game_Clear(HWND hwnd){ReleaseDC(hwnd,g_hdc);DeleteObject(hfont);DeleteObject(bg);DeleteObject(m_hdc);}

以下为完整代码与运行效果图,将展示如何在屏幕上绘制一串文字(Hello Word)和一张背景图 .  
记得找一张BMP的图片放在和源码同一级目录下面即可。
    


完整代码:
#include <Windows.h>#include <string>using namespace std;//窗体的过程函数LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam);HDC g_hdc;//设备环境HDC m_hdc;//兼容的设备环境HBITMAP bg;//绘制的背景图指针wstring test=L"Hello Word";//绘制的字符串HFONT hfont;//字体对象指针//初始化资源,用于初始化设备环境和加载背景图片void Game_Init(HWND hwnd);//绘制图形,正式绘制void Game_Paint(HWND hwnd);//清理资源,程序退出时,释放资源void Game_Clear(HWND hwnd);//WinMain主函数INT WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrivInstance,LPSTR lpCmdLine,int nShowCmd){//设计一个窗体WNDCLASSEX wndClass = {0};wndClass.style = CS_HREDRAW|CS_VREDRAW;wndClass.cbSize = sizeof(wndClass);wndClass.cbClsExtra = 0;wndClass.cbWndExtra = 0;wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);wndClass.hCursor = ::LoadCursor(hInstance,IDC_ARROW);wndClass.hIcon = (HICON)::LoadImage(NULL,L"",IMAGE_ICON,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE);wndClass.hInstance = hInstance;wndClass.lpfnWndProc = WndProc;wndClass.lpszClassName = L"Test";wndClass.lpszMenuName = 0; //注册窗体if (!RegisterClassEx(&wndClass)){return -1;}//创建窗体HWND hwnd = CreateWindow(L"Test",L"GDI",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,800,600,NULL,NULL,hInstance,NULL);if (hwnd == NULL){return -1;}//初始化资源Game_Init(hwnd);//显示与更新窗体ShowWindow(hwnd,nShowCmd);UpdateWindow(hwnd);//消息队列MSG msg = {0};while (msg.message != WM_QUIT){if (PeekMessage(&msg,0,0,0,PM_REMOVE))//读取消息{TranslateMessage(&msg);//翻译消息DispatchMessage(&msg);//发送消息}else{Game_Reader(hwnd);//绘制函数Sleep(50);//绘制间隙50毫秒}}UnregisterClass(L"Test",hInstance);return 0;}//窗口过程函数LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam){switch(message){case WM_PAINT:ValidateRect(hwnd,NULL);//重绘整个窗体break;case WM_DESTROY:Game_Clear(hwnd);//退出程序时,清理资源PostQuitMessage(0);break;default:return DefWindowProc(hwnd,message,wparam,lparam);}return 0;}//初始化资源void Game_Init(HWND hwnd){g_hdc = GetDC(hwnd);//获取设备环境DCm_hdc = CreateCompatibleDC(g_hdc);//建立兼容的设备环境hfont = CreateFont(30,0,0,0,0,0,0,0,GB2312_CHARSET,0,0,0,0,L"微软雅黑");//创建字体SetBkMode(m_hdc,TRANSPARENT);//设置文字背景透明SetTextColor(m_hdc,RGB(50,50,255));//设置文本绘制颜色SelectObject(m_hdc,hfont);//将字符串放到m_hdc//加载背景图片bg = (HBITMAP)LoadImage(NULL,L"bg.bmp",IMAGE_BITMAP,800,600,LR_LOADFROMFILE);}//绘制函数void Game_Paint(HWND hwnd){SelectObject(m_hdc,bg);//将图片放到HDC上TextOut(m_hdc,10,10,test.c_str(),wcslen(test.c_str()));//绘制文本BitBlt(g_hdc,0,0,800,600,m_hdc,0,0,SRCCOPY);//拷贝到设备环境上}//清理内存void Game_Clear(HWND hwnd){ReleaseDC(hwnd,g_hdc);DeleteObject(hfont);DeleteObject(bg);DeleteObject(m_hdc);}




0 0