Part1:win32 程序框架

来自:http://www.codeproject.com/Articles/27219/TetroGL-An-OpenGL-Game-Tutorial-in-C-for-Win32-Pla

main.cpp

#include <Windows.h>
#include "Exception.h"
#include "Application.h"

int WINAPI WinMain(HINSTANCE Instance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT)
{
    try
    {
        // Create the application class, 
        // parse the command line and
        // start the app.
        CApplication theApp(Instance);
        theApp.ParseCmdLine(lpCmdLine);
        theApp.Run();
    }
    catch(CException& e)
    {
        MessageBox(NULL,e.what(),"Error",MB_OK|MB_ICONEXCLAMATION);
    }

    return 0;
}

Application.h 

#ifndef _APPLICATION_H_
#define _APPLICATION_H_

#include <windows.h>

// The application class, which simply wraps the message queue and process
// the command line.
class CApplication
{
public:
    CApplication(HINSTANCE hInstance);
    ~CApplication();

    // Parses the command line to see if the application
    // should be in fullscreen mode.
    void ParseCmdLine(LPSTR lpCmdLine);
    // Creates the main window and start the message loop.
    void Run();

private:
    static const int FRAME_TIME = 75;

    HINSTANCE m_hInstance;
    // Specifies if the application has to be started in fullscreen
    // mode. This option is supplied through the command line
    // ("-fullscreen" option).
    bool m_bFullScreen;
};

#endif  // _APPLICATION_H_

#include "Application.h"
#include "MainWindow.h"
#include <string>

// Disable the warnings for deprecated functions (strtok and stricmp)
#pragma warning(disable:4996)

CApplication::CApplication(HINSTANCE hInstance)
  : m_hInstance(hInstance), m_bFullScreen(false)
{
}

CApplication::~CApplication()
{
}

void CApplication::ParseCmdLine(LPSTR lpCmdLine)
{
    LPSTR lpArgument = strtok(lpCmdLine," ");
    while (lpArgument)
    {
        if (stricmp(lpArgument,"-fullscreen") == 0)
            m_bFullScreen = true;
        lpArgument = strtok(NULL," ");
    }
}

void CApplication::Run()
{
    // Create the main window first
    CMainWindow mainWindow(800,600,m_bFullScreen);

    MSG Message;
    Message.message = ~WM_QUIT;
    DWORD dwNextDeadLine = GetTickCount() + FRAME_TIME;
    DWORD dwSleep = FRAME_TIME;
    bool bUpdate = false;

    // Loop until a WM_QUIT message is received
    while (Message.message != WM_QUIT)
    {
        // Wait until a message comes in or until the timeout expires. The
        // timeout is recalculated so that this function will return at
        // least every FRAME_TIME msec.
        DWORD dwResult = MsgWaitForMultipleObjectsEx(0,NULL,dwSleep,QS_ALLEVENTS,0);
        if (dwResult != WAIT_TIMEOUT)
        {
            // If the function returned with no timeout, it means that at 
            // least one message has been received, so process all of them.
            while (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
            {
                // If a message was waiting in the message queue, process it
                TranslateMessage(&Message);
                DispatchMessage(&Message);
            }

            // If the current time is close (or past) to the 
            // deadline, the application should be processed.
            if (GetTickCount() >= dwNextDeadLine)
                bUpdate = true;
            else
                bUpdate = false;
        }
        else
            // On a timeout, the application should be processed.
            bUpdate = true;

        // Check if the application should be processed
        if (bUpdate)
        {
            DWORD dwCurrentTime = GetTickCount();
            // Update the main window
            mainWindow.Update(dwCurrentTime);
            // Draw the main window
            mainWindow.Draw();

            dwNextDeadLine = dwNextDeadLine + FRAME_TIME;
        }

        // Process the sleep time, which is the difference
        // between the current time and the next deadline.
        dwSleep =  dwNextDeadLine - GetCurrentTime();
        // If the sleep time is larger than the frame time,
        // it probably means that the processing was stopped 
        // (e.g. the window was being moved,...), so recalculate
        // the next deadline.
        if (dwSleep>FRAME_TIME)
        {
            dwSleep = FRAME_TIME;
            dwNextDeadLine = GetCurrentTime() + FRAME_TIME;
        }
    }
}

MainWindow.h

#ifndef _MAINWINDOW_H_
#define _MAINWINDOW_H_

#include <Windows.h>
#include "GL/gl.h"

// The main window class. It wraps the HANDLE of the window and initializes the 
// openGL rendering context. It is also in charge of processing the different
// event messages.
class CMainWindow
{
public:
	CMainWindow(int iWidth, int iHeight, bool bFullScreen);
	~CMainWindow();

	// Called by the application class to update the game logic
	void Update(DWORD dwCurrentTime);
	// Called by the application class when the window need to be redrawn.
	void Draw();

private:
	// Register the window class with the correct window procedure (OnEvent)
	void RegisterWindowClass();
	// Create the rendering context used by OpenGL
	void CreateContext();
	// Initialize openGL
	void InitGL();

	// Called when a WM_SIZE message is received
	void OnSize(GLsizei width, GLsizei height);

	// Static function which will be the window procedure callback
    static LRESULT CALLBACK OnEvent(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam);
	// Processes the messages that were received in OnEvent.
	void ProcessEvent(UINT Message, WPARAM wParam, LPARAM lParam);

	// The window handle
	HWND	m_hWindow;
	// The window device context
    HDC     m_hDeviceContext;
	// The openGL context.
    HGLRC   m_hGLContext;    

	// Specifies if the window is fullscreen.
	bool m_bFullScreen;
};

#endif  // _MAINWINDOW_H_

MainWindow.cpp

#include "MainWindow.h"
#include "Exception.h"

#define WINDOW_CLASSNAME    "Tutorial1"  // Window class name

CMainWindow::CMainWindow(int iWidth, int iHeight, bool bFullScreen) 
  :  m_hWindow(NULL), m_hDeviceContext(NULL), m_hGLContext(NULL), 
     m_bFullScreen(bFullScreen)
{
	RegisterWindowClass();

	RECT WindowRect;
	WindowRect.top = WindowRect.left = 0;
	WindowRect.right = iWidth;
	WindowRect.bottom = iHeight;

	// Window Extended Style
	DWORD dwExStyle = 0;	
	// Windows Style
	DWORD dwStyle = 0;		

	if (m_bFullScreen)
	{
		DEVMODE dmScreenSettings;
		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));	
		dmScreenSettings.dmSize = sizeof(dmScreenSettings);		
		dmScreenSettings.dmPelsWidth	= iWidth;			
		dmScreenSettings.dmPelsHeight	= iHeight;		
		dmScreenSettings.dmBitsPerPel	= 32;		
		dmScreenSettings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;

		// Change the display settings to fullscreen. On error, throw 
		// an exception.
		if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)
				!= DISP_CHANGE_SUCCESSFUL)
		{
			throw CException("Unable to swith to fullscreen mode");
		}

		dwExStyle = WS_EX_APPWINDOW;	
		dwStyle = WS_POPUP;		
		// In fullscreen mode, we hide the cursor.
		ShowCursor(FALSE);
	}
	else
	{
		dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
		dwStyle = WS_OVERLAPPEDWINDOW;	
	}

	// Adjust the window to the true requested size
	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		
	// Now create the main window
    m_hWindow = CreateWindowEx(dwExStyle,TEXT(WINDOW_CLASSNAME), 
							 TEXT("Tutorial1"), 
							 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle,
							 0, 0, WindowRect.right-WindowRect.left, 
							 WindowRect.bottom-WindowRect.top, 
							 NULL, NULL, 
							 GetModuleHandle(NULL), 
							 this);
	if (m_hWindow==NULL)
		throw CException("Cannot create the main window");

	CreateContext();
	InitGL();
	ShowWindow(m_hWindow,SW_SHOW);
	// Call OnSize manually because in fullscreen mode it will be 
	// called only when the window is created (which is too early
	// because OpenGL is not initialized yet).
	OnSize(iWidth,iHeight);
}

CMainWindow::~CMainWindow()
{
	if (m_bFullScreen)
	{
		// Remove the full screen setting
		ChangeDisplaySettings(NULL,0);
		ShowCursor(TRUE);	
	}

	if (m_hGLContext)
	{
		// Make the rendering context not current
		wglMakeCurrent(NULL,NULL);
		// Delete the OpenGL rendering context
		wglDeleteContext(m_hGLContext);
		m_hGLContext = NULL;
	}
	if (m_hDeviceContext)
	{
		// Release the device context
		ReleaseDC(m_hWindow,m_hDeviceContext);
		m_hDeviceContext = NULL;
	}

	// Finally, destroy our main window and unregister the
	// window class.
    DestroyWindow(m_hWindow);
    UnregisterClass(TEXT(WINDOW_CLASSNAME), GetModuleHandle(NULL));
}

LRESULT CMainWindow::OnEvent(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam)
{
	if (Message == WM_NCCREATE)
	{
        // Get the creation parameters.
		CREATESTRUCT* pCreateStruct = reinterpret_cast<CREATESTRUCT*>(lParam);

        // Set as the "user data" parameter of the window
        SetWindowLongPtr(Handle, GWLP_USERDATA, 
						 reinterpret_cast<long>(pCreateStruct->lpCreateParams));
	}

    // Get the CMainWindow instance corresponding to the window handle
    CMainWindow* pWindow = reinterpret_cast<CMainWindow*>
		(GetWindowLongPtr(Handle, GWLP_USERDATA));
	if (pWindow)
		pWindow->ProcessEvent(Message,wParam,lParam);

    return DefWindowProc(Handle, Message, wParam, lParam);
}

void CMainWindow::ProcessEvent(UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
        // Quit when we close the main window
        case WM_CLOSE :
            PostQuitMessage(0);
			break;
		case WM_SIZE:
			OnSize(LOWORD(lParam),HIWORD(lParam));
			break;
        case WM_KEYDOWN :
            break;
        case WM_KEYUP :
            break;
    }
}

void CMainWindow::RegisterWindowClass()
{
    WNDCLASS WindowClass;
    WindowClass.style         = 0;
    WindowClass.lpfnWndProc   = &CMainWindow::OnEvent;
    WindowClass.cbClsExtra    = 0;
    WindowClass.cbWndExtra    = 0;
    WindowClass.hInstance     = GetModuleHandle(NULL);
    WindowClass.hIcon         = NULL;
    WindowClass.hCursor       = 0;
    WindowClass.hbrBackground = 0;
    WindowClass.lpszMenuName  = NULL;
    WindowClass.lpszClassName = WINDOW_CLASSNAME;

    RegisterClass(&WindowClass);
}

void CMainWindow::CreateContext()
{
	// Describes the pixel format of the drawing surface
	PIXELFORMATDESCRIPTOR pfd;
	memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	pfd.nVersion = 1;	// Version Number
	pfd.dwFlags = PFD_DRAW_TO_WINDOW |	// Draws to a window
				  PFD_SUPPORT_OPENGL |	// The format must support OpenGL
				  PFD_DOUBLEBUFFER;		// Support for double buffering
	pfd.iPixelType = PFD_TYPE_RGBA;		// Uses an RGBA pixel format
	pfd.cColorBits = 32;				// 32 bits colors

	if (!(m_hDeviceContext=GetDC(m_hWindow)))	
		throw CException("Unable to create rendering context");

	int PixelFormat;
	// Do Windows find a matching pixel format ?
	if (!(PixelFormat=ChoosePixelFormat(m_hDeviceContext,&pfd)))				
		throw CException("Unable to create rendering context");
	// Set the new pixel format
	if(!SetPixelFormat(m_hDeviceContext,PixelFormat,&pfd))			
		throw CException("Unable to create rendering context");
	// Create the OpenGL rendering context
	if (!(m_hGLContext=wglCreateContext(m_hDeviceContext)))	
		throw CException("Unable to create rendering context");
	// Activate the rendering context
	if(!wglMakeCurrent(m_hDeviceContext,m_hGLContext))
		throw CException("Unable to create rendering context");						
}

void CMainWindow::InitGL()
{
	// Enable 2D texturing
	glEnable(GL_TEXTURE_2D);
	// Choose a smooth shading model
    glShadeModel(GL_SMOOTH);
	// Set the clear color to black
	glClearColor(0.0, 0.0, 0.0, 0.0);

	// Enable the alpha test. This is needed 
	// to be able to have images with transparent 
	// parts.
	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER, 0.0f);
}

void CMainWindow::OnSize(GLsizei width, GLsizei height)
{
	// Sets the size of the OpenGL viewport
    glViewport(0,0,width,height);

	// Select the projection stack and apply 
	// an orthographic projection
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0.0,width,height,0.0,-1.0,1.0);
	glMatrixMode(GL_MODELVIEW);
}

void CMainWindow::Update(DWORD dwCurrentTime)
{
}

void CMainWindow::Draw()
{
	// Clear the buffer
	glClear(GL_COLOR_BUFFER_BIT);

	// Here goes the drawing code
	glBegin(GL_QUADS);
		glColor3f(1.0,0.0,0.0);		glVertex3i(50,200,0);
		glColor3f(0.0,1.0,0.0);		glVertex3i(250,200,0);
		glColor3f(0.0,0.0,1.0);		glVertex3i(250,350,0);
		glColor3f(1.0,1.0,1.0);		glVertex3i(50,350,0);
	glEnd();

	glBegin(GL_TRIANGLES);
		glColor3f(1.0,0.0,0.0);  glVertex3i(400,350,0);
		glColor3f(0.0,1.0,0.0);  glVertex3i(500,200,0);
		glColor3f(0.0,0.0,1.0);  glVertex3i(600,350,0);
	glEnd();

	SwapBuffers(m_hDeviceContext);
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值