CSC3223_Graphics_For_Games_Software_Rasteriser / SoftwareRasteriser / Window.cpp
Window.cpp
Raw
#include "Window.h"

Window::Window(uint width, uint height)	{
	hasInit = false;
	HINSTANCE hInstance = GetModuleHandle( NULL );

	WNDCLASSEX windowClass;
	ZeroMemory(&windowClass, sizeof(WNDCLASSEX));

	if(!GetClassInfoEx(hInstance,WINDOWCLASS,&windowClass))	{
		windowClass.cbSize		= sizeof(WNDCLASSEX);
		windowClass.style		= CS_HREDRAW | CS_VREDRAW;
		windowClass.lpfnWndProc	= (WNDPROC)StaticWindowProc;
		windowClass.hInstance	= hInstance;
		windowClass.hCursor		= LoadCursor(NULL, IDC_ARROW);
		windowClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
		windowClass.lpszClassName = WINDOWCLASS;

		if(!RegisterClassEx(&windowClass)) {
			return;
		}
	}

	windowHandle = CreateWindowEx(NULL,
		WINDOWCLASS,    // name of the window class
		"Software Rasteriser!",   // title of the window
		WS_OVERLAPPEDWINDOW|WS_POPUP|WS_VISIBLE|WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX,    // window style
		(int)100,	// x-position of the window
		(int)100,	// y-position of the window
		(int)width,		// width of the window
		(int)height,		// height of the window
		NULL,				// No parent window!
		NULL,				// No Menus!
		hInstance,			// application handle
		this);				// 

	deviceContext=GetDC(windowHandle);

	RECT    rt; 
	GetClientRect(windowHandle, &rt);

	screenWidth		= rt.right;
	screenHeight	= rt.bottom;

	BuildBitmap();

	Keyboard::Initialise(windowHandle);
	Mouse::Initialise(windowHandle);

	hasInit		= true;
	forceQuit	= false;
}


Window::~Window(void)	{
	DeleteObject(bitBuffers[0]);
	DeleteObject(bitBuffers[1]);
	DeleteDC(drawDC);

	Keyboard::Destroy();
	Mouse::Destroy();
}

void Window::BuildBitmap() {
	DeleteObject(bitBuffers[0]);
	DeleteObject(bitBuffers[1]);
	DeleteDC(drawDC);

	BITMAPINFO bmi; 

	bmi.bmiHeader.biSize		= sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth		= screenWidth;
	bmi.bmiHeader.biHeight		= screenHeight;
	bmi.bmiHeader.biPlanes		= 1;
	bmi.bmiHeader.biBitCount	= 32;         // four 8-bit components 
	bmi.bmiHeader.biCompression = BI_RGB;
	bmi.bmiHeader.biSizeImage	= screenWidth * screenHeight * 3;

	drawDC	= CreateCompatibleDC(deviceContext);

	for (int i = 0; i < 2; ++i) {
		bitBuffers[i] = CreateDIBSection(drawDC, &bmi, DIB_RGB_COLORS, &bufferData[i], NULL, 0x0);
	}
}

void Window::PresentBuffer(Colour*buffer) {
	if ((void*)buffer == bufferData[0]) {
		SelectObject(drawDC, bitBuffers[0]);
	}
	else {
		SelectObject(drawDC, bitBuffers[1]);
		//Using the student provided mem buffer, must memcopy!
		if ((void*)buffer != bufferData[0] && ((void*)buffer != bufferData[1])) {
			memcpy(bufferData[1], buffer, screenWidth * screenHeight * sizeof(unsigned int));
		}
	}
	BitBlt(deviceContext, 0, 0, screenWidth, screenHeight, drawDC, 0, 0, SRCCOPY);
}

LRESULT Window::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)	{
	switch(message)	 {
		case(WM_CREATE):{
			Window* w = reinterpret_cast<Window*>(((LPCREATESTRUCT)lParam)->lpCreateParams);
			SetWindowLongPtr(hWnd,GWL_USERDATA,reinterpret_cast<long>(w));
		}break;
		case(WM_DESTROY):	{
			PostQuitMessage(0);
			forceQuit = true;
		}break;
		case (WM_ACTIVATE): {
			if(LOWORD(wParam) == WA_INACTIVE)	{
				ReleaseCapture();
				ClipCursor(NULL);
				if (hasInit) {
					Mouse::instance->Sleep();
					Keyboard::instance->Sleep();
				}
			}
			else{
				if(hasInit) {
					Mouse::instance->Wake();	
					Keyboard::instance->Wake();
				}
			}
			return 0;
		}break;
		case (WM_LBUTTONDOWN): {

		}break;

		case (WM_MOUSEMOVE): {
			TRACKMOUSEEVENT tme;
			tme.cbSize = sizeof(TRACKMOUSEEVENT);
			tme.dwFlags = TME_LEAVE;
			tme.hwndTrack = windowHandle;
			TrackMouseEvent(&tme);

			if (hasInit) {
				Mouse::instance->SetAbsolutePosition(LOWORD(lParam), HIWORD(lParam));
			}
		}break;
		case(WM_SIZE): {
			screenWidth		= LOWORD(lParam);
			screenHeight	= HIWORD(lParam);

			BuildBitmap();

			Resize();
		}break;

		case(WM_SETFOCUS) : {
			if (hasInit) {
				Mouse::instance->Wake(); 
				Mouse::instance->Wake();
			}
		}break;
		case(WM_KILLFOCUS) : {
			if (hasInit) {
				Mouse::instance->Sleep();
				Keyboard::instance->Sleep();
			}
		}break;
	}
	return DefWindowProc (hWnd, message, wParam, lParam);
}

LRESULT CALLBACK Window::StaticWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)	{
	Window* window = (Window*)GetWindowLongPtr(hWnd,GWL_USERDATA);
	return window->WindowProc(hWnd,message,wParam,lParam);
}

bool	Window::UpdateWindow() {
	Keyboard::instance->UpdateHolds();
	Mouse::instance->UpdateHolds();

	MSG		msg;
	while(PeekMessage(&msg,windowHandle,0,0,PM_REMOVE)) {
		CheckMessages(msg); 
	}

	return !forceQuit;
}

void Window::CheckMessages(MSG &msg)	{
	switch (msg.message)	{				// Is There A Message Waiting?
		case (WM_QUIT):
		case (WM_CLOSE): {					// Have We Received A Quit Message?
			forceQuit = true;
		}break;
		case (WM_INPUT): {
			UINT dwSize;
			GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, NULL, &dwSize,sizeof(RAWINPUTHEADER));

			BYTE* lpb = new BYTE[dwSize];

			GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, lpb, &dwSize,sizeof(RAWINPUTHEADER));
			RAWINPUT* raw = (RAWINPUT*)lpb;

			if (Keyboard::instance && raw->header.dwType == RIM_TYPEKEYBOARD) {
				Keyboard::instance->Update(raw);
			}
			else if (Mouse::instance && raw->header.dwType == RIM_TYPEMOUSE) {
				Mouse::instance->Update(raw);
			}
			delete lpb;
		}break;

		default: {								// If Not, Deal With Window Messages
			TranslateMessage(&msg);				// Translate The Message
			DispatchMessage(&msg);				// Dispatch The Message
		}
	}
}