OpenGL_2 OpenGL窗口

HGLRC hRC = NULL;
HDC	  hDC = NULL;
HWND hWnd = NULL;
HINSTANCE hInstance;
bool keys[256];
bool active = TRUE;
bool fullscreen = TRUE;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
	if (height == 0)
	{
		height = 1;
	}
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

int InitGL(GLvoid)
{
	glShadeModel(GL_SMOOTH);	//设置深度缓存
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);	//启用深度测试
	glDepthFunc(GL_LEQUAL);		//所作深度测试的类型
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	return TRUE;
}

int DrawGLScene(GLvoid)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除屏幕和深度缓存
	glLoadIdentity();	//重置当前的模型观察矩阵
	return TRUE;
}

GLvoid KillGLWindow(GLvoid)
{
	if (fullscreen)
	{
		ChangeDisplaySettings(NULL, 0);//如果全屏,切换回桌面
		ShowCursor(TRUE);//显示指针
	}
	if (hRC)//是否拥有OpenGL渲染描述表
	{
		if (!wglMakeCurrent(NULL, NULL))//是否能释放DC或RC描述表
		{
			MessageBox(NULL, L"fail to release DC or RC", L"error", MB_OK | MB_ICONINFORMATION);
		}
		if (!wglDeleteContext(hRC))//能否删除RC
		{
			MessageBox(NULL, L"fail to release RC", L"error", MB_OK | MB_ICONINFORMATION);
		}
		hRC = NULL;//RC释放为NULL
	}
	if (hDC && !ReleaseDC(hWnd, hDC))//能否释放DC
	{
		MessageBox(NULL, L"fail to release DC",L"error", MB_OK | MB_ICONINFORMATION);
		hDC = NULL;
	}
	if (hWnd && !DestroyWindow(hWnd))//能否销毁窗口
	{
		MessageBox(NULL, L"fail to destroy window",L"error",MB_OK | MB_ICONINFORMATION);
		hWnd = NULL;
	}
	if (!UnregisterClass("OpenG", hInstance))//能否注销类
	{
		MessageBox(NULL, L"fail to unregister window class",L"error", MB_OK | MB_ICONINFORMATION);
		hInstance = NULL;
	}
}

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
	GLuint PixelFormat;
	WNDCLASS wc;
	DWORD dwExStyle;
	DWORD dwStyle;
	RECT WindowRect;//取得矩形的左上角和右下角坐标值
	WindowRect.left = (long)0;
	WindowRect.right = (long)width;
	WindowRect.top = (long)0;
	WindowRect.bottom = (long)height;
	fullscreen = fullscreenflag;

	hInstance = GetModuleHandle(NULL);//取得窗口实例
	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;//移动时重画,并为窗口取得DC
	wc.lpfnWndProc(WNDPROC)WndProc;//	WndProc处理消息
	wc.cbClsExtra = 0;//无额外窗口数据
	wc.cbWndExtra = 0;//无额外窗口数据
	wc.hInstance = hInstance;//设置实例
	wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);//装入缺省图标
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);//装入鼠标指针
	wc.hbrBackground = NULL;//不需要背景
	wc.lpszMenuName = NULL;//不需要菜单
	wc.lpszClassName = "OpenG";

	if (!RegisterClass(&wc))//尝试注册窗口类
	{
		MessageBox(NULL, "注册窗口类失败", "错误", MB_OK | MB_ICONINFORMATION);
		return FALSE;
	}
	if (fullscreen)
	{
		DEVMODE dmScreenSettings;
		memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));//确保内存清空为零
		dmScreenSettings.dmSize = sizeof(dmScreenSettings);//devmode结构大小
		dmScreenSettings.dmPelsWidth = width;//所选屏幕宽度
		dmScreenSettings.dmPelsHeight = height;//所选屏幕高度
		dmScreenSettings.dmBitsPerPel = bits;//所选屏幕色彩深度
		dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

		if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
		{
			if (MessageBox(NULL, L"全屏模式在当前显卡上设置失败!\n使用窗口模式?", L"确认", MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
			{
				fullscreen = FALSE;
			}
			else
			{
				MessageBox(NULL, L"程序将被关闭", L"错误", MB_OK | MB_ICONSTOP);
				return FALSE;
			}
		}
	}
	if (fullscreen)//仍处于全屏模式?
	{
		dwExStyle = WS_EX_APPWINDOW;//拓展窗体风格
		dwStyle = WS_POPUP;//窗体风格
		ShowCursor(FALSE);
	}
	else
	{
		dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;//扩展窗体风格
		dwStyle = WS_OVERLAPPEDWINDOW;//窗体风格
	}
	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);//调整窗口达到真正要求的大小
	if (!hWnd = CreateWindowEx(dwExStyle,
		L"OpenG",
		title,
		WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle
		, 0, 0,
		WindowRect.right - WindowRect.left,
		WindowRect.bottom - WindowRect.top,
		NULL,
		NULL,
		hInstance,
		NULL))
	{
		KillGLWindows();
		MessageBox(NULL, L"不能创建一个设备描述表", L"错误", MB_OK | MB_ICONEXCLAMATION);
		return FALSE;
	}

	static PIXELFORMATDESCRIPTOR pfd =
	{
		sizeof(PIXELFORMATDESCRIPTOR),//上述格式描述符的大小
		1,//版本号
		PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA,
		bits,//选定色彩深度
		0,0,0,0,0,0,//忽略的色彩位
		0,//无Alpha缓存
		0,//shift+bit
		0,//无累加缓存
		0,0,0,0,//忽略聚集位
		16,//16位Z-缓存(深度缓存)
		0,//无蒙版缓存
		0,//无辅助缓存
		PFD_MAIN_PLANE,//主绘图层
		0,
		0,0,0//忽略层遮罩
	};

	if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd)))//windows找到相应的像素格式?
	{
		KillGLWindows();//重置显示区
		MessageBox(NULL, L"不能设置像素格式",L"错误",MB_OK | MB_ICONEXCLAMATION);
		return FALSE;
	}

	if (!SetPixelFormat(hDC, PixelFormat, &pfd))//能够设置像素格式吗
	{
		KillGLWindows();
		MessageBox(NULL, L"不能设置像素格式", L"错误", MB_OK | MB_ICONEXCLAMATION);
		return FALSE;
	}

	if (!(hRC = wglCreateContext(hRC)))
	{
		KillGLWindows();
		MessageBox(NULL, L"不能创建OpenGL渲染描述表", L"错误", MB_OK | MB_ICONEXCLAMATION);
		return FALSE;
	}

	if (!wglMakeCurrent(hDC, hRC))//尝试激活着色描述表
	{
		KillGLWindows();
		MessageBox(NULL, L"不能激活当前OpenGL渲染描述表", L"错误", MB_OK | MB_ICONEXCLAMATION);
		return FALSE;
	}

	ShowWindow(hWnd, SW_SHOW);//显示窗口
	SetForegroundWindow(hWnd);//略略提高优先级
	SetFocus(hWnd);//设置键盘的焦点至此窗口
	ReSizeGLScene(width, height);//设置透视GL屏幕

	if (!InitGL())//初始化新建的GL窗口
	{
		KillGLWindows();
		MessageBox(NULL, "", "", MB_OK | MB_ICONEXCLAMATION);
		return FALSE;
	}

	return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_ACTIVATE://监视窗口激活消息
	{
		if (!HIWORD(wParam))
		{
			active = TRUE;//程序处于激活状态
		}
		else
		{
			active = FALSE;//程序不再激活
		}
		return 0;
	}
	case WM_SYSCOMMAND://系统中断命令
	{
		switch (wParam)//检查系统调用
		{
		case SC_SCREENSAVE://屏保要运行
		case SC_MONITORPOWER://显示器进入节电模式
			return 0;
		}
		break;
	}
	case WM_CLOSE://收到close消息
	{
		PostQuitMessage(0);//发出退出消息
		return 0;
	}
	case WM_KEYDOWN://有键按下
	{
		keys[wParam] = TRUE;
		return 0;
	}
	case WM_KEYUP://有键释放
	{
		keys[wParam] = FALSE;
		return 0;
	}
	case WM_SIZE://调整OpenGL窗口
	{
		ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));
		return 0;
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
	
	default:
		break;
	}
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	MSG msg;
	BOOL done = FALSE;
	if (MessageBox(NULL, L"你想在全屏模式下运行吗", L"设置全屏模式", MB_YESNO | MB_ICONQUESTION) == IDNO)
	{
		fullscreen = FALSE;
	}
	if (!CreateGLWindow(L"OpenGL程序框架", 640, 480, 16, fullscreen))
	{
		return 0;
	}
	while (!done)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))//有消息在等待吗
		{
			if (msg.message == WM_QUIT)
			{
				done = TRUE;
			}
			else
			{
				TranslateMessage(&msg);//翻译消息
				DispatchMessage(&msg);//发送消息
			}
		}
		else
		{
			if (active)
			{
				if (keys[VK_ESCAPE])//ESC按下
				{
					done = TRUE;
				}
				else
				{
					DrawGLScene();
					SwapBuffers(hDC);
				}
				if (keys[VK_F1])//F1按下
				{
					keys[VK_F1] = FALSE;
					KillGLWindow();
					fullscreen = !fullscreen;
					if (!CreateGLWindow(L"OpenGL程序框架", 640, 480, 16, fullscreen))//重建OpenGL窗口
					{
						return 0;
					}
				}
			}
		}
	}

	KillGLWindow();
	return(msg.wParam);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值