GDI初印象

    首先声明一下,图图对风靡CSDN论坛的浅墨大哥比较崇拜,买了一本他的《windows编程从零开始》,图图写的有关游戏编程的博客里面借鉴了好多浅墨大哥书里的话,然后再加上一些图图自己的理解,所以请看过浅墨大哥文章或者他的书的人请不要喷图图写的博客,喜欢的话就提提图图博客里的不足之处,不喜欢的话就说说图图文章哪里写的不好。好了,下面进入正文。


    GDI英文全称为Graphics Device Interface,也就是图形设备接口的意思。GDI是Windows绘图API,使得用户无需关心具体设备的细节,而只需在一个虚拟的环境中进行操作。我们利用GDI所提供的函数可以方便地在屏幕、打印机及其他输出设备上输出图形、文本等操作,实现程序开发与硬件设备的隔离,大大方便我们的开发工作。


    虽然GDI可以让我们轻易进行图形程序开发,但是它的绘图效率跟专业的图形API比起来还是比较低的,我们使用的专业游戏图形API比如DirectX和OpenGL,它们是允许程序直接访问底层显卡内存的,可以实现硬件加速。在现在这个玩家注重游戏运行画面和运行速度的社会下,直接用GDI来进行游戏开发显然是不明智的。但是我们很难在完全不了解GDI的情况下就能直接利用专业的图形API(如DirectX和OpenGL)来进行游戏开发,DirectX中的DrawTex()函数就是对GDI中TextOut()函数的封装。所以如果我们不太注重画面和游戏速度的话,还是可以用GDI来玩玩的,当然了这个仅限于二维游戏,小时候我们玩的《魂斗罗》和《超级玛丽》就是用GDI写出来的。


    GDI中一个最基础而且使用最频繁的概念就是设备上下文,英文全称Device Context,如果把我们的程序窗口比喻成画板的话,那么这个设备上下文就是画板上面的画纸(有点像Java中的JPanel面板的意思,学过Java的同学可以结合一下想想),所以我们在画图之前必须获得设备上下文的句柄(HDC),HDC即Handle of device context的简称,画完画后我们要释放这个设备上下文句柄。


下面介绍两种获得设备上下文句柄的方法:

1、这种方法我们只能在窗口过程函数里的WM_PAINT这个画面重绘消息里使用,这个方法我们使用BeginPaint和EndPaint这两个函数,这两个函数的参数都是一样的,第一个是HWND类型的我们当前激活的窗口实例,第二个参数是PAINTSTRUCT结构体指针类型的保存当前画纸信息的变量,给大家贴出使用代码

HDC g_hdc; //全局设备上下文变量(画纸)
......
int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd )
{
	......
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg)
	{
		PAINTSTRUCT paintStruct; //记录设备上下文(画纸)信息的变量

		case WM_PAINT:
			g_hdc = BeginPaint(hwnd, &paintStruct); //指定是哪个窗口进行画画,
			//并把画纸信息保存进paintStruct变量中
			Game_Paint(); //进行画画的函数
			EndPaint(hwnd, &paintStruct); //画完画我们就关闭画纸
			ValidateRect(hwnd); //更新窗口画面
			break;

		......
	}
......
}

    怎么样,使用还算简单吧,要注意BeginPaint和EndPaint这对好基友要成对出现哦,我们要养成及时释放资源的习惯,最好是我们一写好BeginPaint就立即写上EndPaint函数,这样我们就不太容易出错。


2、第二种获得HDC的方法是使用GetDC和ReleaseDC函数。GetDC函数里的唯一参数就是HWND类型的窗口句柄,Release函数里的第一个参数是HWND类型的窗口句柄,第二个是我们通过GetDC获得的HDC类型的设备上下文句柄,给出演示示例让小伙伴们看看它的简单实用

HDC g_hdc; //全局设备上下文变量(画纸)
g_hdc = GetDC(hwnd); //获得设备上下文句柄
Game_Paint(hwnd); //自定义的画画函数
ReleaseDC(hwnd, g_hdc); //释放设备上下文句柄

     接下来给大家贴出一个GDI程序通用的模板,大家以后写GDI程序就可以直接套用这个模板了

//-----------------------------------------------------------
// 程序名称:GDIdemoCore
// 2014年4月by图图
// 描述:实现GDI游戏卡法所需的核心程序
//-----------------------------------------------------------

#include <Windows.h>

#define WINDOW_WDTH   800 //定义窗口宽度
#define WINDOW_HEIGHT 600 //定义窗口高度
#define WINDOW_CLASS  L"ForTheDreamOfGameDevelop" //定义窗口类名称
#define WINDOW_NAME   L"【致我们永不熄灭的游戏开发梦想】GDI程序核心框架" //定义窗口标题

//全局变量
HDC g_hdc = NULL; //全局设备上下文句柄

//全局函数声明
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //窗口过程函数
BOOL Game_Init(HWND hwnd); //资源初始化函数
VOID Game_Paint(HWND hwnd); //绘画函数
BOOL Game_CleanUp(HWND hwnd); //释放资源函数

//Windows应用程序入口函数
int WINAPI WinMain( 
	__in HINSTANCE hInstance, 
	__in_opt HINSTANCE hPrevInstance, 
	__in LPSTR lpCmdLine, 
	__in int nShowCmd 
)
{
	//设计一个窗口类
	WNDCLASSEX wcex = { 0 };

	wcex.cbClsExtra = 0;
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.cbWndExtra = 0;
	wcex.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hIcon = (HICON)::LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);
	wcex.hIconSm = NULL;
	wcex.hInstance = hInstance;
	wcex.lpfnWndProc = WindowProc;
	wcex.lpszClassName = WINDOW_CLASS;
	wcex.lpszMenuName = NULL;
	wcex.style = CS_HREDRAW | CS_VREDRAW;

	//如果注册失败就返回退出
	if(!RegisterClassEx(&wcex))
	   return -1;

	//创建窗口实例
	HWND hwnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
		                     WINDOW_WDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);

	//窗口的移动、显示和更新
	MoveWindow(hwnd, 250, 80, WINDOW_WDTH, WINDOW_HEIGHT, true); //移动窗口到(250,80)处
	ShowWindow(hwnd, nShowCmd);
	UpdateWindow(hwnd);

	//初始化游戏资源
	if(!Game_Init(hwnd))
	{
		MessageBox(hwnd, L"资源初始化失败", L"消息窗口", 0); //创建消息窗口提示初始化资源失败
		return FALSE;
	}

	//消息循环
	MSG msg = { 0 };
	while(msg.message != WM_QUIT)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	//注销窗口类
	UnregisterClass(WINDOW_CLASS, wcex.hInstance);

	return 0;
}

//窗口过程函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT paintStruct; //定义一个PAINTSTRUCT结构体来记录一些绘制信息

	switch(uMsg)
	{
	case WM_PAINT: //重绘消息
		g_hdc = BeginPaint(hwnd, &paintStruct);
		Game_Paint(hwnd);
		EndPaint(hwnd, &paintStruct);//绘画结束
		ValidateRect(hwnd, NULL); //更新客户区显示
		break; 

	case  WM_KEYDOWN: //键盘按下消息
		if(wParam == VK_ESCAPE)
		   DestroyWindow(hwnd);
		break;

	case  WM_DESTROY:
		Game_CleanUp(hwnd); //释放资源

		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hwnd, uMsg, wParam, lParam);
	}

	return 0;
}

//初始化函数
BOOL Game_Init(HWND hwnd)
{
	g_hdc = GetDC(hwnd);
	Game_Paint(hwnd);
	ReleaseDC(hwnd, g_hdc);
	return TRUE;
}

//绘画函数
VOID Game_Paint(HWND hwnd)
{

}

//释放资源函数
BOOL Game_CleanUp(HWND hwnd)
{
	return TRUE;
}

运行画面如下                

       
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值