When writing the X11 (linux) implementation there was a problem with X11 defining a "Display" type and we also have a Display class in the engine. So to fix that problem and minimize the risk for running into other name conflicts. We move everything from global namespace.
264 lines
No EOL
5.3 KiB
C++
264 lines
No EOL
5.3 KiB
C++
|
|
#include <Windows.h>
|
|
|
|
|
|
#include <Spectre/Display/Display.h>
|
|
#include <Spectre/System/SystemEvent.h>
|
|
#include <Spectre/System/Log.h>
|
|
#include "Win32Application.h"
|
|
#include "Win32Internal.h"
|
|
#include "Win32Display.h"
|
|
|
|
namespace sp {
|
|
|
|
#define WND_CLASSNAME "SPECTRE_WIN32_WNDCLASS"
|
|
|
|
static bool firstTime = true;
|
|
|
|
Win32Display::Win32Display() :
|
|
m_handle (NULL),
|
|
m_icon (0),
|
|
m_cursor (0),
|
|
m_inResizeModalLoop (false),
|
|
m_minSize (200, 200)
|
|
{
|
|
}
|
|
|
|
Win32Display::~Win32Display()
|
|
{
|
|
if (m_icon) {
|
|
DestroyIcon(m_icon);
|
|
}
|
|
|
|
if (m_handle) {
|
|
DestroyWindow(m_handle);
|
|
}
|
|
}
|
|
|
|
bool Win32Display::create(DisplayDescription description)
|
|
{
|
|
DWORD flags = getWin32Flags(description.decoration);
|
|
int x, y;
|
|
|
|
if (firstTime) {
|
|
registerClass();
|
|
firstTime = false;
|
|
}
|
|
|
|
centerWindow(x, y, description.mode.width, description.mode.height);
|
|
|
|
// Create window.
|
|
m_handle = CreateWindowExA(0, WND_CLASSNAME, "", flags,
|
|
x, y, description.mode.width, description.mode.height,
|
|
NULL, NULL, GetModuleHandle(NULL), (LPVOID) this);
|
|
|
|
if (!m_handle) {
|
|
log("Win32 - Could not create window: %s", Win32GetMessage(GetLastError()));
|
|
return false;
|
|
}
|
|
|
|
setSize(description.mode.width, description.mode.height);
|
|
|
|
// Store the size for use later.
|
|
m_size = getSize();
|
|
|
|
return true;
|
|
}
|
|
|
|
void Win32Display::destroy()
|
|
{
|
|
if (m_handle) {
|
|
DestroyWindow(m_handle);
|
|
m_handle = NULL;
|
|
}
|
|
}
|
|
|
|
void* Win32Display::getHandle() const
|
|
{
|
|
return m_handle;
|
|
}
|
|
|
|
bool Win32Display::isValid()
|
|
{
|
|
return m_handle != NULL;
|
|
}
|
|
|
|
void Win32Display::setSize(unsigned int width, unsigned int height)
|
|
{
|
|
int w, h;
|
|
RECT rect = {0, 0, width, height};
|
|
AdjustWindowRect(&rect, GetWindowLong(m_handle, GWL_STYLE), false);
|
|
|
|
w = rect.right - rect.left;
|
|
h = rect.bottom - rect.top;
|
|
|
|
::SetWindowPos(m_handle, NULL, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER);
|
|
}
|
|
|
|
Vector2u Win32Display::getSize() const
|
|
{
|
|
RECT rect;
|
|
Vector2u size;
|
|
|
|
if (GetClientRect(m_handle, &rect)) {
|
|
size.x = rect.right - rect.left;
|
|
size.y = rect.bottom - rect.top;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
void Win32Display::setPosition(unsigned int x, unsigned int y)
|
|
{
|
|
::SetWindowPos(m_handle, NULL, x, y, 0, 0, SWP_NOSIZE);
|
|
}
|
|
|
|
void Win32Display::setCaption(const std::string& caption)
|
|
{
|
|
::SetWindowText(m_handle, caption.c_str());
|
|
}
|
|
|
|
void Win32Display::showCursor(bool value)
|
|
{
|
|
if (value) {
|
|
m_cursor = ::LoadCursor(NULL, IDC_ARROW);
|
|
} else {
|
|
m_cursor = 0;
|
|
}
|
|
|
|
::SetCursor(m_cursor);
|
|
}
|
|
|
|
void Win32Display::setIcon(const std::string& icon)
|
|
{
|
|
HICON hIcon = (HICON) ::LoadImage(0, icon.c_str(), IMAGE_ICON,
|
|
0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);
|
|
|
|
if (hIcon) {
|
|
|
|
if (m_icon) {
|
|
DestroyIcon(m_icon);
|
|
}
|
|
m_icon = hIcon;
|
|
|
|
::SendMessage(m_handle, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
|
|
::SendMessage(m_handle, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
|
|
}
|
|
}
|
|
|
|
void Win32Display::registerClass()
|
|
{
|
|
WNDCLASSA wndcl;
|
|
|
|
ZeroMemory(&wndcl, sizeof(wndcl));
|
|
|
|
wndcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
|
|
wndcl.lpfnWndProc = Win32Display::staticWndProc;
|
|
wndcl.hInstance = ::GetModuleHandle(NULL);
|
|
wndcl.lpszClassName = WND_CLASSNAME;
|
|
|
|
::RegisterClass(&wndcl);
|
|
}
|
|
|
|
DWORD Win32Display::getWin32Flags(unsigned int flags)
|
|
{
|
|
DWORD win32_flags = WS_VISIBLE;
|
|
|
|
if (flags == DisplayDecorate::None) {
|
|
win32_flags |= WS_POPUP;
|
|
} else {
|
|
if (flags & DisplayDecorate::Menu) {
|
|
win32_flags |= WS_CAPTION | WS_MINIMIZEBOX;
|
|
}
|
|
|
|
if (flags & DisplayDecorate::Resize) {
|
|
win32_flags |= WS_THICKFRAME | WS_MAXIMIZEBOX;
|
|
}
|
|
|
|
if (flags & DisplayDecorate::Close) {
|
|
win32_flags |= WS_SYSMENU;
|
|
}
|
|
}
|
|
return win32_flags;
|
|
}
|
|
|
|
void Win32Display::centerWindow(int &x, int &y, int width, int height)
|
|
{
|
|
x = (::GetSystemMetrics(SM_CXSCREEN) - width) / 2;
|
|
y = (::GetSystemMetrics(SM_CYSCREEN) - height) / 2;
|
|
}
|
|
|
|
void Win32Display::processResizeMessage(const Vector2u& new_size)
|
|
{
|
|
// Check if the size has actually changed.
|
|
if (m_size != new_size) {
|
|
|
|
// Update the size and notify the higher layer.
|
|
m_size = new_size;
|
|
onReshape(m_size.x, m_size.y);
|
|
}
|
|
}
|
|
|
|
void Win32Display::processMessage(UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(message) {
|
|
case WM_SETCURSOR :
|
|
if (LOWORD(lParam) == HTCLIENT) {
|
|
::SetCursor(m_cursor);
|
|
}
|
|
break;
|
|
case WM_DESTROY :
|
|
destroy();
|
|
PostQuitMessage(0);
|
|
break;
|
|
case WM_SETFOCUS :
|
|
OutputDebugString("WM_SETFOCUS\n");
|
|
break;
|
|
case WM_KILLFOCUS :
|
|
OutputDebugString("WM_KILLFOCUS\n");
|
|
break;
|
|
case WM_SIZE :
|
|
|
|
if (!m_inResizeModalLoop && (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)) {
|
|
processResizeMessage(getSize());
|
|
}
|
|
break;
|
|
case WM_GETMINMAXINFO :
|
|
{
|
|
MINMAXINFO* info = (MINMAXINFO*)lParam;
|
|
info->ptMinTrackSize.x = m_minSize.x;
|
|
info->ptMinTrackSize.y = m_minSize.y;
|
|
info->ptMaxTrackSize.x = 99999;
|
|
info->ptMaxTrackSize.y = 99999;
|
|
break;
|
|
}
|
|
case WM_ENTERSIZEMOVE :
|
|
m_inResizeModalLoop = true;
|
|
break;
|
|
case WM_EXITSIZEMOVE :
|
|
m_inResizeModalLoop = false;
|
|
processResizeMessage(getSize());
|
|
break;
|
|
}
|
|
}
|
|
|
|
LRESULT CALLBACK Win32Display::staticWndProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
Win32Display *display;
|
|
|
|
if (message == WM_NCCREATE) {
|
|
|
|
LONG_PTR ptr = (LONG_PTR) ((LPCREATESTRUCT)lParam)->lpCreateParams;
|
|
::SetWindowLong(handle, GWL_USERDATA, ptr);
|
|
|
|
display = (Win32Display*) ptr;
|
|
} else {
|
|
display = (Win32Display*) ::GetWindowLong(handle, GWL_USERDATA);
|
|
}
|
|
|
|
if (display) {
|
|
display->processMessage(message, wParam, lParam);
|
|
}
|
|
return DefWindowProc(handle, message, wParam, lParam);
|
|
}
|
|
|
|
} // namespace sp
|