forked from dolphin-emu/dolphin
		
	Not committing VideoOGL.vcproj so that project compiles with old OGL video window. In order to test just replace main.cpp/GLUtil.cpp/GLUtil.h with nmain.cpp/nGLUtil.cpp/nGLUtil.h in the project. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2038 8ced0084-cf51-0410-be5f-012b33b47a6e
		
			
				
	
	
		
			804 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			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);
 | 
						|
}
 |