win32 + OpenGL程序框架

#include <windows.h>				//win32的头文件
#include <tchar.h>
#include <gl\gl.h>					//opengl32.lib 的头文件
#include <gl\glu.h>					//glu32.lib 的头文件

HDC			hDC = NULL;				//全局的设备描述表句柄
HGLRC		hRC = NULL;				//Rendering Context句柄
HWND		hWnd = NULL;			//win32程序的窗口句柄
HINSTANCE	hInst;					//win32程序的实例句柄

bool	Fullscreen = false;
int		Width	= 800;
int		Height	= 600;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);	//声明窗口过程函数
void InitGL();											//初始化OpenGL
void ResizeGLScene(int, int);							//当窗口大小变化时,调整OpenGL的投影
void DrawGLScene();										//绘制OpenGL内容

//创建windows窗口并绑定OpenGL
//未实现全屏判断
BOOL CreateGLWindow(TCHAR *caption, int bits, BOOL fullscreenflag)
{
	GLuint		PixelFormat;
	WNDCLASS	wndclass;					//窗口类结构

	Fullscreen = fullscreenflag;

	hInst					= GetModuleHandle(NULL);
	wndclass.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;		//HREDRAW,VREDRAW表示该窗口在大小改变时候将发生WM_PAINT消息;
																		//OWNDC表示该窗口将保存自己的设备描述表属性
	wndclass.lpfnWndProc	= WndProc;									//注册窗口过程
	wndclass.cbClsExtra		= 0;										//额外的窗口信息
	wndclass.cbWndExtra		= 0;										//额外的窗口信息
	wndclass.hInstance		= hInst;									//为什么要用这个函数?
	wndclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);			//窗口图标
	wndclass.hCursor		= LoadCursor(NULL, IDC_ARROW);				//窗口鼠标图标
	wndclass.hbrBackground	= NULL;										//窗口背景画刷(	因为我们用Opengl绘图,不宜再使用GDI提供的画刷;否则如果选用
																		//				GetStockObject(WHITE_BRUSH),你会发现每次拉动窗口大小时候画面将会被该画刷清除!)
	wndclass.lpszMenuName	= NULL;										//该窗口没有菜单
	wndclass.lpszClassName	= TEXT("OpenGL");							//窗口类名字
	
	//注册该窗口类
	if(!RegisterClass(&wndclass))										
	{
		MessageBox(NULL, TEXT("Failed To Register The Window Class."), TEXT("ERROR"), MB_ICONERROR);
		return false;
	}

	if(Fullscreen)
	{
		MessageBox(NULL, TEXT("不好意思,没实现全屏窗口."), TEXT("ERROR"), MB_OK);
	}
	
	//创建程序窗口
	hWnd = CreateWindow(	TEXT("OpenGL"),
							TEXT("OpenGL Framework"),
							WS_OVERLAPPEDWINDOW,
							0,												//窗口x坐标				
							0,												//窗口y坐标
							Width,											//窗口宽
							Height,											//窗口高
							NULL,											//父窗口句柄
							NULL,											//窗口菜单句柄
							hInst,											//程序实例句柄
							NULL);											//创建附带参数
																			//CreateWindow函数在返回前,会发送WM_CREATE消息
	if(!hWnd)
	{
		MessageBox(NULL, TEXT("Failed To Create A Window."), TEXT("ERROR"), MB_ICONERROR);
		return false;
	}

	//设置像素格式
	PIXELFORMATDESCRIPTOR pfd = {
		sizeof(PIXELFORMATDESCRIPTOR),									//PIXELFORMATDESCRIPTOR结构体的大小
		1,																//PIXELFORMATDESCRIPTOR结构体的版本号
		PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,		//定义像素缓存的属性
		PFD_TYPE_RGBA,													//像素数据类型,可以是RGBA或者是COLORINDEX
		bits,															//每个像素点的颜色位数
		0, 0, 0, 0, 0, 0,												//忽略每个颜色位
		0,																//无alpha缓存
		0,																//忽略移位位 
	    0,																//无累加缓存 
	    0, 0, 0, 0,														//忽略累加位 
	    16,																//16位深度缓存     
	    0,																//无模板缓存 
	    0,																//无辅助缓存 
	    PFD_MAIN_PLANE,													//主层 
	    0,																//保留 
	    0, 0, 0															//忽略层,可见性和损毁掩模 
	};

	hDC = GetDC(hWnd);													//获得设备描述表
																		//相应的ReleaseDC在DestroyGLWindow中调用

	PixelFormat = ChoosePixelFormat(hDC, &pfd);
	SetPixelFormat(hDC, PixelFormat, &pfd );
	hRC = wglCreateContext(hDC);
	wglMakeCurrent(hDC, hRC);

	InitGL();															//我本来想把这个函数放在WM_CREATE消息中处理。
																		//但实际上,CreateWindow函数返回之前,就可能发送并处理WM_CREATE消息了。
																		//而此时上面几句OpenGL绑定到设备描述表的还没做呢
	
	return TRUE;
}

//销毁OpenGL关联的窗口
void DestroyGLWindow()
{
	if(hRC)
	{
		wglMakeCurrent(NULL, NULL);
		wglDeleteContext(hRC);
		hRC = NULL;
	}

	if(hDC)
	{
		ReleaseDC(hWnd, hDC);
	}
}

//主程序入口
int WINAPI WinMain( HINSTANCE	hInstance,				//该实例句柄
				    HINSTANCE	hPrevInstance,			//上一个实例
				    LPSTR		lpCmdLine,				//启动该实例的命令行参数
					int			iCmdShow)				//程序初始显示方法
{
	MSG		msg;										//windows消息结构
	BOOL	quit = FALSE;								//用来判断是否跳出循环
	BOOL	fullscreenflag = true;							//全屏标志
	float	theta = 0.0;

	if(MessageBox(NULL, TEXT("Would U Like To Run In Fullscreen Mode?"), TEXT("Start Fullscreen?"), MB_YESNO|MB_ICONQUESTION) == IDNO)
	{
		fullscreenflag = false;
	}

	if(!CreateGLWindow(TEXT("OpenGL Framework"), 16, fullscreenflag))
	{
		return 0;
	}
	
	ShowWindow(hWnd, SW_SHOW);								//只是CreateWindow的话,窗口只是在内存中创建好了,只有调用了ShowWindow后才会显示窗口
															//ShowWindow函数在显示窗口时,会发送第一个WM_SIZE消息;但具体是在ShowWindow最后返回前还是其他什么时候,我还不知道
	//UpdateWindow(hWnd);										//UpdateWindow函数会发送WM_PAINT消息来更新窗口客户区
															//由于我们用了OpenGL,所以这里可以不需调用UpdateWindow
	
	while(!quit)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))		//提取消息,如果此时没有消息,则不等待,立即返回false
		{
			if(msg.message == WM_QUIT)
			{
				quit = TRUE;
			}
			else
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		else
		{
			DrawGLScene();
			SwapBuffers( hDC );
		}

	}

	DestroyGLWindow();
	return msg.wParam;
}

//窗口过程
LRESULT CALLBACK WndProc( HWND		hwnd,					//窗口句柄 
						  UINT		message,				//接收到的消息
						  WPARAM	wParam,					//消息的附加参数
						  LPARAM	lParam)					//消息的附加参数
{
	switch(message)
	{
	case WM_SIZE:											//窗口大小改变,或者第一次显现窗口时(ShowWindow),都将发送该消息
		ResizeGLScene(LOWORD(lParam), HIWORD(lParam));
		return 0;
	
	case WM_DESTROY:
		PostQuitMessage(0);									//发送WM_QUIT消息
		return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

//初始化OpenGL一些属性
void InitGL()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_FLAT);
}

//根据窗口大小的变化
void ResizeGLScene(int width, int height)
{
	glViewport(0, 0, (GLsizei)width, (GLsizei)height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
	glMatrixMode(GL_MODELVIEW);
}

//OpenGL绘图
void DrawGLScene()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0, 1.0, 1.0);
	glLoadIdentity();
	gluLookAt(	0.0, 0.0, 5.0,
				0.0, 0.0, 0.0, 
				0.0, 1.0, 0.0);
	glScalef(1.0, 2.0, 1.0);
	glBegin(GL_TRIANGLES);
		glVertex3f( 0.0,  1.0,  0.0);
		glVertex3f(-1.0, -1.0,  0.0);
		glVertex3f( 1.0, -1.0,  0.0);
	glEnd();
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值