#include "Window.h" #include #include #include "vec2.h" namespace { // Only one Window can be created per HWND std::map 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::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; }