/* A fractals program. */ #include #include void ComplexSquare( double *x, double *y ); void ComplexAdd( double x, double y, double cx, double cy, double *xAns, double *yAns ); void Mandelbrot( HDC hdc ); void Dragon( HDC hdc ); LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); char szWinName[] = "WinFractal"; /* name of window class */ char str[255] = ""; /* holds output string */ int maxX, maxY, /* screen dimensions */ xCoordinate, yCoordinate; /* current position of the pen */ int i = 0, myRefreshFlag = 0, xCounter = 0, whichFractal = 1, oldWhichFractal, oldi, oldxCounter; HDC memdc; /* handle of memory DC */ HBITMAP hbit; /* handle of compatible bitmap */ HBRUSH hbrush, hOldbrush; /* handles of brushes */ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode) { HWND hwnd; MSG msg; WNDCLASSEX wcl; /* Define a window class. */ wcl.cbSize = sizeof(WNDCLASSEX); wcl.hInstance = hThisInst; /* handle to this instance */ wcl.lpszClassName = szWinName; /* window class name */ wcl.lpfnWndProc = WindowFunc; /* window function */ wcl.style = 0; /* default style */ wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION);/* standard icon */ wcl.hIconSm = LoadIcon(NULL, IDI_WINLOGO); /* small icon */ wcl.hCursor = LoadCursor(NULL, IDC_ARROW); /* cursor style */ wcl.lpszMenuName = NULL; /* no menu */ wcl.cbClsExtra = 0; /* no extra */ wcl.cbWndExtra = 0; /* information needed */ /* Make the window white. */ wcl.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); /* Register the window class. */ if(!RegisterClassEx(&wcl)) return 0; /* Now that a window class has been registered, a window can be created. */ hwnd = CreateWindow( szWinName, /* name of window class */ "Fractals", /* title */ WS_OVERLAPPEDWINDOW, /* window style - normal */ CW_USEDEFAULT, /* X coordinate - let Windows decide */ CW_USEDEFAULT, /* Y coordinate - let Windows decide */ CW_USEDEFAULT, /* width - let Windows decide */ CW_USEDEFAULT, /* height - let Windows decide */ HWND_DESKTOP, /* no parent window */ NULL, /* no menu */ hThisInst, /* handle of this instance of the program */ NULL /* no additional arguments */ ); /* Display the window. */ ShowWindow(hwnd, nWinMode); UpdateWindow(hwnd); /* Create the message loop. */ while(TRUE) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); /* translate keyboard messages */ DispatchMessage(&msg); /* return control to Windows 98 */ } else { if(i <= maxY) { switch(whichFractal) { case 1: Mandelbrot(memdc); break; case 2: Dragon(memdc); break; default: break; } myRefreshFlag = 1; InvalidateRect(hwnd, NULL, 0); /* update screen */ } } } return msg.wParam; } /* This function is called by Windows 98 and is passed messages from the message queue. */ LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT paintstruct; switch(message) { case WM_CREATE: /* get screen coordinates */ maxX = GetSystemMetrics(SM_CXSCREEN); maxY = GetSystemMetrics(SM_CYSCREEN); /* initial position of the pen */ xCoordinate = 0; yCoordinate = 0; /* make a compatible memory image device */ hdc = GetDC(hwnd); memdc = CreateCompatibleDC(hdc); hbit = CreateCompatibleBitmap(hdc, maxX, maxY); SelectObject(memdc, hbit); hbrush = (HBRUSH) GetStockObject(WHITE_BRUSH); SelectObject(memdc, hbrush); PatBlt(memdc, 0, 0, maxX, maxY, PATCOPY); ReleaseDC(hwnd, hdc); strcpy(str, "Welcome to Ebo. (Alt-F4 to Quit)"); TextOut(memdc, maxX/5, maxY/3, str, strlen(str)); break; case WM_PAINT: /* process a repaint request */ hdc = BeginPaint(hwnd, &paintstruct); /* get DC */ if(myRefreshFlag == 1) { BitBlt(hdc, xCounter, 0, 2, maxY, memdc, xCounter, 0, SRCCOPY); xCounter += 2; myRefreshFlag = 0; } else BitBlt(hdc, paintstruct.rcPaint.left, paintstruct.rcPaint.top, paintstruct.rcPaint.right-paintstruct.rcPaint.left, paintstruct.rcPaint.bottom-paintstruct.rcPaint.top, memdc, paintstruct.rcPaint.left, paintstruct.rcPaint.top, SRCCOPY); /* now, copy memory image onto screen */ EndPaint(hwnd, &paintstruct); /* release DC */ break; case WM_LBUTTONDOWN: oldWhichFractal = whichFractal; oldi = i; oldxCounter = xCounter; whichFractal = 9; break; case WM_LBUTTONUP: whichFractal = oldWhichFractal; myRefreshFlag = 1; i = oldi; xCounter = oldxCounter; break; case WM_CHAR: switch((char)wParam) { case '1': whichFractal = 1; myRefreshFlag = 1; i = 1; xCounter = 0; break; case '2': whichFractal = 2; myRefreshFlag = 1; i = 1; xCounter = 0; break; } break; case WM_DESTROY: /* terminate the program */ DeleteDC(memdc); PostQuitMessage(0); break; default: /* Let Windows 98 process any messages not specified in the preceding switch statement. */ return DefWindowProc(hwnd, message, wParam, lParam); } return 0; } void ComplexSquare( double *x, double *y ) { register double temp1, temp2; temp1 = *x * *x - *y * *y; temp2 = *x * *y + *x * *y; *x = temp1; *y = temp2; } void ComplexAdd( double x, double y, double cx, double cy, double *xAns, double *yAns ) { *xAns = x + cx; *yAns = y + cy; } void Mandelbrot(HDC hdc) { static double zoom = 2.0, escape = 4.0; register double scale, magnitude, cx, cy; double x, y; register int j, iter, color, offsetY = 120; scale = 2.0*zoom/maxY; while( i++ <= maxY ) { for(j=0; j <= maxY; j++ ) { x = 0; y = 0; cx = scale * i - zoom; cy = zoom - scale * j; magnitude = 0; iter = 0; while ( (iter < 32) && (magnitude < escape) ) { ComplexSquare( &x, &y ); ComplexAdd( x, y, cx, cy, &x, &y ); magnitude = x*x + y*y; iter++; } if ( magnitude > escape) { color = iter / 6; switch (color) { case 0 : SetPixel(hdc, i, j-offsetY, RGB(0,0,0)); // Black break; case 1 : SetPixel(hdc, i, j-offsetY, RGB(255,0,0)); // Red break; case 2 : SetPixel(hdc, i, j-offsetY, RGB(0,0,255)); // Blue break; case 3 : SetPixel(hdc, i, j-offsetY, RGB(0, 255, 0)); // Green break; case 4 : SetPixel(hdc, i, j-offsetY, RGB(255, 0, 255)); // Purple break; case 5 : SetPixel(hdc, i, j-offsetY, RGB(0, 255, 255)); // Magenta break; default : SetPixel(hdc, i, j-offsetY, RGB(0, 0, 0)); // Black break; } } else SetPixel(hdc, i, j-offsetY, RGB(255, 255, 0)); // Yellow } if(i%2) break; } } void Dragon(HDC hdc) { static double zoom = 2.0, attract = .0001; register double scale, magnitude; double x, y; register int j, iter, color, offsetY = 120; BOOL goAhead; scale = 2.0*zoom/maxY; while( i++ <= maxY ) { for( j = 0; j <= maxY; j++ ) { x = scale * i - zoom; y = zoom - scale * j; goAhead = TRUE; magnitude = 0; iter = 0; while ( goAhead == TRUE ) { ComplexSquare( &x, &y ); ComplexAdd( x, y, .360284, .100376, &x, &y ); magnitude = x*x + y*y; if ( magnitude < attract) goAhead = FALSE; else { if ( (magnitude < 100) && (iter < 32) ) iter++; else { color = iter / 4; switch (color) { case 0 : SetPixel(hdc, i, j-offsetY, RGB(128,128,128)); // Black break; case 1 : SetPixel(hdc, i, j-offsetY, RGB(255,0,0)); // Red break; case 2 : SetPixel(hdc, i, j-offsetY, RGB(0,0,255)); // Blue break; case 3 : SetPixel(hdc, i, j-offsetY, RGB(0, 255, 0)); // Green break; case 4 : SetPixel(hdc, i, j-offsetY, RGB(255, 0, 255)); // Purple break; case 5 : SetPixel(hdc, i, j-offsetY, RGB(0, 255, 255)); // Magenta break; default : SetPixel(hdc, i, j-offsetY, RGB(128, 10, 128)); // Black break; } goAhead = FALSE; } } } } if(i%2) break; } }