#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <string>
#include <iostream>
#include "qr_common_vectors.h"
#include "qr_events.h"
#include "qr_driver_base.h"
#include "qr_opengl_common.h"
#include "qr_win32_driver.h"
namespace qr
{
namespace internal
{
driver *driver_instance = NULL; //hack to alow access to class instance from windows callback
/*********************************************************************/
driver::driver(
vector2d_i viewp_aspr, float project_width, bool fullscreen,
vector2d_i size_hint, bool vsync, int multisample)
{
// store a copy of the aspect ratio
this->viewp_aspr = viewp_aspr;
this->project_width = project_width;
this->multisample = multisample;
this->vsync = vsync;
this->fullscreen = fullscreen;
// Check if there is already a driver instance
if(driver_instance == NULL)
driver_instance=this;
else
{
std::cout<<"A driver already exists\n";
throw 1;
}
// Find the current screen resolution
vector2d_i screen_size = get_screen_res();
// If alt res is 0 or full screen mode is enabled, set the window resolution to
// the screen resolution
if((size_hint.X == 0 && size_hint.Y == 0) || this->fullscreen == true)
this->window_size = screen_size;
else
this->window_size = size_hint;
// Set up window
create_window();
}
/*********************************************************************/
void driver::create_window()
{
// Register window class
register_class();
vector2d_i screen_res = this->get_screen_res();
set_window_size(screen_res);
if(this->fullscreen)
enable_fullscreen();
make_window();
//create device context
this->h_dc=GetDC(h_wnd);
//get device context
this->h_dc=GetDC(h_wnd);
set_pix_format();
// Create and activate GL context
this->h_rc=wglCreateContext(h_dc);
wglMakeCurrent(h_dc,h_rc);
// Make the window visible
ShowWindow(h_wnd,SW_SHOW);
SetForegroundWindow(h_wnd);
SetFocus(h_wnd);
// Resize gl viewport
resize_viewport();
set_projection();
init();
}
/*********************************************************************/
void driver::destroy_window()
{
if (fullscreen)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);
}
if (h_rc)
{
wglMakeCurrent(NULL,NULL);
wglDeleteContext(h_rc);
}
if (h_dc)
{
ReleaseDC(h_wnd,h_dc);
}
if (h_wnd)
{
DestroyWindow(h_wnd);
}
UnregisterClass("Quad-ren",h_instance);
}
/*********************************************************************/
bool driver::get_event(event **nevent)
{
MSG msg;
*nevent = NULL;
if (PeekMessage(&msg,h_wnd,0,0,PM_REMOVE))
{
std::cout<<"msg"<<msg.message<<" \n";
if (msg.message == WM_QUIT)
{
std::cout<<"quit\n";
return false;
}
else if (msg.message == WM_KEYDOWN)
{
std::cout<<"key pressed"<<msg.wParam<<"\n";
*(nevent) = new keydown_event(msg.wParam);
}
else if (msg.message == WM_KEYUP)
{
std::cout<<"key released"<<msg.wParam<<"\n";
*(nevent) = new keyup_event(msg.wParam);
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// std::cout<<nevent;
return true;
}
/*********************************************************************/
LRESULT CALLBACK driver::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) // Check For Windows Messages
{
case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}
case WM_CLOSE: // Did We Receive A Close Message?
{
std::cout<<"quit\n";
PostQuitMessage(0); // Send A Quit Message
return 0;
}
case WM_PAINT:
{
driver_instance->draw();
return 0;
}
case WM_SIZE:
{
driver_instance->set_window_size(qr::vector2d_i(LOWORD(lParam), HIWORD(lParam)));
driver_instance->resize_viewport();
driver_instance->draw();
return 0;
}
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
/*********************************************************************/
void driver::register_class()
{
// Set up window class
this->h_instance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = this->h_instance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "Quad-ren";
if(!RegisterClass(&wc))
{
std::cout<<"Failed to register window class\n";
throw int(1);
}
}
/*********************************************************************/
void driver::make_window()
{
int dw_ex_style = 0;
int dw_style = 0;
if (fullscreen) // Are We Still In Fullscreen Mode?
{
dw_ex_style = WS_EX_APPWINDOW; // Window Extended Style
dw_style = WS_POPUP; // Windows Style
ShowCursor(false); // Hide Mouse Pointer
}
else
{
dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dw_style = WS_OVERLAPPEDWINDOW; // Windows Style
}
// Create window
if (!(h_wnd=CreateWindowEx(
dw_ex_style, // Extended Style For The Window
"Quad-ren", // Class Name
"", // Window title
dw_style |
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
this->window_size.X, // Calculate Window Width
this->window_size.Y, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
h_instance, // Instance
NULL))) // Don't Pass Anything To WM_CREATE
{
std::cout<<"Failed to create window\n";
throw int(1);
}
}
/*********************************************************************/
void driver::set_pix_format()
{
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
24, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
unsigned int PixelFormat = ChoosePixelFormat(h_dc,&pfd);
SetPixelFormat(h_dc, PixelFormat,&pfd);
}
/*********************************************************************/
void driver::enable_fullscreen()
{
if (fullscreen)
{
vector2d_i screen_res = this->get_screen_res();
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = screen_res.X; // Selected Screen Width
dmScreenSettings.dmPelsHeight = screen_res.Y; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = 32; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
throw 1;
//return FALSE; // Return FALSE
}
}
}
}
/*********************************************************************/
void driver::set_window_size(vector2d_i new_window_size)
{
RECT window_rect;
window_rect.left = 0;
window_rect.right = new_window_size.X;
window_rect.top = 0;
window_rect.bottom = new_window_size.Y;
// Adjust window size to account for borders.
AdjustWindowRectEx(&window_rect, WS_OVERLAPPEDWINDOW, false, WS_EX_APPWINDOW);
this->window_size.X = window_rect.right - window_rect.left;
this->window_size.Y = window_rect.bottom - window_rect.top;
}
}
}
int main()
{
qr::internal::driver *drv = new qr::internal::driver(qr::vector2d_i(16,9), 10);
qr::event *nevent;
while(drv->get_event(&nevent))
{
if(nevent != NULL && nevent->get_type() == qr::EV_KEYDOWN)
{
qr::keydown_event *devent = (qr::keydown_event*) nevent;
if(devent->get_keysym() == VK_SPACE)
drv->toggle_fullscreen();
}
drv->draw();
}
}