//after you compile and build this, change the file extension from .exe to .scr (it'll still run but Windows will recognize it as a screen saver program)
#include <windows.h>
#define BLACK 0
#define goingred 1
#define goingyellow 2
#define goinggreen 3
#define goingbluegreen 4
#define goingblue 5
#define goingpurple 6
#define goingredfrompurple 7

int x;
int xPos = -1, yPos = -1, NoErase, cxScreen = 0, cyScreen;
int x1 = 140, x2 = 300, Y1 = 400, y2 = 476, x1Erase, x2Erase, y1Erase, y2Erase;
int x1inc = 2, x2inc = 3, y1inc = 2, y2inc = 1;
int x1incErase = 2, x2incErase = 3, y1incErase = 2, y2incErase = 1;
int Buf[11] = {0,0,0,0,0,0,0,0,0,0};
DWORD dw, fileSize, dwBytesRead, dwBytesWritten;
BYTE Red = 0, Green = 0, Blue = 0;
BYTE CurrentColor;
char Version[] = "1.2\nJune 14, 2012\nDoug Cox\njdmcox.com/";
char Filename[] = "MoireScreenSaver.dta";
HANDLE hFile;
COLORREF Color;
RECT rect;
HBRUSH hBrush;
HWND hwnd;
HDC hdc, hdcMem;
HBITMAP hBitmap;
HPEN hPen, hPen2;
PAINTSTRUCT ps;

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_CREATE:
		CurrentColor = goingred;
		ShowCursor(FALSE);
		hFile = CreateFile(Filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
		if (INVALID_HANDLE_VALUE != hFile)
		{
			ReadFile(hFile, Buf, 44, &dwBytesRead, NULL);
			CloseHandle(hFile);
		}
		break;

	case WM_SIZE:
		if (lParam)
		{
			cxScreen = LOWORD(lParam);
			cyScreen = HIWORD(lParam);
			rect.left = 0;
			rect.top = 0;
			rect.right = cxScreen;
			rect.bottom = cyScreen;
			hdc = GetDC(hwnd);
			hdcMem = CreateCompatibleDC(hdc);
			hBitmap = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);
			ReleaseDC(hwnd, hdc);
			SelectObject(hdcMem, hBitmap);
			hBrush = CreateSolidBrush(0);
			FillRect(hdcMem, &rect, hBrush);
			NoErase = 2048; // 256*8
			if ((cxScreen == Buf[9]) && (cyScreen == Buf[10]))
			{//same resolution as before
				x1 = Buf[0];
				x2 = Buf[1];
				Y1 = Buf[2];
				y2 = Buf[3];
				x1inc = x1incErase = Buf[4];
				x2inc = x2incErase = Buf[5];
				y1inc = y1incErase = Buf[6];
				y2inc = y2incErase = Buf[7];
			}
			x1Erase = x1;
			x2Erase = x2;
			y1Erase = Y1;
			y2Erase = y2;
			SetTimer(hwnd, 123, 1, NULL);//123 is an ID and 1 means send a WM_TIMER message every millisecond
		}
		break;

	case WM_TIMER:
		InvalidateRect(hwnd, NULL, FALSE);
		break;

	case WM_KEYDOWN:
		DestroyWindow(hwnd);
		break;

	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0, SRCCOPY);
		Color = (Blue << 16) | (Green << 8) | Red;
		hPen = CreatePen(PS_SOLID, 1, Color);
		SelectObject(hdcMem, hPen);

		if (CurrentColor == goingred) {
			if (Red == 0xFF)
				CurrentColor = goingyellow;
			else
				Red++;
		}
		else if (CurrentColor == goingyellow) {
			if (Green == 0xFF)
				CurrentColor = goinggreen;
			else
				Green++;
		}
		else if (CurrentColor == goinggreen) {
			if (Red == 0)
				CurrentColor = goingbluegreen;
			else
				Red--;
		}
		else if (CurrentColor == goingbluegreen) {
			if (Blue == 0xFF)
				CurrentColor = goingblue;
			else
				Blue++;
		}
		else if (CurrentColor == goingblue) {
			if (Green == 0)
				CurrentColor = goingpurple;
			else
				Green--;
		}
		else if (CurrentColor == goingpurple) {
			if (Red == 0xFF)
				CurrentColor = goingredfrompurple;
			else
				Red++;
		}
		else if (CurrentColor == goingredfrompurple) {
			if (Blue == 0) {
				CurrentColor = goingyellow;
			}
			else {
				if (Blue == 0x80)
					NoErase = 0;
				Blue--;
			}
		}
		MoveToEx(hdcMem, x1, Y1, NULL);
		LineTo(hdcMem, x2, y2);
		DeleteObject(hPen);
		x1 += x1inc;
		x2 += x2inc;
		Y1 += y1inc;
		y2 += y2inc;
		if ((x1 < 3) || (x1 > cxScreen - 3))
			x1inc = -x1inc;
		if ((x2 < 3) || (x2 > cxScreen - 3))
			x2inc = -x2inc;
		if ((Y1 < 3) || (Y1 > cyScreen - 3))
			y1inc = -y1inc;
		if ((y2 < 3) || (y2 > cyScreen - 3))
			y2inc = -y2inc;
		if (NoErase == 0)
		{
			hPen2 = CreatePen(PS_SOLID, 1, BLACK);
			SelectObject(hdcMem, hPen2);
			MoveToEx(hdcMem, x1Erase, y1Erase, NULL);
			LineTo(hdcMem, x2Erase, y2Erase);
			DeleteObject(hPen2);
			x1Erase += x1incErase;
			x2Erase += x2incErase;
			y1Erase += y1incErase;
			y2Erase += y2incErase;
			if ((x1Erase < 3) || (x1Erase > cxScreen - 3))
				x1incErase = -x1incErase;
			if ((x2Erase < 3) || (x2Erase > cxScreen - 3))
				x2incErase = -x2incErase;
			if ((y1Erase < 3) || (y1Erase > cyScreen - 3))
				y1incErase = -y1incErase;
			if ((y2Erase < 3) || (y2Erase > cyScreen - 3))
				y2incErase = -y2incErase;
		}
		EndPaint(hwnd, &ps);
		break;

	case WM_DESTROY:
		ShowCursor(TRUE);
		KillTimer(hwnd, 123);
		Buf[0] = x1;
		Buf[1] = x2;
		Buf[2] = Y1;
		Buf[3] = y2;
		Buf[4] = x1inc;
		Buf[5] = x2inc;
		Buf[6] = y1inc;
		Buf[7] = y2inc;
//		Buf[8] = c;
		Buf[9] = cxScreen;
		Buf[10] = cyScreen;
		hFile = CreateFile(Filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
		WriteFile(hFile, Buf, 44, &dwBytesWritten, NULL);
		CloseHandle(hFile);
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	char szAppName[] = "MOIRE";
	MSG          msg;
	WNDCLASS     wndclass;

	wndclass.style         = CS_HREDRAW|CS_VREDRAW;
	wndclass.lpfnWndProc   = WndProc;
	wndclass.cbClsExtra    = 0;
	wndclass.cbWndExtra    = 0;
	wndclass.hInstance     = hInstance;
	wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wndclass.lpszMenuName  = NULL;
	wndclass.lpszClassName = szAppName;

	if (!RegisterClass(&wndclass))
		return 0;

	hwnd = CreateWindow(szAppName, NULL,
		WS_POPUP,
		0, 0, 0, 0,
		NULL, NULL, hInstance, NULL);

	ShowWindow(hwnd, SW_SHOWMAXIMIZED);
	UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return (int)msg.wParam;
}
