概述
上一章,我们已经知道了如何创建一个窗体,窗体是有了,接下来就是如何在上面绘图呢?下面我们就来介绍和使用GDI吧,很简单的一个东西。(以下内容均为个人理解与学习经验)
GDI,什么是GDI,GDI是windows有生俱来绘图接口,全称:GraphicsDeviceInterface(图形设备接口),windows的三大核心组件之一,负责处理所有的windows程序的图形输出,利用它,我们可以很轻松的在屏幕上绘制图形了。我们能利用它开发一些绘制要求不高的游戏,比如小时候玩的魂斗罗,超级玛丽啊等小游戏,或一些RPG(角色扮演类)小游戏,我们都是可以用GDI制作的。那么LOL,DNF,QQ炫舞等这些游戏是用什么图形接口呢?当然是DirectX或OpenGL,什么是DirectX和OpenGL呢?后面我们会讲DirectX,这里不做了解。还是从最简单的GDI开始吧。
准备一张背景图片,要求是BMP格式的,然后创建一个窗体,在窗体上进行绘制。
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_DEFAULTSIZE
HBITMAP 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);//获取设备环境DC
m_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);//获取设备环境DC
m_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);
}
最后
以上就是自然蜡烛为你收集整理的C++游戏之GDI的初步认识与使用(二)的全部内容,希望文章能够帮你解决C++游戏之GDI的初步认识与使用(二)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复