Hi Marc, I thought your idea was pretty neat, but unfortunately I do not have VS2005 or the .NET 2.0 runtime so it did not work on my machine. I slapped together a win32 c++ version but I did not think it deserved an article of it's own so I am posting the source here for anyone who wants it.
Hope you don't mind;)
Merry Christmas!
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <math.h>
#include <time.h>
#include <list>
using namespace std;
const double rangle = 0.0 - 60.0 * 3.1415926535897932384626433832795 / 180.0;
const int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
const int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
const int step = 1;
HWND MainWindow = NULL;
HDC DC1, DC2;
HBITMAP bmp1, bmp2;
class DPOINT
{
public:
DPOINT() { x = 0.0; y = 0.0; }
DPOINT(double a, double b) { x = a; y = b; }
double x;
double y;
operator POINT() { POINT pt; pt.x = (int)x; pt.y = (int)y; return pt; }
DPOINT &operator =(const DPOINT &pt) { x = pt.x; y = pt.y; return *this; }
};
list<DPOINT> Split(DPOINT one, DPOINT two)
{
list<DPOINT> pts;
double originalheight = two.y - one.y;
double originalwidth = two.x - one.x;
double originallength = sqrt((originalheight * originalheight) + (originalwidth * originalwidth));
if (originallength >= 5.0)
{
double length = originallength / 3;
double angle = atan2(originalheight, originalwidth) + rangle;
DPOINT p1 (one.x + originalwidth / 3, one.y + originalheight / 3);
DPOINT p2 (p1.x + length * cos(angle), p1.y + length * sin(angle));
DPOINT p3 (one.x + originalwidth * 2 / 3, one.y + originalheight * 2 / 3);
pts.push_back(p1);
pts.push_back(p2);
pts.push_back(p3);
}
return pts;
}
class Flake
{
public:
Flake() { PenColour = RGB(0, 0, 0); }
void Create()
{
DPOINT Point1, Point2;
do {
Point1 = DPOINT(0, 0);
Point2 = DPOINT(rand() % 300, rand() % 300);
points = Split(Point1, Point2);
} while (points.empty());
list<DPOINT> temp;
bool Continue = true;
list<DPOINT>::iterator it = points.begin();
while (Continue)
{
Point1 = *it++;
if (points.end() == it)
it = points.begin();
Point2 = *it;
temp = Split(Point1, Point2);
Continue = !temp.empty();
points.splice(it, temp);
}
PenColour = RGB(rand() % 256, rand() % 256, rand() % 256);
}
void Draw(HDC DC, POINT pt)
{
point.x = pt.x;
point.y = pt.y;
int s = SaveDC(DC);
HPEN Pen = CreatePen(PS_SOLID, 1, PenColour);
SelectObject(DC, Pen);
SetROP2(DC, R2_XORPEN);
MoveToEx(DC, pt.x + points.front().x, pt.y + points.front().y, NULL);
for (list<DPOINT>::iterator it = points.begin(); it != points.end(); ++it)
LineTo(DC, pt.x + (*it).x, pt.y + (*it).y);
LineTo(DC, pt.x + points.front().x, pt.y + points.front().y);
RestoreDC(DC, s);
DeleteObject(Pen);
}
void Erase(HDC DC)
{
Draw(DC, point);
}
protected:
list<DPOINT> points;
COLORREF PenColour;
POINT point;
};
LRESULT CALLBACK WndProc(HWND hWnd,
UINT nMsg,
WPARAM wp,
LPARAM lp)
{
switch (nMsg)
{
case WM_SETCURSOR:
ShowCursor(FALSE);;
break;
case WM_CREATE:
{
HDC ScreenDC = GetDC(NULL);
DC1 = CreateCompatibleDC(ScreenDC);
DC2 = CreateCompatibleDC(ScreenDC);
bmp1 = CreateCompatibleBitmap(ScreenDC, ScreenWidth, ScreenHeight + 400);
bmp2 = CreateCompatibleBitmap(ScreenDC, ScreenWidth, ScreenHeight + 400);
ReleaseDC(NULL, ScreenDC);
SelectObject(DC1, bmp1);
SelectObject(DC2, bmp2);
RECT rc = {0, 0, ScreenWidth, ScreenHeight + 400};
HBRUSH br = CreateSolidBrush(RGB(0, 255, 255));
FillRect(DC1, &rc, br);
DeleteObject(br);
}
break;
case WM_TIMER:
{
static int counter = 0;
if (wp == 1)
{
HBRUSH br = CreateSolidBrush(RGB(0, 255, 255));
RECT rc = {0, 0, ScreenWidth, step * counter};
FillRect(DC1, &rc, br);
DeleteObject(br);
BitBlt(DC1, 0, 0, ScreenWidth, ScreenHeight + 400, DC2, 0, 0, SRCCOPY);
Flake f;
f.Create();
POINT pt = { rand() % ScreenWidth, 200 };
f.Draw(DC1, pt);
counter = 0;
}
else if (wp == 2)
{
BitBlt(DC2, 0, step * counter++, ScreenWidth, ScreenHeight + 400, DC1, 0, 0, SRCCOPY);
RedrawWindow(MainWindow, NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps = {0};
HDC DC = BeginPaint(MainWindow, &ps);
if (DC)
{
BitBlt(DC,
0,
0,
ScreenWidth,
ScreenHeight,
DC2,
0,
400,
SRCCOPY);
EndPaint(MainWindow, &ps);
}
}
break;
default:
return DefWindowProc(hWnd, nMsg, wp, lp);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HBRUSH bkBrush = CreateSolidBrush(RGB(0, 255, 255));
WNDCLASS WndClass = {0};
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc;
WndClass.hbrBackground = bkBrush;
WndClass.lpszClassName = "SnowFlake";
if (!RegisterClass(&WndClass))
throw ("Failed to register main window class");
MainWindow = CreateWindowEx(0, "SnowFlake",
"SnowFlake",
WS_POPUP | WS_VISIBLE,
0, 0, ScreenWidth, ScreenHeight,
NULL,
NULL,
hInstance,
NULL);
if (MainWindow == NULL)
throw ("Failed create main window");
ShowWindow(MainWindow, SW_SHOW);
SetTimer(MainWindow, 1, 1500, NULL);
SetTimer(MainWindow, 2, 10, NULL);
MSG msg = {0};
while (GetMessage(&msg, MainWindow, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
-- modified at 5:03 Sunday 25th December, 2005
fixed where html mangled code
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" - mYkel - 21 Jun '04
"There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05
Within you lies the power for good - Use it!
|