diff EXCLUDE/GLTSF/src/Window.cpp @ 4730:6032ada8b9e5

Adding GLTSF (somewhat based on SFML, no actual TSF code yet)
author dewyatt
date Tue, 25 May 2010 18:53:09 -0400
parents
children 0c7c67d4e6ee
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EXCLUDE/GLTSF/src/Window.cpp	Tue May 25 18:53:09 2010 -0400
@@ -0,0 +1,263 @@
+#include "Window.hpp"
+
+#pragma comment(lib, "opengl32.lib")
+
+const wchar_t *Window::Window_Class_Name = L"GLTSF";
+
+Window::Window() : my_Handle(0),
+				   my_Device_Context(0),
+				   my_GL_Context(0),
+				   my_Class_Registered(false),
+				   my_Listener(0)
+{
+
+}
+
+Window::~Window()
+{
+	Finalize();
+}
+
+void Window::Initialize(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen)
+{
+	Finalize();
+
+	my_Video_Mode = Mode;
+	if (!my_Video_Mode.Is_Valid())
+		throw std::runtime_error("Invalid video mode");
+
+	my_Fullscreen = Fullscreen;
+	Register_Class();
+	Create_Window(Title, Mode, Fullscreen);
+}
+
+void Window::Finalize()
+{
+	Destroy_Window();
+	Unregister_Class();
+}
+
+void Window::Set_Listener(Window_Listener *Listener)
+{
+	my_Listener = Listener;
+}
+
+void Window::Register_Class()
+{
+	WNDCLASSEXW Window_Class = {0};
+	Window_Class.cbSize = sizeof(Window_Class);
+	Window_Class.style = 0;
+	Window_Class.lpfnWndProc = &Window::Window_Procedure;
+	Window_Class.cbClsExtra = 0;
+	Window_Class.cbWndExtra = 0;
+	Window_Class.hInstance = GetModuleHandle(NULL);
+	Window_Class.hIcon = NULL;
+	Window_Class.hCursor = NULL;
+	Window_Class.hbrBackground = NULL;
+	Window_Class.lpszMenuName = NULL;
+	Window_Class.lpszClassName = Window_Class_Name;
+	Window_Class.hIconSm = NULL;
+	if (0 == RegisterClassExW(&Window_Class))
+		throw std::runtime_error("Failed to register window class");
+
+	my_Class_Registered = true;
+}
+
+void Window::Unregister_Class()
+{
+	if (my_Class_Registered)
+	{
+		if (0 == UnregisterClassW(Window_Class_Name, GetModuleHandle(NULL)))
+			printf("Warning: Failed to unregister window class\n");
+
+		my_Class_Registered = false;
+	}
+}
+
+void Window::Create_Window(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen)
+{
+	HDC Screen_DC = GetDC(NULL);
+	int Left = (GetDeviceCaps(Screen_DC, HORZRES) - my_Video_Mode.Width) / 2;
+	int Top = (GetDeviceCaps(Screen_DC, VERTRES) - my_Video_Mode.Height) / 2;
+	int Width = my_Video_Mode.Width;
+	int Height = my_Video_Mode.Height;
+	ReleaseDC(NULL, Screen_DC);
+
+	DWORD Style = WS_OVERLAPPEDWINDOW;
+	if (!my_Fullscreen)
+	{
+		RECT Rect = {0, 0, Width, Height};
+		AdjustWindowRect(&Rect, Style, false);
+		Width = Rect.right - Rect.left;
+		Height = Rect.bottom - Rect.top;
+	}
+	my_Handle = CreateWindowW(Window_Class_Name, Title.c_str(), Style, Left, Top, Width, Height, NULL, NULL, GetModuleHandle(NULL), this);
+	if (!my_Handle)
+		throw std::runtime_error("Failed to create window");
+
+	if (Fullscreen)
+		Switch_To_Fullscreen(Mode);
+
+	Create_Context(Mode);
+
+	RECT Rect = {0};
+	GetClientRect(my_Handle, &Rect);
+	//TODO: ...
+}
+
+void Window::Destroy_Window()
+{
+	Destroy_Context();
+	if (my_Handle)
+	{
+		DestroyWindow(my_Handle);
+		my_Handle = 0;
+
+		if (my_Fullscreen)
+			ChangeDisplaySettings(NULL, 0);
+	}
+}
+
+void Window::Create_Context(const Video_Mode &Mode)
+{
+	my_Device_Context = GetDC(my_Handle);
+	if (!my_Device_Context)
+		throw std::runtime_error("Failed to get device context");
+
+	PIXELFORMATDESCRIPTOR Pixel_Descriptor = {0};
+	Pixel_Descriptor.nSize = sizeof(Pixel_Descriptor);
+	Pixel_Descriptor.nVersion = 1;
+	Pixel_Descriptor.iLayerType = PFD_MAIN_PLANE;
+	Pixel_Descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+	Pixel_Descriptor.iPixelType = PFD_TYPE_RGBA;
+	Pixel_Descriptor.cColorBits = static_cast<BYTE>(Mode.Bits_Per_Pixel);
+	Pixel_Descriptor.cDepthBits = 24;
+	Pixel_Descriptor.cStencilBits = 8;
+	Pixel_Descriptor.cAlphaBits = Mode.Bits_Per_Pixel == 32 ? 8 : 0;
+
+	int Best_Format = ChoosePixelFormat(my_Device_Context, &Pixel_Descriptor);
+	if (0 == Best_Format)
+		throw std::runtime_error("Failed to find suitable pixel format");
+
+	PIXELFORMATDESCRIPTOR Actual_Format = {0};
+	Actual_Format.nSize = sizeof(Actual_Format);
+	Actual_Format.nVersion = 1;
+	DescribePixelFormat(my_Device_Context, Best_Format, sizeof(Actual_Format), &Actual_Format);
+	if (!SetPixelFormat(my_Device_Context, Best_Format, &Actual_Format))
+		throw std::runtime_error("Failed to set device pixel format");
+
+	my_GL_Context = wglCreateContext(my_Device_Context);
+	if (!my_GL_Context)
+		throw std::runtime_error("Failed to create OpenGL context");
+
+	wglMakeCurrent(my_Device_Context, my_GL_Context);
+}
+
+void Window::Destroy_Context()
+{
+	if (my_GL_Context)
+	{
+		wglDeleteContext(my_GL_Context);
+		my_GL_Context = 0;
+	}
+	if (my_Device_Context)
+	{
+		ReleaseDC(my_Handle, my_Device_Context);
+		my_Device_Context = 0;
+	}
+}
+
+void Window::Switch_To_Fullscreen(const Video_Mode &Mode)
+{
+	DEVMODE Device_Mode = {0};
+	Device_Mode.dmSize = sizeof(Device_Mode);
+	Device_Mode.dmPelsWidth = Mode.Width;
+	Device_Mode.dmPelsHeight = Mode.Height;
+	Device_Mode.dmBitsPerPel = Mode.Bits_Per_Pixel;
+	Device_Mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
+
+	if (DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettings(&Device_Mode, CDS_FULLSCREEN))
+		throw std::runtime_error("Failed to change to fullscreen mode");
+
+	SetWindowLong(my_Handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
+	SetWindowLong(my_Handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
+
+	SetWindowPos(my_Handle, HWND_TOP, 0, 0, Mode.Width, Mode.Height, SWP_FRAMECHANGED);
+}
+
+LRESULT CALLBACK Window::Window_Procedure(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam)
+{
+	switch (Message)
+	{
+	case WM_CREATE:
+		{
+			LONG This = reinterpret_cast<LONG>(reinterpret_cast<CREATESTRUCT *>(lParam)->lpCreateParams);
+			SetWindowLongPtr(Handle, GWLP_USERDATA, This);
+			return 0;
+		}
+		break;
+	case WM_DESTROY:
+		PostQuitMessage(0);
+		return 0;
+		break;
+	default:
+		{
+			Window* Win = reinterpret_cast<Window *>(GetWindowLongPtr(Handle, GWLP_USERDATA));
+			if (Win)
+				return Win->Handle_Message(Handle, Message, wParam, lParam);
+		}
+		break;
+	}
+	return DefWindowProcW(Handle, Message, wParam, lParam);
+}
+
+#define Call_Listener(x)\
+	if (my_Listener) my_Listener->x
+
+LRESULT Window::Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam)
+{
+	switch (Message)
+	{
+	case WM_CLOSE:
+		Call_Listener(On_Close());
+		break;
+	case WM_KEYDOWN:
+		Call_Listener(On_Key_Down(wParam));
+		break;
+	case WM_KEYUP:
+		Call_Listener(On_Key_Up(wParam));
+		break;
+	default:
+		return DefWindowProcW(Handle, Message, wParam, lParam);
+		break;
+	}
+	return 0;
+}
+
+void Window::Show()
+{
+	if (my_Handle)
+		ShowWindow(my_Handle, SW_SHOW);
+}
+
+void Window::Hide()
+{
+	if (my_Handle)
+		ShowWindow(my_Handle, SW_HIDE);
+}
+
+void Window::Update()
+{
+	MSG Message = {0};
+	while (PeekMessageW(&Message, NULL, 0, 0, PM_REMOVE))
+	{
+		TranslateMessage(&Message);
+		DispatchMessageW(&Message);
+	}
+}
+
+void Window::Display()
+{
+	if (my_Device_Context && my_GL_Context)
+		SwapBuffers(my_Device_Context);
+}