#define WIDTH	640														//Height of the screen in pixels
#define HEIGHT	480														//Width of the screen in pixels

#include <windows.h>														//Windows headerfile
#include <gl/gl.h>														//OpenGL Headerfile
#include <gl/glu.h>														//OpenGL utilities

//FUNCTION DECLARATIONS
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);							//Processes Messages
VOID EnableOpenGL(HWND hWnd,HDC * hDC,HGLRC * hRC);										//Enables OpenGL
VOID DisableOpenGL(HWND hWnd,HDC hDC,HGLRC hRC);										//Disables OpenGL - releases device and rendering context
DEVMODE dmScreenSettings;

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
		   LPSTR lpCmdLine,int iCmdShow){
	WNDCLASS	wc;
	HWND		hWnd;													//Window handle
	HDC		hDC;													//Device context handle
	HGLRC		hRC;													//Rendering context handle
	MSG		msg;													//Message datatype
	BOOL		bQuit=FALSE;												//Boolean value. If bQuit==TRUE, then exit

	//REGISTER WINDOW CLASS
	wc.style		=	CS_OWNDC;										//Creates a private DC for the Window (DC is not shared across applications)
	wc.lpfnWndProc		=	WndProc;										//Handles messages
	wc.cbClsExtra		=	0;
	wc.cbWndExtra		=	0;
	wc.hInstance		=	hInstance;
	wc.hIcon		=	LoadIcon(NULL,IDI_APPLICATION);
	wc.hCursor		=	LoadCursor(NULL,IDC_ARROW);
	wc.hbrBackground	=	NULL;											//No background brush is required in OpenGL
	wc.lpszMenuName		=	NULL;
	wc.lpszClassName	=	"FullScreen";
	RegisterClass(&wc);													//Register the class

	hWnd=CreateWindowEx(WS_EX_APPWINDOW,"FullScreen","FullScreen",WS_POPUP|WS_CLIPSIBLINGS,					//Attempt to create the window
		0,0,WIDTH,HEIGHT,NULL,NULL,hInstance,NULL);
																//Device Mode
	memset(&dmScreenSettings,0,sizeof(dmScreenSettings));									//Makes Sure Memory's Cleared
	dmScreenSettings.dmSize		= sizeof(dmScreenSettings);								//Size Of The Devmode Structure
	dmScreenSettings.dmPelsWidth	= WIDTH;										//Selected Screen Width
	dmScreenSettings.dmPelsHeight	= HEIGHT;										//Selected Screen Height
	dmScreenSettings.dmBitsPerPel	= 16;											//Selected Bits Per Pixel
	dmScreenSettings.dmFields	= DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
	
	ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN);								//Attempt to enter full screen device mode

	EnableOpenGL(hWnd,&hDC,&hRC);												//Enable OpenGL for the window
	while(!bQuit){														//Program main loop
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)){									//Check for quit message
			if(msg.message==WM_QUIT) bQuit = TRUE;									//If WM_QUIT then break the main loop
			else{
				TranslateMessage(&msg);										//Translates keystrokes that may be specific to this application
				DispatchMessage(&msg);										//Pass message to Windows, WndProc, etc
			}
		}
		else{
////////////////OPENGL CODING STARTS HERE////////////////

			glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);							//Clear screen with current color
				
			glLoadIdentity();
			glBegin(GL_TRIANGLES);											//Start Drawing A Triangle
				glColor3f(1.0f,0.0f,0.0f);									//Set Top Point Of Triangle To Red
				glVertex3f( 0.0f, 1.0f, 0.0f);									//First Point Of The Triangle
				glColor3f(0.0f,1.0f,0.0f);									//Set Left Point Of Triangle To Green
				glVertex3f(-1.0f,-1.0f, 0.0f);									//Second Point Of The Triangle
				glColor3f(0.0f,0.0f,1.0f);									//Set Right Point Of Triangle To Blue
				glVertex3f( 1.0f,-1.0f, 0.0f);									//Third Point Of The Triangle
			glEnd();												//Done Drawing The Triangle
			SwapBuffers(hDC);											//Swap virtual screen to physical screen

/////////////////OPENGL CODING ENDS HERE/////////////////
		}
	}
	ChangeDisplaySettings(NULL,0);												//Change display settings back to desktop mode
	DisableOpenGL(hWnd,hDC,hRC);												//Shutdown OpenGL
	DestroyWindow(hWnd);													//Destroy the window explicitly
	return msg.wParam;													//Return back to the desktop
}

// Window Procedure (Process window messages)
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){
	if(message==WM_CREATE) return 0;
	else if(message==WM_CLOSE){
		PostQuitMessage(0);
		return 0;
	}
	else if(message==WM_DESTROY) return 0;
	else if(message==WM_KEYDOWN){
		if(wParam==VK_ESCAPE){
			PostQuitMessage(0);
			return 0;
		}
		return 0;
	}
	else return DefWindowProc(hWnd,message,wParam,lParam);									//If message wasn't processed, return it to Windows
}

//Enables OpenGL
VOID EnableOpenGL(HWND hWnd,HDC *hDC,HGLRC *hRC){
	PIXELFORMATDESCRIPTOR pfd;
	int format;
	*hDC=GetDC(hWnd);													// get the device context (DC)

	//Set the pixel format for the DC
	memset(&pfd,0,sizeof(pfd));
	pfd.nSize			= sizeof(pfd);										//Size of the pfd
	pfd.nVersion		= 1;												//Always equals 1
	pfd.dwFlags			= PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;				//Pixel format: is used to draw to window, needs to support OpenGL, has double buffering capabilities
	pfd.iPixelType		= PFD_TYPE_RGBA;
	pfd.cColorBits		= 24;												//24 bit color buffer
	pfd.cDepthBits		= 16;												//16 bit depth buffer

	format = ChoosePixelFormat(*hDC,&pfd);
	SetPixelFormat(*hDC,format,&pfd);											//Set the pixel format
 
	*hRC=wglCreateContext(*hDC);												//Create rendering context
	wglMakeCurrent(*hDC,*hRC);												//Enable rendering context
}

// Disable OpenGL
VOID DisableOpenGL(HWND hWnd,HDC hDC,HGLRC hRC){
	wglMakeCurrent(NULL,NULL);												//Release the rendering context
	wglDeleteContext(hRC);
	ReleaseDC(hWnd,hDC);													//Release the device context
}