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 *************************************************************************/
PVRShellOutputDebug(char const * const format,...) const68 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 *************************************************************************/
OsInit()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 *************************************************************************/
OsInitOS()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 *************************************************************************/
OsReleaseOS()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 *************************************************************************/
OsExit()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 *************************************************************************/
OsDoInitAPI()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 *************************************************************************/
OsDoReleaseAPI()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 *************************************************************************/
OsRenderComplete()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 *************************************************************************/
OsPixmapCopy()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 *************************************************************************/
OsGetNativeDisplayType()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 *************************************************************************/
OsGetNativePixmapType()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 *************************************************************************/
OsGetNativeWindowType()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 *************************************************************************/
OsGet(const prefNameIntEnum prefName,int * pn)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 *************************************************************************/
OsSet(const prefNameBoolEnum prefName,const bool value)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 *************************************************************************/
OsSet(const prefNameIntEnum prefName,const int i32Value)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 *************************************************************************/
OsGet(const prefNamePtrEnum prefName,void ** pp)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 *************************************************************************/
OsDisplayDebugString(char const * const str)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 *************************************************************************/
OsGetTime()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 **********************************************************************************************/
MyRegisterClass()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 *****************************************************************************/
doButtonDown(HWND hWnd,PVRShellInit * pData,EPVRShellButtonState eButton,LPARAM lParam)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 
doButtonUp(HWND hWnd,PVRShellInit * pData,EPVRShellButtonState eButton,LPARAM lParam)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 *****************************************************************************/
WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)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 *****************************************************************************/
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,TCHAR * lpCmdLine,int nCmdShow)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