Home | History | Annotate | Download | only in Windows
      1 /******************************************************************************
      2 
      3  @File         PVRShellOS.cpp
      4 
      5  @Title        Windows/PVRShellOS
      6 
      7  @Version
      8 
      9  @Copyright    Copyright (c) Imagination Technologies Limited.
     10 
     11  @Platform     WinCE/Windows
     12 
     13  @Description  Makes programming for 3D APIs easier by wrapping window creation
     14                and other functions for use by a demo.
     15 
     16 ******************************************************************************/
     17 
     18 /****************************************************************************
     19  ** INCLUDES                                                               **
     20  ****************************************************************************/
     21 #include <windows.h>
     22 #include <TCHAR.H>
     23 #include <stdio.h>
     24 
     25 #include "PVRShell.h"
     26 #include "PVRShellAPI.h"
     27 #include "PVRShellOS.h"
     28 #include "PVRShellImpl.h"
     29 
     30 // No Doxygen for CPP files, due to documentation duplication
     31 /// @cond NO_DOXYGEN
     32 
     33 #if !(WINVER >= 0x0500)
     34 	#define COMPILE_MULTIMON_STUBS
     35 	#include <multimon.h>
     36 #endif
     37 
     38 /****************************************************************************
     39 	Defines
     40 *****************************************************************************/
     41 /*! The class name for the window */
     42 #define WINDOW_CLASS _T("PVRShellClass")
     43 
     44 /*! Maximum size to create string array for determining the read/write paths */
     45 #define DIR_BUFFER_LEN	(10240)
     46 
     47 /*! X dimension of the window that is created */
     48 #define SHELL_DISPLAY_DIM_X	800
     49 /*! Y dimension of the window that is created */
     50 #define SHELL_DISPLAY_DIM_Y	600
     51 
     52 /*****************************************************************************
     53 	Declarations
     54 *****************************************************************************/
     55 LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
     56 
     57 /*!***************************************************************************
     58 	Class: PVRShellInit
     59 *****************************************************************************/
     60 
     61 /*!***********************************************************************
     62 @Function		PVRShellOutputDebug
     63 @Input			format			printf style format followed by arguments it requires
     64 @Description	Writes the resultant string to the debug output (e.g. using
     65 				printf(), OutputDebugString(), ...). Check the SDK release notes for
     66 				details on how the string is output.
     67 *************************************************************************/
     68 void PVRShell::PVRShellOutputDebug(char const * const format, ...) const
     69 {
     70 	va_list arg;
     71 	char	buf[1024];
     72 
     73 	va_start(arg, format);
     74 	vsnprintf(buf, 1024, format, arg);
     75 	va_end(arg);
     76 
     77 	// Passes the data to a platform dependant function
     78 	m_pShellInit->OsDisplayDebugString(buf);
     79 }
     80 
     81 /*!***********************************************************************
     82  @Function		OsInit
     83  @description	Initialisation for OS-specific code.
     84 *************************************************************************/
     85 void PVRShellInit::OsInit()
     86 {
     87 	m_hAccelTable = 0;
     88 
     89 	m_pShell->m_pShellData->nShellDimX = SHELL_DISPLAY_DIM_X;
     90 	m_pShell->m_pShellData->nShellDimY = SHELL_DISPLAY_DIM_Y;
     91 
     92 	m_hDC = 0;
     93 	m_hWnd = 0;
     94 
     95 	// Pixmap support: init variables to 0
     96 	m_hBmPixmap = 0;
     97 	m_hBmPixmapOld = 0;
     98 	m_hDcPixmap = 0;
     99 
    100 	/*
    101 		Construct the binary path for GetReadPath() and GetWritePath()
    102 	*/
    103 	{
    104 		/* Allocate memory for strings and return 0 if allocation failed */
    105 		TCHAR* exeNameTCHAR = new TCHAR[DIR_BUFFER_LEN];
    106 		char* exeName = new char[DIR_BUFFER_LEN];
    107 		if(exeNameTCHAR && exeName)
    108 		{
    109 			DWORD retSize;
    110 
    111 			/*
    112 				Get the data path and a default application name
    113 			*/
    114 
    115 			// Get full path of executable
    116 			retSize = GetModuleFileName(NULL, exeNameTCHAR, DIR_BUFFER_LEN);
    117 
    118 			if (DIR_BUFFER_LEN > (int)retSize)
    119 			{
    120 				/* Get string length in char */
    121 				retSize = (DWORD)_tcslen(exeNameTCHAR);
    122 
    123 				/* Convert TChar to char */
    124 				for (DWORD i = 0; i <= retSize; i++)
    125 				{
    126 					exeName[i] = (char)exeNameTCHAR[i];
    127 				}
    128 
    129 				SetAppName(exeName);
    130 				SetReadPath(exeName);
    131 				SetWritePath(exeName);
    132 			}
    133 		}
    134 
    135 		delete [] exeName;
    136 		delete [] exeNameTCHAR;
    137 	}
    138 
    139 	m_u32ButtonState = 0;	// clear mouse button state at startup
    140 }
    141 
    142 /*!***********************************************************************
    143  @Function		OsInitOS
    144  @description	Saves instance handle and creates main window
    145 				In this function, we save the instance handle in a global variable and
    146 				create and display the main program window.
    147 *************************************************************************/
    148 bool PVRShellInit::OsInitOS()
    149 {
    150 	MONITORINFO sMInfo;
    151 	TCHAR		*appName;
    152 	RECT		winRect;
    153 	POINT		p;
    154 
    155 	MyRegisterClass();
    156 
    157 	/*
    158 		Build the window title
    159 	*/
    160 	{
    161 		const char		*pszName, *pszSeparator, *pszVersion;
    162 		size_t			len;
    163 		unsigned int	out, in;
    164 
    165 		pszName			= (const char*)m_pShell->PVRShellGet(prefAppName);
    166 		pszSeparator	= STR_WNDTITLE;
    167 		pszVersion		= (const char*)m_pShell->PVRShellGet(prefVersion);
    168 
    169 		len = strlen(pszName)+strlen(pszSeparator)+strlen(pszVersion)+1;
    170 		appName = new TCHAR[len];
    171 
    172 		for(out = 0; (appName[out] = pszName[out]) != 0; ++out);
    173 		for(in = 0; (appName[out] = pszSeparator[in]) != 0; ++in, ++out);
    174 		for(in = 0; (appName[out] = pszVersion[in]) != 0; ++in, ++out);
    175 		_ASSERT(out == len-1);
    176 	}
    177 
    178 	/*
    179 		Retrieve the monitor information.
    180 
    181 		MonitorFromWindow() doesn't work, because the window hasn't been
    182 		created yet.
    183 	*/
    184 	{
    185 		HMONITOR	hMonitor;
    186 		BOOL		bRet;
    187 
    188 		p.x			= m_pShell->m_pShellData->nShellPosX;
    189 		p.y			= m_pShell->m_pShellData->nShellPosY;
    190 		hMonitor	= MonitorFromPoint(p, MONITOR_DEFAULTTOPRIMARY);
    191 		sMInfo.cbSize = sizeof(sMInfo);
    192 		bRet = GetMonitorInfo(hMonitor, &sMInfo);
    193 		_ASSERT(bRet);
    194 	}
    195 
    196 	/*
    197 		Reduce the window size until it fits on screen
    198 	*/
    199 	while(
    200 		(m_pShell->m_pShellData->nShellDimX > (sMInfo.rcMonitor.right - sMInfo.rcMonitor.left)) ||
    201 		(m_pShell->m_pShellData->nShellDimY > (sMInfo.rcMonitor.bottom - sMInfo.rcMonitor.top)))
    202 	{
    203 		m_pShell->m_pShellData->nShellDimX >>= 1;
    204 		m_pShell->m_pShellData->nShellDimY >>= 1;
    205 	}
    206 
    207 
    208 	/*
    209 		Create the window
    210 	*/
    211 
    212 	if(m_pShell->m_pShellData->bFullScreen)
    213 	{
    214 		m_hWnd = CreateWindow(WINDOW_CLASS, appName, WS_VISIBLE | WS_SYSMENU,CW_USEDEFAULT, CW_USEDEFAULT, m_pShell->m_pShellData->nShellDimX, m_pShell->m_pShellData->nShellDimY,
    215 				NULL, NULL, m_hInstance, this);
    216 
    217 		SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE) &~ WS_CAPTION);
    218 		SetWindowPos(m_hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
    219 	}
    220 	else
    221 	{
    222 		int x, y;
    223 
    224 		SetRect(&winRect,
    225 			m_pShell->m_pShellData->nShellPosX,
    226 			m_pShell->m_pShellData->nShellPosY,
    227 			m_pShell->m_pShellData->nShellPosX+m_pShell->m_pShellData->nShellDimX,
    228 			m_pShell->m_pShellData->nShellPosY+m_pShell->m_pShellData->nShellDimY);
    229 		AdjustWindowRectEx(&winRect, WS_CAPTION|WS_SYSMENU, false, 0);
    230 
    231 		x = m_pShell->m_pShellData->nShellPosX - winRect.left;
    232 		winRect.left += x;
    233 		winRect.right += x;
    234 
    235 		y = m_pShell->m_pShellData->nShellPosY - winRect.top;
    236 		winRect.top += y;
    237 		winRect.bottom += y;
    238 
    239 		if(m_pShell->m_pShellData->bShellPosWasDefault)
    240 		{
    241 			x = CW_USEDEFAULT;
    242 			y = CW_USEDEFAULT;
    243 		}
    244 		else
    245 		{
    246 			x = winRect.left;
    247 			y = winRect.top;
    248 		}
    249 
    250 		m_hWnd = CreateWindow(WINDOW_CLASS, appName, WS_VISIBLE|WS_CAPTION|WS_SYSMENU,
    251 			x, y, winRect.right-winRect.left, winRect.bottom-winRect.top, NULL, NULL, m_hInstance, this);
    252 
    253 	}
    254 
    255 	if(!m_hWnd)
    256 		return false;
    257 
    258 	if(m_pShell->m_pShellData->bFullScreen)
    259 	{
    260 		m_pShell->m_pShellData->nShellDimX = sMInfo.rcMonitor.right;
    261 		m_pShell->m_pShellData->nShellDimY = sMInfo.rcMonitor.bottom;
    262 		SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,m_pShell->m_pShellData->nShellDimX,m_pShell->m_pShellData->nShellDimY,0);
    263 	}
    264 
    265 	m_hDC = GetDC(m_hWnd);
    266 	ShowWindow(m_hWnd, m_nCmdShow);
    267 	UpdateWindow(m_hWnd);
    268 
    269 	delete [] appName;
    270 	return true;
    271 }
    272 
    273 /*!***********************************************************************
    274  @Function		OsReleaseOS
    275  @description	Destroys main window
    276 *************************************************************************/
    277 void PVRShellInit::OsReleaseOS()
    278 {
    279 	ReleaseDC(m_hWnd, m_hDC);
    280 	DestroyWindow(m_hWnd);
    281 }
    282 
    283 /*!***********************************************************************
    284  @Function		OsExit
    285  @description	Destroys main window
    286 *************************************************************************/
    287 void PVRShellInit::OsExit()
    288 {
    289 	const char	*szText;
    290 
    291 	/*
    292 		Show the exit message to the user
    293 	*/
    294 	szText		= (const char*)m_pShell->PVRShellGet(prefExitMessage);
    295 
    296 	int			i, nT, nC;
    297 	const char	*szCaption;
    298 	TCHAR		*tzText, *tzCaption;
    299 
    300 	szCaption	= (const char*)m_pShell->PVRShellGet(prefAppName);
    301 
    302 	if(!szText || !szCaption)
    303 		return;
    304 
    305 	nT = (int)strlen(szText) + 1;
    306 	nC = (int)strlen(szCaption) + 1;
    307 
    308 	tzText = (TCHAR*)malloc(nT * sizeof(*tzText));
    309 	tzCaption = (TCHAR*)malloc(nC * sizeof(*tzCaption));
    310 
    311 	for(i = 0; (tzText[i] = szText[i]) != 0; ++i);
    312 	for(i = 0; (tzCaption[i] = szCaption[i]) != 0; ++i);
    313 
    314 	MessageBox(NULL, tzText, tzCaption, MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND);
    315 
    316 	FREE(tzText);
    317 	FREE(tzCaption);
    318 }
    319 
    320 /*!***********************************************************************
    321  @Function		OsDoInitAPI
    322  @Return		true on success
    323  @description	Perform API initialisation and bring up window / fullscreen
    324 *************************************************************************/
    325 bool PVRShellInit::OsDoInitAPI()
    326 {
    327 
    328 	// Pixmap support: create the pixmap
    329 	if(m_pShell->m_pShellData->bNeedPixmap)
    330 	{
    331 		m_hDcPixmap = CreateCompatibleDC(m_hDC);
    332 		m_hBmPixmap = CreateCompatibleBitmap(m_hDC, 640, 480);
    333 	}
    334 
    335 	if(!ApiInitAPI())
    336 	{
    337 		return false;
    338 	}
    339 
    340 	// Pixmap support: select the pixmap into a device context (DC) ready for blitting
    341 	if(m_pShell->m_pShellData->bNeedPixmap)
    342 	{
    343 		m_hBmPixmapOld = (HBITMAP)SelectObject(m_hDcPixmap, m_hBmPixmap);
    344 	}
    345 
    346 	SetForegroundWindow(m_hWnd);
    347 
    348 	/* No problem occured */
    349 	return true;
    350 }
    351 
    352 /*!***********************************************************************
    353  @Function		OsDoReleaseAPI
    354  @description	Clean up after we're done
    355 *************************************************************************/
    356 void PVRShellInit::OsDoReleaseAPI()
    357 {
    358 	ApiReleaseAPI();
    359 
    360 	if(m_pShell->m_pShellData->bNeedPixmap)
    361 	{
    362 		// Pixmap support: free the pixmap
    363 		SelectObject(m_hDcPixmap, m_hBmPixmapOld);
    364 		DeleteDC(m_hDcPixmap);
    365 		DeleteObject(m_hBmPixmap);
    366 	}
    367 }
    368 
    369 /*!***********************************************************************
    370  @Function		OsRenderComplete
    371  @Returns		false when the app should quit
    372  @description	Main message loop / render loop
    373 *************************************************************************/
    374 void PVRShellInit::OsRenderComplete()
    375 {
    376 	MSG		msg;
    377 
    378 	/*
    379 		Process the message queue
    380 	*/
    381 	while(PeekMessage(&msg, m_hWnd, 0, 0, PM_REMOVE))
    382 	{
    383 		if (!TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg))
    384 		{
    385 			TranslateMessage(&msg);
    386 			DispatchMessage(&msg);
    387 		}
    388 	}
    389 
    390 }
    391 
    392 /*!***********************************************************************
    393  @Function		OsPixmapCopy
    394  @Return		true if the copy succeeded
    395  @description	When using pixmaps, copy the render to the display
    396 *************************************************************************/
    397 bool PVRShellInit::OsPixmapCopy()
    398 {
    399 	return (BitBlt(m_hDC, 0, 0, 640, 480, m_hDcPixmap, 0, 0, SRCCOPY) == TRUE);
    400 }
    401 
    402 /*!***********************************************************************
    403  @Function		OsGetNativeDisplayType
    404  @Return		The 'NativeDisplayType' for EGL
    405  @description	Called from InitAPI() to get the NativeDisplayType
    406 *************************************************************************/
    407 void *PVRShellInit::OsGetNativeDisplayType()
    408 {
    409 	return m_hDC;
    410 }
    411 
    412 /*!***********************************************************************
    413  @Function		OsGetNativePixmapType
    414  @Return		The 'NativePixmapType' for EGL
    415  @description	Called from InitAPI() to get the NativePixmapType
    416 *************************************************************************/
    417 void *PVRShellInit::OsGetNativePixmapType()
    418 {
    419 	// Pixmap support: return the pixmap
    420 	return m_hBmPixmap;
    421 }
    422 
    423 /*!***********************************************************************
    424  @Function		OsGetNativeWindowType
    425  @Return		The 'NativeWindowType' for EGL
    426  @description	Called from InitAPI() to get the NativeWindowType
    427 *************************************************************************/
    428 void *PVRShellInit::OsGetNativeWindowType()
    429 {
    430 	return m_hWnd;
    431 }
    432 
    433 /*!***********************************************************************
    434  @Function		OsGet
    435  @Input			prefName	Name of value to get
    436  @Modified		pn A pointer set to the value asked for
    437  @Returns		true on success
    438  @Description	Retrieves OS-specific data
    439 *************************************************************************/
    440 bool PVRShellInit::OsGet(const prefNameIntEnum prefName, int *pn)
    441 {
    442 	switch(prefName)
    443 	{
    444 	case prefButtonState:
    445 		*pn = m_u32ButtonState;
    446 		return true;
    447 	};
    448 	return false;
    449 }
    450 
    451 /*!***********************************************************************
    452  @Function		OsSet
    453  @Input			prefName				Name of preference to set to value
    454  @Input			value					Value
    455  @Return		true for success
    456  @Description	Sets OS-specific data
    457 *************************************************************************/
    458 bool PVRShellInit::OsSet(const prefNameBoolEnum prefName, const bool value)
    459 {
    460 	switch(prefName)
    461 	{
    462 	case prefShowCursor:
    463 		ShowCursor(value ? TRUE : FALSE);
    464 		return true;
    465 	}
    466 
    467 	return false;
    468 }
    469 
    470 /*!***********************************************************************
    471  @Function		OsSet
    472  @Input			prefName	Name of value to set
    473  @Input			i32Value 	The value to set our named value to
    474  @Returns		true on success
    475  @Description	Sets OS-specific data
    476 *************************************************************************/
    477 bool PVRShellInit::OsSet(const prefNameIntEnum prefName, const int i32Value)
    478 {
    479 	PVRSHELL_UNREFERENCED_PARAMETER(prefName);
    480 	PVRSHELL_UNREFERENCED_PARAMETER(i32Value);
    481 	return false;
    482 }
    483 
    484 /*!***********************************************************************
    485  @Function		OsGet
    486  @Input			prefName	Name of value to get
    487  @Modified		pp A pointer set to the value asked for
    488  @Returns		true on success
    489  @Description	Retrieves OS-specific data
    490 *************************************************************************/
    491 bool PVRShellInit::OsGet(const prefNamePtrEnum prefName, void **pp)
    492 {
    493 	switch(prefName)
    494 	{
    495 	case prefHINSTANCE:
    496 		*pp = m_hInstance;
    497 		return true;
    498 	default:
    499 		return false;
    500 	}
    501 }
    502 
    503 /*!***********************************************************************
    504  @Function		OsDisplayDebugString
    505  @Input			str		string to output
    506  @Description	Prints a debug string
    507 *************************************************************************/
    508 void PVRShellInit::OsDisplayDebugString(char const * const str)
    509 {
    510 	if(str)
    511 	{
    512 #if defined(UNICODE)
    513 		wchar_t	strc[1024];
    514 		int		i;
    515 
    516 		for(i = 0; (str[i] != '\0') && (i < (sizeof(strc) / sizeof(*strc))); ++i)
    517 		{
    518 			strc[i] = (wchar_t)str[i];
    519 		}
    520 
    521 		strc[i] = '\0';
    522 
    523 		OutputDebugString(strc);
    524 #else
    525 		OutputDebugString(str);
    526 #endif
    527 	}
    528 }
    529 
    530 /*!***********************************************************************
    531  @Function		OsGetTime
    532  @Return		An incrementing time value measured in milliseconds
    533  @Description	Returns an incrementing time value measured in milliseconds
    534 *************************************************************************/
    535 unsigned long PVRShellInit::OsGetTime()
    536 {
    537 	return (unsigned long)GetTickCount();
    538 }
    539 
    540 /*****************************************************************************
    541  Class: PVRShellInitOS
    542 *****************************************************************************/
    543 
    544 /*!******************************************************************************************
    545 @function		MyRegisterClass()
    546 @description	Registers the window class.
    547 				This function and its usage is only necessary if you want this code
    548 				to be compatible with Win32 systems prior to the 'RegisterClassEx'
    549 				function that was added to Windows 95. It is important to call this function
    550 				so that the application will get 'well formed' small icons associated
    551 				with it.
    552 **********************************************************************************************/
    553 ATOM PVRShellInitOS::MyRegisterClass()
    554 {
    555 	WNDCLASS wc;
    556 
    557     wc.style			= CS_HREDRAW | CS_VREDRAW;
    558 	wc.lpfnWndProc		= (WNDPROC)WndProc;
    559     wc.cbClsExtra		= 0;
    560     wc.cbWndExtra		= 0;
    561     wc.hInstance		= m_hInstance;
    562     wc.hIcon			= LoadIcon(m_hInstance, _T("ICON"));
    563     wc.hCursor			= 0;
    564     wc.lpszMenuName		= 0;
    565 	wc.hbrBackground	= (HBRUSH) GetStockObject(WHITE_BRUSH);
    566     wc.lpszClassName	= WINDOW_CLASS;
    567 
    568 	return RegisterClass(&wc);
    569 }
    570 
    571 /*****************************************************************************
    572  Global code
    573 *****************************************************************************/
    574 void doButtonDown(HWND hWnd, PVRShellInit *pData, EPVRShellButtonState eButton, LPARAM lParam)
    575 {
    576 	RECT rcWinDimensions;
    577 	GetClientRect(hWnd,&rcWinDimensions);
    578 	float vec2TouchPosition[2] = { (float)(short)LOWORD(lParam)/(float)(rcWinDimensions.right), (float)(short)HIWORD(lParam)/(float)(rcWinDimensions.bottom) };
    579 	pData->TouchBegan(vec2TouchPosition);
    580 	SetCapture(hWnd);	// must be within window so capture
    581 	pData->m_u32ButtonState |= eButton;
    582 }
    583 
    584 bool doButtonUp(HWND hWnd, PVRShellInit *pData, EPVRShellButtonState eButton, LPARAM lParam)
    585 {
    586 	RECT rcWinDimensions;
    587 	GetClientRect(hWnd,&rcWinDimensions);
    588 	float vec2TouchPosition[2] = { (float)(short)LOWORD(lParam)/(float)(rcWinDimensions.right), (float)(short)HIWORD(lParam)/(float)(rcWinDimensions.bottom) };
    589 	pData->TouchEnded(vec2TouchPosition);
    590 	pData->m_u32ButtonState &= (~eButton);
    591 
    592 	if(vec2TouchPosition[0] < 0.f || vec2TouchPosition[0] > 1.f || vec2TouchPosition[1] < 0.f || vec2TouchPosition[1] > 1.f)
    593 	{	// pointer has left window
    594 		if(pData->m_u32ButtonState==0)
    595 		{	// only release capture if mouse buttons have been released
    596 			ReleaseCapture();
    597 		}
    598 
    599 		return false;
    600 	}
    601 	return true;
    602 }
    603 
    604 /*!***************************************************************************
    605 @function		WndProc
    606 @input			hWnd		Handle to the window
    607 @input			message		Specifies the message
    608 @input			wParam		Additional message information
    609 @input			lParam		Additional message information
    610 @returns		result code to OS
    611 @description	Processes messages for the main window.
    612 *****************************************************************************/
    613 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    614 {
    615 	PVRShellInit *pData = (PVRShellInit*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
    616 
    617 	switch (message)
    618 	{
    619 	case WM_CREATE:
    620 		{
    621 			CREATESTRUCT	*pCreate = (CREATESTRUCT*)lParam;
    622 			SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pCreate->lpCreateParams);
    623 			break;
    624 		}
    625 	case WM_PAINT:
    626 		break;
    627 	case WM_DESTROY:
    628 		return 0;
    629 	case WM_CLOSE:
    630 		pData->gShellDone = true;
    631 		return 0;
    632 	case WM_QUIT:
    633 		return 0;
    634 	case WM_MOVE:
    635 		pData->m_pShell->PVRShellSet(prefPositionX, (int)LOWORD(lParam));
    636 		pData->m_pShell->PVRShellSet(prefPositionY, (int)HIWORD(lParam));
    637 		break;
    638 	case WM_LBUTTONDOWN:
    639 		{
    640 			doButtonDown(hWnd,pData,ePVRShellButtonLeft,lParam);
    641 			break;
    642 		}
    643 	case WM_LBUTTONUP:
    644 		{
    645 			if(!doButtonUp(hWnd,pData,ePVRShellButtonLeft,lParam))
    646 				return false;
    647 		break;
    648 		}
    649 	case WM_RBUTTONDOWN:
    650 		{
    651 			doButtonDown(hWnd,pData,ePVRShellButtonRight,lParam);
    652 			break;
    653 		}
    654 	case WM_RBUTTONUP:
    655 		{
    656 			if(!doButtonUp(hWnd,pData,ePVRShellButtonRight,lParam))
    657 				return false;
    658 			break;
    659 		}
    660 	case WM_MBUTTONDOWN:
    661 		{
    662 			doButtonDown(hWnd,pData,ePVRShellButtonMiddle,lParam);
    663 			break;
    664 		}
    665 	case WM_MBUTTONUP:
    666 		{
    667 			if(!doButtonUp(hWnd,pData,ePVRShellButtonMiddle,lParam))
    668 				return false;
    669 			break;
    670 		}
    671 	case WM_MOUSEMOVE:
    672 		{
    673 			RECT rcWinDimensions;
    674 			GetClientRect(hWnd,&rcWinDimensions);
    675 			float vec2TouchPosition[2] = { (float)(short)LOWORD(lParam)/(float)(rcWinDimensions.right), (float)(short)HIWORD(lParam)/(float)(rcWinDimensions.bottom) };
    676 
    677 			if(vec2TouchPosition[0] < 0.f || vec2TouchPosition[0] > 1.f || vec2TouchPosition[1] < 0.f || vec2TouchPosition[1] > 1.f)
    678 			{
    679 				// pointer has left window
    680 				if(pData->m_u32ButtonState==0)
    681 				{	// only release capture if mouse buttons have been released
    682 					ReleaseCapture();
    683 				}
    684 
    685 				pData->TouchEnded(vec2TouchPosition);
    686 				return false;
    687 			}
    688 			else
    689 			{	// pointer is inside window
    690 				pData->TouchMoved(vec2TouchPosition);
    691 			}
    692 			break;
    693 		}
    694 	case WM_SETFOCUS:
    695 		pData->m_bHaveFocus = true;
    696 		return 0;
    697 	case WM_KILLFOCUS:
    698 		pData->m_bHaveFocus = false;
    699 		return 0;
    700 	case WM_KEYDOWN:
    701 	{
    702 		switch(wParam)
    703 		{
    704 		case VK_ESCAPE:
    705 		case 0xC1:
    706 			pData->KeyPressed(PVRShellKeyNameQUIT);
    707 			break;
    708 		case VK_UP:
    709 		case 0x35:
    710 			pData->KeyPressed(pData->m_eKeyMapUP);
    711 			break;
    712 		case VK_DOWN:
    713 		case 0x30:
    714 			pData->KeyPressed(pData->m_eKeyMapDOWN);
    715 			break;
    716 		case VK_LEFT:
    717 		case 0x37:
    718 			pData->KeyPressed(pData->m_eKeyMapLEFT);
    719 			break;
    720 		case VK_RIGHT:
    721 		case 0x39:
    722 			pData->KeyPressed(pData->m_eKeyMapRIGHT);
    723 			break;
    724 		case VK_SPACE:
    725 		case 0x38:
    726 			pData->KeyPressed(PVRShellKeyNameSELECT);
    727 			break;
    728 		case '1':
    729 		case 0x34:
    730 			pData->KeyPressed(PVRShellKeyNameACTION1);
    731 			break;
    732 		case '2':
    733 		case 0x36:
    734 			pData->KeyPressed(PVRShellKeyNameACTION2);
    735 			break;
    736 		case VK_F11:
    737 		case 0xC2:
    738 			pData->KeyPressed(PVRShellKeyNameScreenshot);
    739 			break;
    740 		}
    741 	}
    742 	default:
    743 		break;
    744 	}
    745 
    746 	return DefWindowProc(hWnd, message, wParam, lParam);
    747 }
    748 
    749 /*!***************************************************************************
    750 @function		WinMain
    751 @input			hInstance		Application instance from OS
    752 @input			hPrevInstance	Always NULL
    753 @input			lpCmdLine		command line from OS
    754 @input			nCmdShow		Specifies how the window is to be shown
    755 @returns		result code to OS
    756 @description	Main function of the program
    757 *****************************************************************************/
    758 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, TCHAR *lpCmdLine, int nCmdShow)
    759 {
    760 	size_t			i;
    761 	char			*pszCmdLine;
    762 	PVRShellInit	init;
    763 
    764 	PVRSHELL_UNREFERENCED_PARAMETER(hPrevInstance);
    765 
    766 #if defined(_WIN32)
    767 	// Enable memory-leak reports
    768 	_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
    769 #endif
    770 
    771 	// Get a char-array command line as the input may be UNICODE
    772 	i = _tcslen(lpCmdLine) + 1;
    773 	pszCmdLine = new char[i];
    774 
    775 	while(i)
    776 	{
    777 		--i;
    778 		pszCmdLine[i] = (char)lpCmdLine[i];
    779 	}
    780 
    781 	//	Init the demo, process the command line, create the OS initialiser.
    782 	if(!init.Init())
    783 	{
    784 		delete[] pszCmdLine;
    785 		return EXIT_ERR_CODE;
    786 	}
    787 
    788 	init.CommandLine(pszCmdLine);
    789 	init.m_hInstance = hInstance;
    790 	init.m_nCmdShow = nCmdShow;
    791 
    792 	//	Initialise/run/shutdown
    793 	while(init.Run());
    794 
    795 	delete[] pszCmdLine;
    796 
    797 	return EXIT_NOERR_CODE;
    798 }
    799 
    800 /// @endcond
    801 
    802 /*****************************************************************************
    803  End of file (PVRShellOS.cpp)
    804 *****************************************************************************/
    805 
    806