dolphin/Source/Plugins/Plugin_VideoOGL/Src/Win32Window.cpp

804 lines
24 KiB
C++

#include "Win32Window.h"
// Static member data
unsigned int Win32Window::ourWindowCount = 0;
const char* Win32Window::ourClassName = _T("DolphinEmuWnd");
Win32Window* Win32Window::ourFullscreenWindow = NULL;
Win32Window::Win32Window() : GLWindow(),
myHandle (NULL),
myCallback (0),
myCursor (NULL),
myIcon (NULL),
myKeyRepeatEnabled (true),
myIsCursorIn (false)
{
// Register the window class at first call
if (ourWindowCount == 0)
RegisterWindowClass();
// Use small dimensions
//SetWinSize(1, 1);
// Create the rendering window
if (!(myHandle = CreateWindow(ourClassName, _T(""), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
GetXwin(), GetYwin(), NULL, NULL, myhInstance, this))) {
PanicAlert("Error creating GL Window");
}
ShowWindow(myHandle, SW_SHOW);
// Create the rendering context
if (myHandle)
{
VideoMode Mode;
Mode.Width = GetXwin();
Mode.Height = GetYwin();
Mode.BitsPerPixel = 32;
Mode.DepthBits = 24;
Mode.StencilBits = 8;
Mode.AntialiasingLevel = 0;
CreateContext(Mode);
// Don't activate by default
//SetNotActive();
}
}
Win32Window::~Win32Window()
{
// Destroy the custom icon, if any
if (myIcon)
DestroyIcon(myIcon);
if (!myCallback)
{
// Destroy the window
if (myHandle)
DestroyWindow(myHandle);
// Decrement the window count
ourWindowCount--;
// Unregister window class if we were the last window
if (ourWindowCount == 0)
UnregisterClass(ourClassName, GetModuleHandle(NULL));
}
else
{
// The window is external : remove the hook on its message callback
SetWindowLongPtr(myHandle, GWLP_WNDPROC, myCallback);
}
}
void Win32Window::SwapBuffers()
{
if (myDeviceContext && myGLContext)
::SwapBuffers(myDeviceContext);
}
void Win32Window::SetWindowText(const char *text)
{
::SetWindowText(GetWnd(), text);
}
void Win32Window::ShowMouseCursor(bool Show)
{
if (Show)
myCursor = LoadCursor(NULL, IDC_ARROW);
else
myCursor = NULL;
SetCursor(myCursor);
}
bool Win32Window::PeekMessages()
{
// We update the window only if we own it
if (!myCallback)
{
MSG Message;
while (PeekMessage(&Message, myHandle, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
}
return true; // I don't know why this is bool...
}
void Win32Window::Update()
{
// We just check all of our events here
// TODO
PeekMessages();
eventHandler->Update();
updateDim();
}
bool Win32Window::MakeCurrent()
{
if (myDeviceContext && myGLContext && (wglGetCurrentContext() != myGLContext))
{
wglMakeCurrent(myDeviceContext, myGLContext);
return true;
}
else
return false;
}
void Win32Window::RegisterWindowClass()
{
WNDCLASS WindowClass;
myhInstance = GetModuleHandle(NULL);
WindowClass.style = CS_OWNDC;
WindowClass.lpfnWndProc = &Win32Window::GlobalOnEvent;
WindowClass.cbClsExtra = 0;
WindowClass.cbWndExtra = 0;
WindowClass.hInstance = myhInstance;
WindowClass.hIcon = NULL;
WindowClass.hCursor = 0;
WindowClass.hbrBackground = 0;
WindowClass.lpszMenuName = NULL;
WindowClass.lpszClassName = ourClassName;
if (!RegisterClass(&WindowClass))
ERROR_LOG("Failed To Register The Window Class\n");
}
void Win32Window::SwitchToFullscreen(const VideoMode& Mode)
{
DEVMODE DevMode;
DevMode.dmSize = sizeof(DEVMODE);
DevMode.dmPelsWidth = Mode.Width;
DevMode.dmPelsHeight = Mode.Height;
DevMode.dmBitsPerPel = Mode.BitsPerPixel;
DevMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
// Apply fullscreen mode
if (ChangeDisplaySettings(&DevMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
ERROR_LOG("Failed to change display mode for fullscreen\n");
return;
}
// Change window style (no border, no titlebar, ...)
SetWindowLong(myHandle, GWL_STYLE, WS_POPUP);
SetWindowLong(myHandle, GWL_EXSTYLE, WS_EX_APPWINDOW);
// And resize it so that it fits the entire screen
SetWindowPos(myHandle, HWND_TOP, 0, 0, Mode.Width, Mode.Height, SWP_FRAMECHANGED);
ShowWindow(myHandle, SW_SHOW);
// Set "this" as the current fullscreen window
ourFullscreenWindow = this;
// SetPixelFormat can fail (really ?) if window style doesn't contain these flags
long Style = GetWindowLong(myHandle, GWL_STYLE);
SetWindowLong(myHandle, GWL_STYLE, Style | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
}
//VideoMode Win32Window::GetSupportedVideoModes(std::vector<VideoMode>& Modes)
//{
// // First, clear array to fill
// Modes.clear();
//
// // Enumerate all available video modes for primary display adapter
// DEVMODE Win32Mode;
// Win32Mode.dmSize = sizeof(DEVMODE);
// for (int Count = 0; EnumDisplaySettings(NULL, Count, &Win32Mode); ++Count)
// {
// // Convert to sfVideoMode
// VideoMode Mode(Win32Mode.dmPelsWidth, Win32Mode.dmPelsHeight, Win32Mode.dmBitsPerPel);
//
// // Add it only if it is not already in the array
// if (std::find(Modes.begin(), Modes.end(), Mode) == Modes.end())
// Modes.push_back(Mode);
// }
//}
void Win32Window::CreateContext(VideoMode& Mode)
{
// TESTING
Mode.DepthBits = 24;
Mode.StencilBits = 8;
//Mode.AntialiasingLevel = 4;
// Get the device context attached to the window
myDeviceContext = GetDC(myHandle);
if (myDeviceContext == NULL)
{
ERROR_LOG("Failed to get device context of window -- cannot create OpenGL context\n");
return;
}
// Let's find a suitable pixel format -- first try with antialiasing
int BestFormat = 0;
if (Mode.AntialiasingLevel > 0)
{
// Get the wglChoosePixelFormatARB function (it is an extension)
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB"));
// Define the basic attributes we want for our window
int IntAttributes[] =
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_SAMPLE_BUFFERS_ARB, (Mode.AntialiasingLevel ? GL_TRUE : GL_FALSE),
WGL_SAMPLES_ARB, Mode.AntialiasingLevel,
0, 0
};
// Let's check how many formats are supporting our requirements
int Formats[128];
UINT NbFormats;
float FloatAttributes[] = {0, 0};
bool IsValid = wglChoosePixelFormatARB(myDeviceContext, IntAttributes, FloatAttributes, sizeof(Formats) / sizeof(*Formats), Formats, &NbFormats) != 0;
if (!IsValid || (NbFormats == 0))
{
if (Mode.AntialiasingLevel > 2)
{
// No format matching our needs : reduce the multisampling level
char errMsg[256];
sprintf(errMsg, "Failed to find a pixel format supporting %u antialiasing levels ; trying with 2 levels\n", Mode.AntialiasingLevel);
ERROR_LOG(errMsg);
Mode.AntialiasingLevel = IntAttributes[1] = 2;
IsValid = wglChoosePixelFormatARB(myDeviceContext, IntAttributes, FloatAttributes, sizeof(Formats) / sizeof(*Formats), Formats, &NbFormats) != 0;
}
if (!IsValid || (NbFormats == 0))
{
// Cannot find any pixel format supporting multisampling ; disabling antialiasing
ERROR_LOG("Failed to find a pixel format supporting antialiasing ; antialiasing will be disabled\n");
Mode.AntialiasingLevel = 0;
}
}
// Get the best format among the returned ones
if (IsValid && (NbFormats > 0))
{
int BestScore = 0xFFFF;
for (UINT i = 0; i < NbFormats; ++i)
{
// Get the current format's attributes
PIXELFORMATDESCRIPTOR Attribs;
Attribs.nSize = sizeof(PIXELFORMATDESCRIPTOR);
Attribs.nVersion = 1;
DescribePixelFormat(myDeviceContext, Formats[i], sizeof(PIXELFORMATDESCRIPTOR), &Attribs);
// Evaluate the current configuration
int Color = Attribs.cRedBits + Attribs.cGreenBits + Attribs.cBlueBits + Attribs.cAlphaBits;
int Score = abs(static_cast<int>(Mode.BitsPerPixel - Color)) + // The EvaluateConfig function
abs(static_cast<int>(Mode.DepthBits - Attribs.cDepthBits)) +
abs(static_cast<int>(Mode.StencilBits - Attribs.cStencilBits));
// Keep it if it's better than the current best
if (Score < BestScore)
{
BestScore = Score;
BestFormat = Formats[i];
}
}
}
}
// Find a pixel format with no antialiasing, if not needed or not supported
if (BestFormat == 0)
{
// Setup a pixel format descriptor from the rendering settings
PIXELFORMATDESCRIPTOR PixelDescriptor;
ZeroMemory(&PixelDescriptor, sizeof(PIXELFORMATDESCRIPTOR));
PixelDescriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
PixelDescriptor.nVersion = 1;
PixelDescriptor.iLayerType = PFD_MAIN_PLANE;
PixelDescriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
PixelDescriptor.iPixelType = PFD_TYPE_RGBA;
PixelDescriptor.cColorBits = static_cast<BYTE>(Mode.BitsPerPixel);
PixelDescriptor.cDepthBits = static_cast<BYTE>(Mode.DepthBits);
PixelDescriptor.cStencilBits = static_cast<BYTE>(Mode.StencilBits);
// Get the pixel format that best matches our requirements
BestFormat = ChoosePixelFormat(myDeviceContext, &PixelDescriptor);
if (BestFormat == 0)
{
ERROR_LOG("Failed to find a suitable pixel format for device context -- cannot create OpenGL context\n");
return;
}
}
// Extract the depth and stencil bits from the chosen format
PIXELFORMATDESCRIPTOR ActualFormat;
ActualFormat.nSize = sizeof(PIXELFORMATDESCRIPTOR);
ActualFormat.nVersion = 1;
DescribePixelFormat(myDeviceContext, BestFormat, sizeof(PIXELFORMATDESCRIPTOR), &ActualFormat);
Mode.DepthBits = ActualFormat.cDepthBits;
Mode.StencilBits = ActualFormat.cStencilBits;
// Set the chosen pixel format
if (!SetPixelFormat(myDeviceContext, BestFormat, &ActualFormat))
{
ERROR_LOG("Failed to set pixel format for device context -- cannot create OpenGL context\n");
return;
}
// Create the OpenGL context from the device context
myGLContext = wglCreateContext(myDeviceContext);
if (myGLContext == NULL)
{
ERROR_LOG("Failed to create an OpenGL context for this window\n");
return;
}
// Share display lists with other contexts
HGLRC CurrentContext = wglGetCurrentContext();
if (CurrentContext)
wglShareLists(CurrentContext, myGLContext);
// Activate the context
MakeCurrent();
// Enable multisampling
if (Mode.AntialiasingLevel > 0)
glEnable(GL_MULTISAMPLE_ARB);
}
void Win32Window::Cleanup()
{
// Restore the previous video mode (in case we were running in fullscreen)
if (ourFullscreenWindow == this)
{
ChangeDisplaySettings(NULL, 0);
ourFullscreenWindow = NULL;
}
// Unhide the mouse cursor (in case it was hidden)
ShowMouseCursor(true);
//GetProperty(OGL_HIDECURSOR)
// Destroy the OpenGL context
if (myGLContext)
{
// Unbind the context before destroying it
//SetNotActive();
wglDeleteContext(myGLContext);
myGLContext = NULL;
}
if (myDeviceContext)
{
ReleaseDC(myHandle, myDeviceContext);
myDeviceContext = NULL;
}
}
////////////////////////////////////////////////////////////
/// Process a Win32 Event
////////////////////////////////////////////////////////////
void Win32Window::ProcessEvent(UINT Message, WPARAM WParam, LPARAM LParam)
{
// Don't process any message until window is created
if (myHandle == NULL)
return;
switch (Message)
{
// Destroy Event
case WM_DESTROY :
{
// Here we must cleanup resources !
Cleanup();
break;
}
// Set cursor Event
case WM_SETCURSOR :
{
// The mouse has moved, if the cursor is in our window we must refresh the cursor
if (LOWORD(LParam) == HTCLIENT)
SetCursor(myCursor);
break;
}
case WM_CLOSE :
{
sf::Event Evt;
Evt.Type = sf::Event::Closed;
eventHandler->addEvent(&Evt);
break;
}
// Resize Event
case WM_SIZE :
{
// Update window size
RECT Rect;
GetClientRect(myHandle, &Rect);
SetWinSize(Rect.right - Rect.left, Rect.bottom - Rect.top);
sf::Event Evt;
Evt.Type = sf::Event::Resized;
Evt.Size.Width = GetXwin();
Evt.Size.Height = GetYwin();
eventHandler->addEvent(&Evt);
break;
}
// Gain focus Event
case WM_SETFOCUS :
{
sf::Event Evt;
Evt.Type = sf::Event::GainedFocus;
eventHandler->addEvent(&Evt);
break;
}
// Lost focus Event
case WM_KILLFOCUS :
{
sf::Event Evt;
Evt.Type = sf::Event::LostFocus;
eventHandler->addEvent(&Evt);
break;
}
// Text Event
case WM_CHAR :
{
sf::Event Evt;
Evt.Type = sf::Event::TextEntered;
Evt.Text.Unicode = static_cast<u32>(WParam);
eventHandler->addEvent(&Evt);
break;
}
// Keydown Event
case WM_KEYDOWN :
case WM_SYSKEYDOWN :
{
if (myKeyRepeatEnabled || ((LParam & (1 << 30)) == 0))
{
sf::Event Evt;
Evt.Type = sf::Event::KeyPressed;
Evt.Key.Code = (WParam == VK_SHIFT) ? GetShiftState(true) : VirtualKeyCodeToSF(WParam, LParam);
Evt.Key.Alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
Evt.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
Evt.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
eventHandler->addEvent(&Evt);
}
break;
}
// Keyup Event
case WM_KEYUP :
case WM_SYSKEYUP :
{
sf::Event Evt;
Evt.Type = sf::Event::KeyReleased;
Evt.Key.Code = (WParam == VK_SHIFT) ? GetShiftState(false) : VirtualKeyCodeToSF(WParam, LParam);
Evt.Key.Alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
Evt.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
Evt.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
eventHandler->addEvent(&Evt);
break;
}
// Mouse wheel Event
case WM_MOUSEWHEEL :
{
sf::Event Evt;
Evt.Type = sf::Event::MouseWheelMoved;
Evt.MouseWheel.Delta = static_cast<s16>(HIWORD(WParam)) / 120;
eventHandler->addEvent(&Evt);
break;
}
// Mouse left button down Event
case WM_LBUTTONDOWN :
{
sf::Event Evt;
Evt.Type = sf::Event::MouseButtonPressed;
Evt.MouseButton.Button = sf::Mouse::Left;
Evt.MouseButton.X = LOWORD(LParam);
Evt.MouseButton.Y = HIWORD(LParam);
eventHandler->addEvent(&Evt);
break;
}
// Mouse left button up Event
case WM_LBUTTONUP :
{
sf::Event Evt;
Evt.Type = sf::Event::MouseButtonReleased;
Evt.MouseButton.Button = sf::Mouse::Left;
Evt.MouseButton.X = LOWORD(LParam);
Evt.MouseButton.Y = HIWORD(LParam);
eventHandler->addEvent(&Evt);
break;
}
// Mouse right button down Event
case WM_RBUTTONDOWN :
{
sf::Event Evt;
Evt.Type = sf::Event::MouseButtonPressed;
Evt.MouseButton.Button = sf::Mouse::Right;
Evt.MouseButton.X = LOWORD(LParam);
Evt.MouseButton.Y = HIWORD(LParam);
eventHandler->addEvent(&Evt);
break;
}
// Mouse right button up Event
case WM_RBUTTONUP :
{
sf::Event Evt;
Evt.Type = sf::Event::MouseButtonReleased;
Evt.MouseButton.Button = sf::Mouse::Right;
Evt.MouseButton.X = LOWORD(LParam);
Evt.MouseButton.Y = HIWORD(LParam);
eventHandler->addEvent(&Evt);
break;
}
// Mouse wheel button down Event
case WM_MBUTTONDOWN :
{
sf::Event Evt;
Evt.Type = sf::Event::MouseButtonPressed;
Evt.MouseButton.Button = sf::Mouse::Middle;
Evt.MouseButton.X = LOWORD(LParam);
Evt.MouseButton.Y = HIWORD(LParam);
eventHandler->addEvent(&Evt);
break;
}
// Mouse wheel button up Event
case WM_MBUTTONUP :
{
sf::Event Evt;
Evt.Type = sf::Event::MouseButtonReleased;
Evt.MouseButton.Button = sf::Mouse::Middle;
Evt.MouseButton.X = LOWORD(LParam);
Evt.MouseButton.Y = HIWORD(LParam);
eventHandler->addEvent(&Evt);
break;
}
// Mouse X button down Event
case WM_XBUTTONDOWN :
{
sf::Event Evt;
Evt.Type = sf::Event::MouseButtonPressed;
Evt.MouseButton.Button = HIWORD(WParam) == XBUTTON1 ? sf::Mouse::XButton1 : sf::Mouse::XButton2;
Evt.MouseButton.X = LOWORD(LParam);
Evt.MouseButton.Y = HIWORD(LParam);
eventHandler->addEvent(&Evt);
break;
}
// Mouse X button up Event
case WM_XBUTTONUP :
{
sf::Event Evt;
Evt.Type = sf::Event::MouseButtonReleased;
Evt.MouseButton.Button = HIWORD(WParam) == XBUTTON1 ? sf::Mouse::XButton1 : sf::Mouse::XButton2;
Evt.MouseButton.X = LOWORD(LParam);
eventHandler->addEvent(&Evt);
break;
}
// Mouse move Event
case WM_MOUSEMOVE :
{
// Check if we need to generate a MouseEntered Event
if (!myIsCursorIn)
{
TRACKMOUSEEVENT MouseEvent;
MouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
MouseEvent.hwndTrack = myHandle;
MouseEvent.dwFlags = TME_LEAVE;
TrackMouseEvent(&MouseEvent);
myIsCursorIn = true;
sf::Event Evt;
Evt.Type = sf::Event::MouseEntered;
eventHandler->addEvent(&Evt);
}
sf::Event Evt;
Evt.Type = sf::Event::MouseMoved;
Evt.MouseMove.X = LOWORD(LParam);
Evt.MouseMove.Y = HIWORD(LParam); // (shuffle2) Added this, check to see if it's good
eventHandler->addEvent(&Evt);
break;
}
// Mouse leave Event
case WM_MOUSELEAVE :
{
myIsCursorIn = false;
sf::Event Evt;
Evt.Type = sf::Event::MouseLeft;
eventHandler->addEvent(&Evt);
break;
}
}
}
///////////////////////////////////////////////////////////
/// Check the state of the shift keys on a key sf::Event,
/// and return the corresponding SF key code
////////////////////////////////////////////////////////////
sf::Key::Code Win32Window::GetShiftState(bool KeyDown)
{
static bool LShiftPrevDown = false;
static bool RShiftPrevDown = false;
bool LShiftDown = (HIWORD(GetAsyncKeyState(VK_LSHIFT)) != 0);
bool RShiftDown = (HIWORD(GetAsyncKeyState(VK_RSHIFT)) != 0);
sf::Key::Code Code = sf::Key::Code(0);
if (KeyDown)
{
if (!LShiftPrevDown && LShiftDown) Code = sf::Key::LShift;
else if (!RShiftPrevDown && RShiftDown) Code = sf::Key::RShift;
}
else
{
if (LShiftPrevDown && !LShiftDown) Code = sf::Key::LShift;
else if (RShiftPrevDown && !RShiftDown) Code = sf::Key::RShift;
}
LShiftPrevDown = LShiftDown;
RShiftPrevDown = RShiftDown;
return Code;
}
///////////////////////////////////////////////////////////
/// Convert a Win32 virtual key code to a SFML key code
////////////////////////////////////////////////////////////
sf::Key::Code Win32Window::VirtualKeyCodeToSF(WPARAM VirtualKey, LPARAM Flags)
{
switch (VirtualKey)
{
// VK_SHIFT is handled by the GetShiftState function
case VK_MENU : return (Flags & (1 << 24)) ? sf::Key::RAlt : sf::Key::LAlt;
case VK_CONTROL : return (Flags & (1 << 24)) ? sf::Key::RControl : sf::Key::LControl;
case VK_LWIN : return sf::Key::LSystem;
case VK_RWIN : return sf::Key::RSystem;
case VK_APPS : return sf::Key::Menu;
case VK_OEM_1 : return sf::Key::SemiColon;
case VK_OEM_2 : return sf::Key::Slash;
case VK_OEM_PLUS : return sf::Key::Equal;
case VK_OEM_MINUS : return sf::Key::Dash;
case VK_OEM_4 : return sf::Key::LBracket;
case VK_OEM_6 : return sf::Key::RBracket;
case VK_OEM_COMMA : return sf::Key::Comma;
case VK_OEM_PERIOD : return sf::Key::Period;
case VK_OEM_7 : return sf::Key::Quote;
case VK_OEM_5 : return sf::Key::BackSlash;
case VK_OEM_3 : return sf::Key::Tilde;
case VK_ESCAPE : return sf::Key::Escape;
case VK_SPACE : return sf::Key::Space;
case VK_RETURN : return sf::Key::Return;
case VK_BACK : return sf::Key::Back;
case VK_TAB : return sf::Key::Tab;
case VK_PRIOR : return sf::Key::PageUp;
case VK_NEXT : return sf::Key::PageDown;
case VK_END : return sf::Key::End;
case VK_HOME : return sf::Key::Home;
case VK_INSERT : return sf::Key::Insert;
case VK_DELETE : return sf::Key::Delete;
case VK_ADD : return sf::Key::Add;
case VK_SUBTRACT : return sf::Key::Subtract;
case VK_MULTIPLY : return sf::Key::Multiply;
case VK_DIVIDE : return sf::Key::Divide;
case VK_PAUSE : return sf::Key::Pause;
case VK_F1 : return sf::Key::F1;
case VK_F2 : return sf::Key::F2;
case VK_F3 : return sf::Key::F3;
case VK_F4 : return sf::Key::F4;
case VK_F5 : return sf::Key::F5;
case VK_F6 : return sf::Key::F6;
case VK_F7 : return sf::Key::F7;
case VK_F8 : return sf::Key::F8;
case VK_F9 : return sf::Key::F9;
case VK_F10 : return sf::Key::F10;
case VK_F11 : return sf::Key::F11;
case VK_F12 : return sf::Key::F12;
case VK_F13 : return sf::Key::F13;
case VK_F14 : return sf::Key::F14;
case VK_F15 : return sf::Key::F15;
case VK_LEFT : return sf::Key::Left;
case VK_RIGHT : return sf::Key::Right;
case VK_UP : return sf::Key::Up;
case VK_DOWN : return sf::Key::Down;
case VK_NUMPAD0 : return sf::Key::Numpad0;
case VK_NUMPAD1 : return sf::Key::Numpad1;
case VK_NUMPAD2 : return sf::Key::Numpad2;
case VK_NUMPAD3 : return sf::Key::Numpad3;
case VK_NUMPAD4 : return sf::Key::Numpad4;
case VK_NUMPAD5 : return sf::Key::Numpad5;
case VK_NUMPAD6 : return sf::Key::Numpad6;
case VK_NUMPAD7 : return sf::Key::Numpad7;
case VK_NUMPAD8 : return sf::Key::Numpad8;
case VK_NUMPAD9 : return sf::Key::Numpad9;
case 'A' : return sf::Key::A;
case 'Z' : return sf::Key::Z;
case 'E' : return sf::Key::E;
case 'R' : return sf::Key::R;
case 'T' : return sf::Key::T;
case 'Y' : return sf::Key::Y;
case 'U' : return sf::Key::U;
case 'I' : return sf::Key::I;
case 'O' : return sf::Key::O;
case 'P' : return sf::Key::P;
case 'Q' : return sf::Key::Q;
case 'S' : return sf::Key::S;
case 'D' : return sf::Key::D;
case 'F' : return sf::Key::F;
case 'G' : return sf::Key::G;
case 'H' : return sf::Key::H;
case 'J' : return sf::Key::J;
case 'K' : return sf::Key::K;
case 'L' : return sf::Key::L;
case 'M' : return sf::Key::M;
case 'W' : return sf::Key::W;
case 'X' : return sf::Key::X;
case 'C' : return sf::Key::C;
case 'V' : return sf::Key::V;
case 'B' : return sf::Key::B;
case 'N' : return sf::Key::N;
case '0' : return sf::Key::Num0;
case '1' : return sf::Key::Num1;
case '2' : return sf::Key::Num2;
case '3' : return sf::Key::Num3;
case '4' : return sf::Key::Num4;
case '5' : return sf::Key::Num5;
case '6' : return sf::Key::Num6;
case '7' : return sf::Key::Num7;
case '8' : return sf::Key::Num8;
case '9' : return sf::Key::Num9;
}
return sf::Key::Code(0);
}
///////////////////////////////////////////////////////////
/// Win32 Callback for the window class
////////////////////////////////////////////////////////////
LRESULT CALLBACK Win32Window::GlobalOnEvent(HWND Handle, UINT Message, WPARAM WParam, LPARAM LParam)
{
// Associate handle and Window instance when the creation message is received
if (Message == WM_CREATE)
{
// Get Win32Window instance (it was passed as the last argument of CreateWindow)
long This = reinterpret_cast<long>(reinterpret_cast<CREATESTRUCT*>(LParam)->lpCreateParams);
// Set as the "user data" parameter of the window
SetWindowLongPtr(Handle, GWLP_USERDATA, This);
}
// Get the GLWindow instance corresponding to the window handle
Win32Window* Window = reinterpret_cast<Win32Window*>(GetWindowLongPtr(Handle, GWLP_USERDATA));
// Forward the event to the appropriate function
if (Window)
{
Window->ProcessEvent(Message, WParam, LParam);
if (Window->myCallback)
return CallWindowProc(reinterpret_cast<WNDPROC>(Window->myCallback), Handle, Message, WParam, LParam);
}
// We don't forward the WM_CLOSE message to prevent the OS from automatically destroying the window
if (Message == WM_CLOSE)
return 0;
return DefWindowProc(Handle, Message, WParam, LParam);
}