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

       上一章,我们已经知道了如何创建一个窗体,窗体是有了,接下来就是如何在上面绘图呢?下面我们就来介绍和使用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_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);
}




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值