Last active
October 14, 2015 00:57
-
-
Save maxdeliso/4282902 to your computer and use it in GitHub Desktop.
w32 application template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * basic opengl and windows integration | |
| * see: http://www.opengl.org/archives/resources/faq/technical/gettingstarted.htm | |
| * for the proper link flags | |
| * Max DeLiso | |
| */ | |
| #include <Windows.h> | |
| #include <GL/gl.h> | |
| #include <GL/glu.h> | |
| #include <cassert> | |
| #include <iostream> | |
| #include <fstream> | |
| inline BOOL debugging() { | |
| #ifdef _DEBUG | |
| return true; | |
| #else | |
| return false; | |
| #endif | |
| } | |
| /* class prototype */ | |
| class EngineSingleton; | |
| class GFX_Context { | |
| friend class EngineSingleton; | |
| HWND ghWnd; | |
| HDC ghDC; | |
| HGLRC ghRC; | |
| GFX_Context() { | |
| ghWnd = 0; | |
| ghDC = 0; | |
| ghRC = 0; | |
| } | |
| public: | |
| void init(const HWND& hwnd); | |
| }; | |
| class WIN_Context { | |
| friend class EngineSingleton; | |
| HINSTANCE hInstance; | |
| WIN_Context(HINSTANCE inst) { | |
| hInstance = inst; | |
| } | |
| public: | |
| void messageLoop(); | |
| BOOL registerWindowClass(); | |
| BOOL createMainWindow(int nCmdShow, GFX_Context* gfxContextPtr); | |
| BOOL bSetupPixelFormat(HDC hdc); | |
| static LRESULT CALLBACK windowProcedure(HWND hwnd, UINT uint, WPARAM wParam, LPARAM lParam); | |
| static const TCHAR windowClassName[]; | |
| static const TCHAR windowTitleName[]; | |
| static const int windowInitialWidth; | |
| static const int windowInitialHeight; | |
| }; | |
| /* see http://stackoverflow.com/questions/2496918/singleton-pattern-in-c */ | |
| class EngineSingleton | |
| { | |
| public: | |
| static EngineSingleton& instance(); | |
| int runWithInstance(HINSTANCE hInstance, int nCmdShow); | |
| private: | |
| /* singleton boilerplate */ | |
| static void destroy(); | |
| EngineSingleton(); | |
| ~EngineSingleton(); | |
| EngineSingleton(EngineSingleton const&) {} | |
| EngineSingleton& operator=(EngineSingleton const&) {} | |
| static EngineSingleton* gInstance; | |
| }; | |
| EngineSingleton& EngineSingleton::instance() { | |
| if (gInstance == NULL) { gInstance = new EngineSingleton(); } | |
| return *gInstance; | |
| } | |
| int EngineSingleton::runWithInstance(HINSTANCE hInstance, int nCmdShow) { | |
| GFX_Context* gfxContext = new GFX_Context(); | |
| WIN_Context* winContext = new WIN_Context(hInstance); | |
| if( winContext->registerWindowClass() && | |
| winContext->createMainWindow(nCmdShow, gfxContext) ) { | |
| winContext->messageLoop(); | |
| } else { | |
| return EXIT_FAILURE; | |
| } | |
| delete winContext; | |
| delete gfxContext; | |
| return EXIT_SUCCESS; | |
| } | |
| EngineSingleton* EngineSingleton::gInstance = NULL; | |
| EngineSingleton::EngineSingleton() { | |
| atexit(&destroy); | |
| /* TODO: setup global state*/ | |
| } | |
| EngineSingleton::~EngineSingleton() { | |
| /* TODO: tear-down global state */ | |
| } | |
| void EngineSingleton::destroy() { | |
| delete gInstance; | |
| gInstance = NULL; | |
| } | |
| void GFX_Context::init(const HWND& hwnd) { | |
| ghWnd = hwnd; | |
| ghDC = GetDC(hwnd); | |
| ghRC = wglCreateContext(ghDC); | |
| wglMakeCurrent(ghDC, ghRC); | |
| RECT clientRect; | |
| GetClientRect(hwnd, &clientRect); | |
| const GLubyte* gluVersion = gluGetString(GLU_VERSION); | |
| const GLubyte* gluExtensions = gluGetString(GLU_EXTENSIONS); | |
| } | |
| const TCHAR WIN_Context::windowClassName[] = TEXT("testClass"); | |
| const TCHAR WIN_Context::windowTitleName[] = TEXT("testTitle"); | |
| const int WIN_Context::windowInitialWidth = 512; | |
| const int WIN_Context::windowInitialHeight = 316; | |
| int CALLBACK WinMain( | |
| HINSTANCE hInstance, | |
| HINSTANCE hPrevInstance, | |
| LPSTR lpCmdLine, | |
| int nCmdShow) { | |
| UNREFERENCED_PARAMETER(hPrevInstance); | |
| UNREFERENCED_PARAMETER(lpCmdLine); | |
| EngineSingleton& engine = EngineSingleton::instance(); | |
| if(debugging()) { | |
| BOOL allocOk = AllocConsole(); | |
| assert(allocOk); | |
| std::ofstream conOut("con"); | |
| conOut << "DEBUGGING: ON"; | |
| conOut.close(); | |
| } | |
| return engine.runWithInstance(hInstance, nCmdShow); | |
| } | |
| void WIN_Context::messageLoop() { | |
| MSG msg; | |
| BOOL bRet; | |
| while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) { | |
| if( bRet == -1 ) { | |
| /* TODO: signal error */ | |
| } else { | |
| TranslateMessage(&msg); | |
| DispatchMessage(&msg); | |
| } | |
| } | |
| } | |
| BOOL WIN_Context::registerWindowClass() { | |
| WNDCLASSEX wcx; | |
| wcx.cbSize = sizeof(wcx); | |
| wcx.style = CS_HREDRAW | CS_VREDRAW; | |
| wcx.lpfnWndProc = windowProcedure; | |
| wcx.cbClsExtra = 0; | |
| wcx.cbWndExtra = 0; | |
| wcx.hInstance = hInstance; | |
| wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION); | |
| wcx.hCursor = LoadCursor(NULL, IDC_ARROW); | |
| wcx.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); | |
| wcx.lpszMenuName = NULL; | |
| wcx.lpszClassName = windowClassName; | |
| wcx.hIconSm = NULL; | |
| return RegisterClassEx(&wcx); | |
| } | |
| BOOL WIN_Context::createMainWindow( | |
| int nCmdShow, | |
| GFX_Context* gfxContextPtr) { | |
| HWND hwnd; | |
| hwnd = CreateWindowEx( | |
| 0, | |
| windowClassName, | |
| windowTitleName, | |
| WS_OVERLAPPEDWINDOW, | |
| CW_USEDEFAULT, | |
| CW_USEDEFAULT, | |
| windowInitialWidth, | |
| windowInitialHeight, | |
| (HWND) NULL, | |
| (HMENU) NULL, | |
| hInstance, | |
| (LPVOID) gfxContextPtr); | |
| if (!hwnd) { | |
| return FALSE; | |
| } | |
| ShowWindow(hwnd, nCmdShow); | |
| UpdateWindow(hwnd); | |
| return TRUE; | |
| } | |
| BOOL WIN_Context::bSetupPixelFormat(HDC hdc) { | |
| PIXELFORMATDESCRIPTOR pfd; | |
| int pixelformat; | |
| pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); | |
| pfd.nVersion = 1; | |
| pfd.dwFlags = | |
| PFD_DRAW_TO_WINDOW | | |
| PFD_SUPPORT_OPENGL | | |
| PFD_DOUBLEBUFFER; | |
| pfd.dwLayerMask = PFD_MAIN_PLANE; | |
| pfd.iPixelType = PFD_TYPE_COLORINDEX; | |
| pfd.cColorBits = 24; | |
| pfd.cDepthBits = 32; | |
| pfd.cAccumBits = 0; | |
| pfd.cStencilBits = 0; | |
| pixelformat = ChoosePixelFormat(hdc, &pfd); | |
| if ( (pixelformat = ChoosePixelFormat(hdc, &pfd)) == 0 ) { | |
| return FALSE; | |
| } | |
| if (SetPixelFormat(hdc, pixelformat, &pfd) == FALSE) { | |
| return FALSE; | |
| } | |
| return TRUE; | |
| } | |
| LRESULT CALLBACK WIN_Context::windowProcedure( | |
| HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { | |
| static GFX_Context* gfxContext = NULL; | |
| if(debugging()) { | |
| std::ofstream conOut("con"); | |
| conOut << "event " << msg << std::endl; | |
| conOut.close(); | |
| } | |
| switch(msg) { | |
| case WM_CREATE: | |
| gfxContext = (GFX_Context*) ((CREATESTRUCT*)lParam)->lpCreateParams; | |
| gfxContext->init(hwnd); | |
| /* initialize opengl projection matrix */ | |
| /* initialize data */ | |
| /* create widgets */ | |
| return DefWindowProc(hwnd, msg, wParam, lParam); | |
| case WM_PAINT: | |
| /* draw widgets */ | |
| return DefWindowProc(hwnd, msg, wParam, lParam); | |
| case WM_CLOSE: | |
| if(!DestroyWindow(hwnd)) { | |
| /* TODO: signal error */ | |
| } else { | |
| /* destroy data */ | |
| PostQuitMessage(EXIT_SUCCESS); | |
| } | |
| return 0; | |
| default: | |
| return DefWindowProc(hwnd, msg, wParam, lParam); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment