#include <windows.h>
#include <stdio.h>
#include <tchar.h>

const TCHAR g_szClassName[] = _T("myWindowClass");

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
		case WM_CLOSE:
			DestroyWindow(hwnd);
		break;
		case WM_DESTROY:
			PostQuitMessage(0);
		break;
		case WM_KEYDOWN:
		case WM_SYSKEYDOWN: {
			int scancode;
			int repeat;
			int extended;
			TCHAR name[50] = { '\0' };
			
			scancode = (lParam >> 16) & 0xff;
			extended = (lParam >> 24) & 1;
			repeat = (lParam >> 30) & 1;
			GetKeyNameText((LONG)lParam, name, sizeof(name));
			_tprintf(_T("DOWN (%s) %s Ext=%d SC=%08x VK=%08x\n"), repeat ? _T("R") : _T(" "),
				                                             name, extended, scancode, wParam);
			break;
		}
		case WM_KEYUP:
		case WM_SYSKEYUP: {
			int scancode;
			int extended;
			TCHAR name[50] = { '\0' };
			
			scancode = (lParam >> 16) & 0xff;
			extended = (lParam >> 24) & 1;
			GetKeyNameText((LONG)lParam, name, sizeof(name));
			_tprintf(_T("UP       %s Ext=%d SC=%08x VK=%08x\n"), name, extended, scancode, wParam);
			break;
		}
		case WM_UNICHAR:
			if (wParam == UNICODE_NOCHAR)
				return TRUE;
			printf("UNI");
		// falling through to WM_CHAR
		case WM_CHAR: {
			int repeat;

			repeat = (lParam >> 30) & 1;
			_tprintf(_T("CHAR (%s) '%c' %08x\n"), repeat ? _T("R") : _T(" "), wParam, wParam);
			break;
		}
		default:
			return DefWindowProc(hwnd, msg, wParam, lParam);
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX wc;
	HWND hwnd;
	MSG Msg;

	//Step 1: Registering the Window Class
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.style		 = 0;
	wc.lpfnWndProc	 = WndProc;
	wc.cbClsExtra	 = 0;
	wc.cbWndExtra	 = 0;
	wc.hInstance	 = hInstance;
	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName	 = NULL;
	wc.lpszClassName = g_szClassName;
	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);

	if(!RegisterClassEx(&wc))
	{
		MessageBox(NULL, _T("Window Registration Failed!"), _T("Error!"),
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	// Step 2: Creating the Window
	hwnd = CreateWindowEx(
		WS_EX_CLIENTEDGE,
		g_szClassName,
#ifdef UNICODE
		L"Key input test (UNICODE)",
#else
		"Key input test (ANSI)",
#endif
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, 300, 300,
		NULL, NULL, hInstance, NULL);

	if(hwnd == NULL)
	{
		MessageBox(NULL, _T("Window Creation Failed!"), _T("Error!"),
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

#ifdef UNICODE
	printf("UNICODE build, euro sign: € (0x80)\n");
#else
	printf("ANSI build, euro sign: € (0x80)\n");
#endif

	// Step 3: The Message Loop
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
	return (int)Msg.wParam;
}
