charcoal/archive/Window.cpp
elipzer b494f68d0c A Working Triangle
Now using GLFW3 instead of the custom window class. This library
looks like it will make development much simpler and will make it
so that I am less worried about my windows code breaking. Currently
setup the http://antongerdelan.net/opengl/hellotriangle.html
tutorial in the MySimpleScene. Will probably create another scene
file to try to get the object oriented stuff working.
2018-09-05 16:26:50 -04:00

216 lines
3.9 KiB
C++

#include "Window.h"
#include <iostream>
#include <map>
#include "vec2.h"
namespace {
// Only one Window can be created per HWND
std::map<HWND, Window*> g_windows;
}
LRESULT CALLBACK main_wnd_proc(HWND h_wnd, UINT msg, WPARAM w_param, LPARAM l_param) {
auto w = g_windows.find(h_wnd);
if (w == g_windows.end())
{
return DefWindowProc(h_wnd, msg, w_param, l_param);
}
else
{
return w->second->wnd_proc(h_wnd, msg, w_param, l_param);
}
}
Window::Window(const char* class_name, HINSTANCE h_instance)
: m_class_name(class_name), m_h_instance(h_instance)
{
}
Window::~Window()
{
if (m_h_wnd != nullptr)
{
g_windows.erase(m_h_wnd);
}
}
LRESULT CALLBACK Window::wnd_proc(HWND h_wnd, UINT msg, WPARAM w_param, LPARAM l_param)
{
switch (msg)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
m_input_manager.key_down(l_param);
return DefWindowProc(h_wnd, msg, w_param, l_param);
case WM_KEYUP:
case WM_SYSKEYUP:
m_input_manager.key_up((unsigned long)l_param);
break;
case WM_LBUTTONDOWN:
m_input_manager.key_down(VK_LBUTTON);
break;
case WM_LBUTTONUP:
m_input_manager.key_up(VK_LBUTTON);
break;
case WM_RBUTTONDOWN:
m_input_manager.key_down(VK_RBUTTON);
break;
case WM_RBUTTONUP:
m_input_manager.key_up(VK_RBUTTON);
break;
case WM_MBUTTONDOWN:
m_input_manager.key_down(VK_MBUTTON);
break;
case WM_MBUTTONUP:
m_input_manager.key_up(VK_MBUTTON);
break;
case WM_MOUSEMOVE:
m_input_manager.mouse_move(ivec2(GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param)));
break;
case WM_MOUSEWHEEL:
m_input_manager.mouse_scroll(GET_WHEEL_DELTA_WPARAM(w_param) / WHEEL_DELTA);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(h_wnd, msg, w_param, l_param);
}
bool Window::register_class()
{
m_wc.style = 0;
m_wc.cbSize = sizeof(WNDCLASSEX);
m_wc.cbClsExtra = 0;
m_wc.cbWndExtra = 0;
m_wc.hInstance = m_h_instance;
m_wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
m_wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
m_wc.hCursor = LoadCursor(NULL, IDC_ARROW);
m_wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
m_wc.lpszClassName = m_class_name;
m_wc.lpszMenuName = NULL;
m_wc.lpfnWndProc = main_wnd_proc;
return RegisterClassEx(&m_wc);
}
bool Window::create_window(const char* title, int x, int y, int w, int h)
{
if (m_h_wnd != NULL)
{
g_windows.erase(m_h_wnd);
}
// Fix for window border with width and height
DWORD style = WS_POPUP | WS_VISIBLE | WS_SYSMENU;
RECT window_rect = { 0, 0, w, h };
AdjustWindowRect(&window_rect, style, false);
int width = window_rect.right - window_rect.left;
int height = window_rect.bottom - window_rect.top;
if (x == -1)
{
// Center x-position
x = GetSystemMetrics(SM_CXSCREEN) / 2 - width / 2;
}
if (y == -1)
{
// Center y-position
y = GetSystemMetrics(SM_CYSCREEN) / 2 - height / 2;
}
m_h_wnd = CreateWindow
(
m_class_name,
title,
style,
x, y,
width, height,
NULL,
NULL,
m_h_instance,
NULL
);
if (m_h_wnd != NULL)
{
m_h_dc = GetDC(m_h_wnd);
// TODO: Figure out why value_type is needed here...
g_windows.insert(std::map<HWND, Window*>::value_type(m_h_wnd, this));
return true;
}
else
{
return false;
}
}
MessageResponse Window::handle_message()
{
MSG msg = { 0 };
if (!PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
return NO_MESSAGE;
}
if (msg.message == WM_QUIT)
{
return QUIT_MESSAGE;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
return HANDLED_MESSAGE;
}
void Window::show(int cmd_show)
{
ShowWindow(m_h_wnd, cmd_show);
}
void Window::update()
{
UpdateWindow(m_h_wnd);
}
void Window::swap()
{
SwapBuffers(m_h_dc);
}
void Window::close()
{
CloseWindow(m_h_wnd);
}
void Window::set_h_glrc(HGLRC h_glrc)
{
m_h_glrc = h_glrc;
}
HWND Window::get_h_wnd()
{
return m_h_wnd;
}
HDC Window::get_h_dc()
{
return m_h_dc;
}
HGLRC Window::get_h_glrc()
{
return m_h_glrc;
}
const InputManager & Window::get_input_manager()
{
return m_input_manager;
}