|
|
1.1 ! root 1: /**************************************************************************** ! 2: ! 3: MANDEL.C -- ! 4: ! 5: Main code for the Windows Mandelbrot Set distributed drawing program. ! 6: ! 7: Copyright (C) 1990 Microsoft Corporation. ! 8: ! 9: This code sample is provided for demonstration purposes only. ! 10: Microsoft makes no warranty, either express or implied, ! 11: as to its usability in any given situation. ! 12: ! 13: ****************************************************************************/ ! 14: ! 15: #include <sys\types.h> ! 16: #include <sys\stat.h> ! 17: #include <direct.h> ! 18: #include <dos.h> ! 19: #include <string.h> ! 20: #include <ctype.h> ! 21: #include <malloc.h> // malloc, free ! 22: #include <stdio.h> ! 23: #include <stdlib.h> ! 24: #include <time.h> ! 25: ! 26: #ifdef RPC ! 27: #include <rpc.h> ! 28: #include "mdlrpc.h" ! 29: #endif ! 30: ! 31: #include <windows.h> /* Required for all Windows applications */ ! 32: #include "mandel.h" /* Specific to this program */ ! 33: ! 34: #define MENUNAME "MandelMenu" ! 35: #define CLASSNAME "MandelClass" ! 36: #define ABOUTBOX "AboutBox" ! 37: #define SAVEBOX "SAVEBOX" ! 38: ! 39: ! 40: #define POLL_TIME 100 ! 41: #define LINES 4 ! 42: ! 43: #ifdef RPC ! 44: char szTitle[] = "Mandelbrot RPC"; ! 45: #else ! 46: char szTitle[] = "Mandelbrot Standalone"; ! 47: #endif ! 48: ! 49: char szBitmap[] = "Mandel"; ! 50: ! 51: CPOINT cptUL = { (double) -2.05, (double) 1.4 }; ! 52: double dPrec = (double) .01; ! 53: ! 54: void PaintLine( HWND, svr_table *, HDC, int); ! 55: COLORREF MapColor( DWORD, DWORD ); ! 56: void DrawRect( HWND, PRECT, BOOL, HDC); ! 57: long get_drivemap(void); ! 58: void set_dlgitems(HWND, char *, long); ! 59: BOOL update_curdir(HWND, char *, long); ! 60: char * getdcwd( int, char *, unsigned); ! 61: void set_filename( HWND ); ! 62: BOOL munge_path( char *); ! 63: ! 64: HANDLE hInst; /* current instance */ ! 65: ! 66: int iLines = LINES; ! 67: svr_table SvrTable[20]; ! 68: int SvrTableSz = 0; ! 69: ! 70: #define NCOLORS 11 ! 71: int fContinueZoom = TRUE; ! 72: int fZoomIn = TRUE; ! 73: int Histogram[4][4][NCOLORS+1] = {0}; /* split current picture into 16 regions */ ! 74: /* zoom on most complex region; region with most colors represented */ ! 75: int ColorCount[4][4] = {0}; ! 76: int Max[4][4] = { 0 }; ! 77: int iHistMaxI = 2; ! 78: int iHistMaxJ = 3; ! 79: RECT rcZoom; ! 80: BOOL fRectDefined = FALSE; ! 81: ! 82: ! 83: /* ! 84: * ! 85: * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) ! 86: * ! 87: * PURPOSE: Calls initialization function, processes message loop ! 88: * ! 89: * COMMENTS: ! 90: * ! 91: * Windows recognizes this function by name as the initial entry point ! 92: * for the program. This function calls the application initialization ! 93: * routine, if no other instance of the program is running, and always ! 94: * calls the instance initialization routine. It then executes a message ! 95: * retrieval and dispatch loop that is the top-level control structure ! 96: * for the remainder of execution. The loop is terminated when a WM_QUIT ! 97: * message is received, at which time this function exits the application ! 98: * instance by returning the value passed by PostQuitMessage(). ! 99: * ! 100: * If this function must abort before entering the message loop, it ! 101: * returns the conventional value NULL. ! 102: * ! 103: */ ! 104: ! 105: int APIENTRY WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow) ! 106: HANDLE hInstance; /* current instance */ ! 107: HANDLE hPrevInstance; /* previous instance */ ! 108: LPSTR lpCmdLine; /* command line */ ! 109: int nCmdShow; /* show-window type (open/icon) */ ! 110: { ! 111: MSG msg; /* message */ ! 112: ! 113: UNREFERENCED_PARAMETER(lpCmdLine); ! 114: ! 115: // add a runtime exception handler for RPC version ! 116: // see below for additional exception handling code ! 117: #ifdef RPC ! 118: RpcTryExcept { ! 119: #endif ! 120: ! 121: if (!hPrevInstance) /* Other instances of app running? */ ! 122: if (!InitApplication(hInstance)) /* Initialize shared things */ ! 123: return (FALSE); /* Exits if unable to initialize */ ! 124: ! 125: /* Perform initializations that apply to a specific instance */ ! 126: ! 127: if (!InitInstance(hInstance, nCmdShow)) ! 128: return (FALSE); ! 129: ! 130: /* Acquire and dispatch messages until a WM_QUIT message is received. */ ! 131: ! 132: ! 133: while (GetMessage(&msg, /* message structure */ ! 134: NULL, /* handle of window receiving the message */ ! 135: 0, /* lowest message to examine */ ! 136: 0)) /* highest message to examine */ ! 137: { ! 138: TranslateMessage(&msg); /* Translates virtual key codes */ ! 139: DispatchMessage(&msg); /* Dispatches message to window */ ! 140: } ! 141: ! 142: return (msg.wParam); /* Returns the value from PostQuitMessage */ ! 143: ! 144: // add a runtime exception handler for RPC version ! 145: // see above for additional exception handling code ! 146: #ifdef RPC ! 147: } // end of RpcTryExcept statements ! 148: RpcExcept(1) { ! 149: sprintf(pszFail, "Please start the server application."); ! 150: MessageBox(msg.hwnd, pszFail, "Mandel Server Not Started", ! 151: MB_ICONHAND | MB_SYSTEMMODAL); ! 152: } ! 153: RpcEndExcept ! 154: #endif ! 155: ! 156: } // end WinMain ! 157: ! 158: ! 159: ! 160: ! 161: /* ! 162: * FUNCTION: InitApplication(HANDLE) ! 163: * ! 164: * PURPOSE: Initializes window data and registers window class ! 165: * ! 166: * COMMENTS: ! 167: * ! 168: * This function is called at initialization time only if no other ! 169: * instances of the application are running. This function performs ! 170: * initialization tasks that can be done once for any number of running ! 171: * instances. ! 172: * ! 173: * In this case, we initialize a window class by filling out a data ! 174: * structure of type WNDCLASS and calling the Windows RegisterClass() ! 175: * function. Since all instances of this application use the same window ! 176: * class, we only need to do this when the first instance is initialized. ! 177: */ ! 178: ! 179: BOOL InitApplication(hInstance) ! 180: HANDLE hInstance; /* current instance */ ! 181: { ! 182: WNDCLASS wc; ! 183: ! 184: /* Fill in window class structure with parameters that describe the */ ! 185: /* main window. */ ! 186: ! 187: wc.style = 0; /* Class style(s). */ ! 188: wc.lpfnWndProc = (WNDPROC)MainWndProc; /* Function to retrieve messages for */ ! 189: /* windows of this class. */ ! 190: wc.cbClsExtra = 0; /* No per-class extra data. */ ! 191: wc.cbWndExtra = 0; /* No per-window extra data. */ ! 192: wc.hInstance = hInstance; /* Application that owns the class. */ ! 193: wc.hIcon = LoadIcon(hInstance, "RPC_ICON"); ! 194: wc.hCursor = LoadCursor(NULL, IDC_ARROW); ! 195: wc.hbrBackground = GetStockObject(WHITE_BRUSH); ! 196: wc.lpszMenuName = MENUNAME; /* Name of menu resource in .RC file. */ ! 197: wc.lpszClassName = CLASSNAME; /* Name used in call to CreateWindow. */ ! 198: ! 199: /* Register the window class and return success/failure code. */ ! 200: ! 201: return (RegisterClass(&wc)); ! 202: ! 203: } ! 204: ! 205: ! 206: ! 207: /* ! 208: * FUNCTION: InitInstance(HANDLE, int) ! 209: * ! 210: * PURPOSE: Saves instance handle and creates main window. ! 211: * ! 212: * COMMENTS: ! 213: * ! 214: * This function is called at initialization time for every instance of ! 215: * this application. This function performs initialization tasks that ! 216: * cannot be shared by multiple instances. ! 217: * ! 218: * In this case, we save the instance handle in a static variable and ! 219: * create and display the main program window. ! 220: */ ! 221: ! 222: BOOL InitInstance(hInstance, nCmdShow) ! 223: HANDLE hInstance; /* Current instance identifier. */ ! 224: int nCmdShow; /* Param for first ShowWindow() call. */ ! 225: { ! 226: HWND hWnd; /* Main window handle. */ ! 227: RECT rc; ! 228: ! 229: /* Save the instance handle in static variable, which will be used in */ ! 230: /* many subsequence calls from this application to Windows. */ ! 231: ! 232: hInst = hInstance; ! 233: ! 234: /* Create a main window for this application instance. */ ! 235: ! 236: hWnd = CreateWindow( ! 237: CLASSNAME, /* See RegisterClass() call. */ ! 238: szTitle, /* Text for window title bar. */ ! 239: WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX, ! 240: CW_USEDEFAULT, /* Default horizontal position. */ ! 241: CW_USEDEFAULT, /* Default vertical position. */ ! 242: WIDTH, /* Default width. */ ! 243: HEIGHT, /* Default height. */ ! 244: NULL, /* Overlapped windows have no parent. */ ! 245: NULL, /* Use the window class menu. */ ! 246: hInstance, /* This instance owns this window. */ ! 247: NULL /* Pointer not needed. */ ! 248: ); ! 249: ! 250: /* If window could not be created, return "failure" */ ! 251: ! 252: if (!hWnd) ! 253: return (FALSE); ! 254: ! 255: /* Make the window visible; update its client area; and return "success" */ ! 256: ! 257: ShowWindow(hWnd, nCmdShow); /* Show the window */ ! 258: UpdateWindow(hWnd); /* Sends WM_PAINT message */ ! 259: ! 260: rc.top = rc.left = 0; ! 261: rc.bottom = HEIGHT-1; ! 262: rc.right = WIDTH-1; ! 263: ! 264: SetNewCalc(cptUL, dPrec, rc); ! 265: ! 266: return (TRUE); /* Returns the value from PostQuitMessage */ ! 267: } ! 268: ! 269: ! 270: ! 271: /* ! 272: * FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG) ! 273: * ! 274: * PURPOSE: Processes messages ! 275: * ! 276: * MESSAGES: ! 277: * ! 278: * WM_COMMAND - application menu (About dialog box) ! 279: * WM_DESTROY - destroy window ! 280: * ! 281: * COMMENTS: ! 282: * ! 283: * To process the IDM_ABOUT message, call MakeProcInstance() to get ! 284: * the current instance address of the About() function, then call ! 285: * DialogBox to create the box according to the information in the ! 286: * MANDEL.RC file and turn control over to the About() function. ! 287: * When it returns, free the intance address. ! 288: */ ! 289: ! 290: LONG APIENTRY MainWndProc( ! 291: HWND hWnd, /* window handle */ ! 292: UINT message, /* type of message */ ! 293: UINT wParam, /* additional information */ ! 294: LONG lParam) /* additional information */ ! 295: { ! 296: FARPROC lpProcAbout; /* pointer to the "About" function */ ! 297: PAINTSTRUCT ps; ! 298: HDC hdc; ! 299: static HDC hdcMem; ! 300: static HBITMAP hbmMem; ! 301: static int width; ! 302: static int height; ! 303: RECT rc; ! 304: static BOOL fButtonDown = FALSE; ! 305: static POINT pSelected; ! 306: POINT pMove; ! 307: int iWidthNew; ! 308: int iHeightNew; ! 309: static int miOldLines; ! 310: double scaling; ! 311: ! 312: switch (message) ! 313: { ! 314: ! 315: case WM_CREATE: ! 316: if (!InitRemote(hWnd)) ! 317: return FALSE; ! 318: ! 319: InitHistogram(); ! 320: ! 321: hdc = GetDC(hWnd); ! 322: hdcMem = CreateCompatibleDC(hdc); ! 323: GetWindowRect(hWnd, &rc); ! 324: width = rc.right - rc.left; ! 325: height = rc.bottom - rc.top; ! 326: hbmMem = CreateCompatibleBitmap(hdc, width, height); ! 327: SelectObject(hdcMem, hbmMem); ! 328: ! 329: ReleaseDC(hWnd,hdc); ! 330: ! 331: rc.left = rc.top = 0; ! 332: rc.right = width+1; ! 333: rc.bottom = height + 1; ! 334: FillRect(hdcMem, &rc, GetStockObject(WHITE_BRUSH)); ! 335: ! 336: SetTimer(hWnd, 1, POLL_TIME, NULL); // set timer for polls ! 337: ! 338: CheckMenuItem(GetMenu(hWnd), IDM_4LINES, MF_CHECKED); ! 339: CheckMenuItem(GetMenu(hWnd), IDM_CONTINUOUS, MF_CHECKED); ! 340: miOldLines = IDM_4LINES; // save to uncheck ! 341: ! 342: break; ! 343: ! 344: case WM_PAINT: ! 345: hdc = BeginPaint(hWnd, &ps); ! 346: BitBlt(hdc, ps.rcPaint.left, ! 347: ps.rcPaint.top, ! 348: ps.rcPaint.right - ps.rcPaint.left, ! 349: ps.rcPaint.bottom - ps.rcPaint.top, ! 350: hdcMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); ! 351: EndPaint(hWnd, &ps); ! 352: break; ! 353: ! 354: case WM_COMMAND: /* message: command from application menu */ ! 355: switch(wParam) ! 356: { ! 357: ! 358: case IDM_ABOUT: ! 359: lpProcAbout = MakeProcInstance((FARPROC)About, hInst); ! 360: ! 361: DialogBox(hInst, /* current instance */ ! 362: ABOUTBOX, /* resource to use */ ! 363: hWnd, /* parent handle */ ! 364: (WNDPROC)lpProcAbout); /* About() instance address */ ! 365: ! 366: FreeProcInstance(lpProcAbout); ! 367: break; ! 368: ! 369: case IDM_ZOOMOUT: ! 370: if (dPrec > (double)MAXPREC) // don't allow the zoom out ! 371: break; ! 372: rcZoom.left = WIDTH/4 + (WIDTH/8); // center square ! 373: rcZoom.top = HEIGHT/4 + (HEIGHT/8); ! 374: rcZoom.right = rcZoom.left + (WIDTH/4); ! 375: rcZoom.bottom = rcZoom.top + (HEIGHT/4); ! 376: ! 377: cptUL.real -= (rcZoom.left * dPrec); // inverse of zoom in ! 378: cptUL.imag += (rcZoom.top * dPrec); ! 379: iWidthNew = (rcZoom.right - rcZoom.left + 1); ! 380: iHeightNew = (rcZoom.bottom - rcZoom.top + 1); ! 381: scaling = ! 382: ( (double) ((iWidthNew > iHeightNew) ? iWidthNew : iHeightNew) ! 383: / (double)width); ! 384: dPrec /= scaling; ! 385: ! 386: rc.left = rc.top = 0; ! 387: rc.bottom = height - 1; ! 388: rc.right = width - 1; ! 389: ! 390: SetNewCalc(cptUL, dPrec, rc); ! 391: fRectDefined = FALSE; ! 392: DoSomeWork(hWnd, FALSE); ! 393: break; ! 394: ! 395: case IDM_ZOOMIN: // zoom in on selected rectangle ! 396: // if no rectangle, don't zoom in ! 397: if (!fRectDefined) ! 398: break; ! 399: if (dPrec < (double)MINPREC) // don't allow zoom in ! 400: break; ! 401: DrawRect(hWnd, &rcZoom, TRUE, hdcMem); // draw new rect ! 402: ! 403: // calculate new upper-left ! 404: cptUL.real += (rcZoom.left * dPrec); ! 405: cptUL.imag -= (rcZoom.top * dPrec); ! 406: ! 407: iWidthNew = (rcZoom.right - rcZoom.left + 1); ! 408: iHeightNew = (rcZoom.bottom - rcZoom.top + 1); ! 409: scaling = ! 410: ( (double) ((iWidthNew > iHeightNew) ? iWidthNew : iHeightNew) ! 411: / (double)width); ! 412: ! 413: dPrec *= scaling; ! 414: ! 415: rc.left = rc.top = 0; ! 416: rc.bottom = height - 1; ! 417: rc.right = width - 1; ! 418: ! 419: SetNewCalc( cptUL, dPrec, rc); ! 420: IncPictureID(); ! 421: ! 422: fRectDefined = FALSE; ! 423: DoSomeWork(hWnd, FALSE); ! 424: break; ! 425: ! 426: case IDM_CONTINUOUS: // continuous zoom in ! 427: if (fContinueZoom == TRUE) { ! 428: CheckMenuItem(GetMenu(hWnd), IDM_CONTINUOUS, MF_UNCHECKED); ! 429: fContinueZoom = FALSE; ! 430: } ! 431: else { ! 432: CheckMenuItem(GetMenu(hWnd), IDM_CONTINUOUS, MF_CHECKED); ! 433: fContinueZoom = TRUE; ! 434: } ! 435: break; ! 436: ! 437: case IDM_REDRAW: ! 438: if (fContinueZoom == TRUE) ! 439: InitHistogram(); ! 440: rc.left = rc.top = 0; ! 441: rc.right = width+1; ! 442: rc.bottom = height + 1; ! 443: FillRect(hdcMem, &rc, GetStockObject(WHITE_BRUSH)); ! 444: InvalidateRect(hWnd, NULL, TRUE); ! 445: ! 446: rc.left = rc.top = 0; ! 447: rc.bottom = height - 1; ! 448: rc.right = width - 1; ! 449: SetNewCalc( cptUL, dPrec, rc); ! 450: ! 451: fRectDefined = FALSE; ! 452: DoSomeWork(hWnd, FALSE); ! 453: break; ! 454: ! 455: case IDM_EXIT: ! 456: DestroyWindow(hWnd); ! 457: break; ! 458: ! 459: case IDM_TOP: ! 460: cptUL.real = (double) -2.05; ! 461: cptUL.imag = (double) 1.4; ! 462: dPrec = .01; ! 463: ! 464: rc.left = rc.top = 0; ! 465: rc.bottom = height - 1; ! 466: rc.right = width - 1; ! 467: SetNewCalc( cptUL, dPrec, rc); ! 468: cPictureID = 0; // incremented past original ! 469: ! 470: fRectDefined = FALSE; ! 471: DoSomeWork(hWnd, FALSE); ! 472: break; ! 473: ! 474: case IDM_1LINE: ! 475: case IDM_2LINES: ! 476: case IDM_4LINES: ! 477: case IDM_8LINES: ! 478: case IDM_16LINES: ! 479: case IDM_32LINES: ! 480: ! 481: CheckMenuItem(GetMenu(hWnd), miOldLines, MF_UNCHECKED); ! 482: miOldLines = wParam; ! 483: switch(wParam) ! 484: { ! 485: case IDM_1LINE: ! 486: iLines = 1; ! 487: break; ! 488: case IDM_2LINES: ! 489: iLines = 2; ! 490: break; ! 491: case IDM_4LINES: ! 492: iLines = 4; ! 493: break; ! 494: case IDM_8LINES: ! 495: iLines = 8; ! 496: break; ! 497: case IDM_16LINES: ! 498: iLines = 16; ! 499: break; ! 500: case IDM_32LINES: ! 501: iLines = 32; ! 502: } ! 503: ! 504: CheckMenuItem(GetMenu(hWnd), miOldLines, MF_CHECKED); ! 505: break; ! 506: ! 507: ! 508: default: /* Lets Windows process it */ ! 509: return (DefWindowProc(hWnd, message, wParam, lParam)); ! 510: } ! 511: break; ! 512: ! 513: case WM_DESTROY: /* message: window being destroyed */ ! 514: PostQuitMessage(0); ! 515: DeleteDC(hdcMem); ! 516: DeleteObject(hbmMem); ! 517: break; ! 518: ! 519: case WM_DOSOMEWORK: ! 520: // do another slice of calculation work ! 521: DoSomeWork(hWnd, FALSE); ! 522: break; ! 523: ! 524: case WM_PAINTLINE: ! 525: // The shared buffer contains a line of data; draw it ! 526: PaintLine(hWnd, ! 527: (svr_table *)&SvrTable[(signed int)wParam], ! 528: hdcMem, ! 529: height); ! 530: break; ! 531: ! 532: case WM_TIMER: ! 533: // timer means we should do another slice of work ! 534: DoSomeWork(hWnd, TRUE); ! 535: break; ! 536: ! 537: case WM_LBUTTONDOWN: ! 538: // left button down; start to define a zoom rectangle ! 539: ! 540: if (fRectDefined) ! 541: DrawRect(hWnd, &rcZoom, FALSE, hdcMem); // undraw old rectangle ! 542: ! 543: // initialize rectangle ! 544: rcZoom.left = rcZoom.right = pSelected.x = LOWORD(lParam); ! 545: rcZoom.top = rcZoom.bottom = pSelected.y = HIWORD(lParam); ! 546: ! 547: // draw the new rectangle ! 548: DrawRect(hWnd, &rcZoom, TRUE, hdcMem); ! 549: ! 550: fRectDefined = TRUE; ! 551: fButtonDown = TRUE; ! 552: SetCapture(hWnd); // capture all mouse events ! 553: break; ! 554: ! 555: case WM_MOUSEMOVE: ! 556: ! 557: // mouse move -- if the button is down, change the rect ! 558: if (!fButtonDown) ! 559: break; ! 560: ! 561: DrawRect(hWnd, &rcZoom, FALSE, hdcMem); // undraw old rect ! 562: ! 563: pMove.x = LOWORD(lParam); ! 564: pMove.y = HIWORD(lParam); ! 565: ! 566: // update the selection rectangle ! 567: if (pMove.x <= pSelected.x) ! 568: rcZoom.left = pMove.x; ! 569: if (pMove.x >= pSelected.x) ! 570: rcZoom.right = pMove.x; ! 571: if (pMove.y <= pSelected.y) ! 572: rcZoom.top = pMove.y; ! 573: if (pMove.y >= pSelected.y) ! 574: rcZoom.bottom = pMove.y; ! 575: ! 576: DrawRect(hWnd, &rcZoom, TRUE, hdcMem); // draw new rect ! 577: break; ! 578: ! 579: case WM_LBUTTONUP: ! 580: // button up; end selection ! 581: fButtonDown = FALSE; ! 582: ReleaseCapture(); ! 583: break; ! 584: ! 585: default: /* Passes it on if unproccessed */ ! 586: return (DefWindowProc(hWnd, message, wParam, lParam)); ! 587: } ! 588: return (0L); ! 589: } ! 590: ! 591: ! 592: ! 593: /* ! 594: * FUNCTION: About(HWND, unsigned, WORD, LONG) ! 595: * ! 596: * PURPOSE: Processes messages for "About" dialog box ! 597: * ! 598: * MESSAGES: ! 599: * ! 600: * WM_INITDIALOG - initialize dialog box ! 601: * WM_COMMAND - Input received ! 602: * ! 603: * COMMENTS: ! 604: * ! 605: * No initialization is needed for this particular dialog box, but TRUE ! 606: * must be returned to Windows. ! 607: * ! 608: * Wait for user to click on "Ok" button, then close the dialog box. ! 609: */ ! 610: ! 611: BOOL APIENTRY About( ! 612: HWND hDlg, /* window handle of the dialog box */ ! 613: UINT message, /* type of message */ ! 614: UINT wParam, /* message-specific information */ ! 615: LONG lParam) ! 616: { ! 617: UNREFERENCED_PARAMETER(lParam); ! 618: ! 619: switch (message) ! 620: { ! 621: case WM_INITDIALOG: /* message: initialize dialog box */ ! 622: ! 623: return (TRUE); ! 624: ! 625: case WM_COMMAND: /* message: received a command */ ! 626: if (wParam == IDOK /* "OK" box selected? */ ! 627: || wParam == IDCANCEL) /* System menu close command? */ ! 628: { ! 629: EndDialog(hDlg, TRUE); /* Exits the dialog box */ ! 630: return (TRUE); ! 631: } ! 632: break; ! 633: } ! 634: return (FALSE); /* Didn't process a message */ ! 635: } ! 636: ! 637: ! 638: ! 639: ! 640: /* ! 641: * DoSomeWork -- ! 642: * ! 643: * This function does our work for us. It does it in little pieces, and ! 644: * will schedule itself as it sees fit. ! 645: */ ! 646: ! 647: void ! 648: DoSomeWork( HWND hwnd, ! 649: BOOL fTimer) ! 650: { ! 651: ! 652: static WORD wIteration = 0; ! 653: ! 654: if (fTimer) { ! 655: wIteration++; ! 656: ! 657: // on every nth tick, we send out a poll ! 658: if (wIteration == 120) { // tune this? ! 659: wIteration = 0; ! 660: return; ! 661: } ! 662: ! 663: // on the half-poll, we check for responses ! 664: if ((wIteration == 2) || (wIteration == 10)) { ! 665: return; ! 666: } ! 667: ! 668: } ! 669: ! 670: if (CheckDrawStatus(hwnd)) ! 671: SendMessage(hwnd, WM_DOSOMEWORK, 0, 0L); ! 672: ! 673: return; ! 674: } ! 675: ! 676: ! 677: ! 678: /* ! 679: * DrawRect -- ! 680: * ! 681: * This function draws (or undraws) the zoom rectangle. ! 682: */ ! 683: ! 684: void ! 685: DrawRect( HWND hwnd, ! 686: PRECT prc, ! 687: BOOL fDrawIt, ! 688: HDC hdcBM) ! 689: { ! 690: ! 691: HDC hdc; ! 692: DWORD dwRop; ! 693: ! 694: hdc = GetDC(hwnd); ! 695: ! 696: if (fDrawIt) ! 697: dwRop = NOTSRCCOPY; ! 698: else ! 699: dwRop = SRCCOPY; ! 700: ! 701: ! 702: // top side ! 703: BitBlt(hdc, prc->left, prc->top, (prc->right - prc->left) + 1, ! 704: 1, hdcBM, prc->left, prc->top, dwRop); ! 705: ! 706: // bottom side ! 707: BitBlt(hdc, prc->left, prc->bottom, (prc->right - prc->left) + 1, ! 708: 1, hdcBM, prc->left, prc->bottom, dwRop); ! 709: ! 710: // left side ! 711: BitBlt(hdc,prc->left, prc->top, 1, (prc->bottom - prc->top) + 1, ! 712: hdcBM, prc->left, prc->top, dwRop); ! 713: ! 714: // right side ! 715: BitBlt(hdc,prc->right, prc->top, 1, (prc->bottom - prc->top) + 1, ! 716: hdcBM, prc->right, prc->top, dwRop); ! 717: ! 718: ReleaseDC(hwnd, hdc); ! 719: } ! 720: ! 721: ! 722: ! 723: /* ! 724: * PaintLine -- ! 725: * ! 726: * This function paints a buffer of data into the bitmap. ! 727: */ ! 728: ! 729: void ! 730: PaintLine( HWND hwnd, ! 731: svr_table * pst, ! 732: HDC hdcBM, ! 733: int cHeight) ! 734: { ! 735: ! 736: PWORD pwDrawData; ! 737: int y; ! 738: int x; ! 739: DWORD dwThreshold; ! 740: RECT rc; ! 741: WORD lines; ! 742: ! 743: lines = (WORD) pst->cLines; ! 744: ! 745: // picture ID had better match, or else we skip it ! 746: if (CheckDrawingID(pst->cPicture)) ! 747: { ! 748: // figure out our threshold ! 749: dwThreshold = QueryThreshold(); ! 750: ! 751: // get a pointer to the draw buffer ! 752: pwDrawData = (PWORD)GetDrawBuffer(); ! 753: if (pwDrawData == NULL) { ! 754: ReturnDrawBuffer(); ! 755: return; ! 756: } ! 757: ! 758: // starting x coordinate ! 759: x = (int) pst->dwLine; ! 760: ! 761: // now loop through the rectangle ! 762: while (lines-- > 0) ! 763: { ! 764: // bottom to top, since that's the order of the data in the buffer ! 765: y = (int) cHeight-1; ! 766: ! 767: ! 768: while (y >= 0) { ! 769: // draw a pixel ! 770: SetPixel(hdcBM, x,y, MapColor((DWORD)*pwDrawData, dwThreshold)); ! 771: if (fContinueZoom == TRUE) ! 772: CalcHistogram(x, y, (DWORD)*pwDrawData, dwThreshold); ! 773: // now increment buffer pointer and y coord ! 774: y--; ! 775: pwDrawData++; ! 776: } ! 777: x++; // increment X coordinate ! 778: } ! 779: ! 780: // figure out the rectangle to invalidate ! 781: rc.top = 0; ! 782: rc.bottom = cHeight; ! 783: rc.left = (int)(pst->dwLine); ! 784: rc.right = (int)(pst->dwLine) + pst->cLines; ! 785: ! 786: FreeDrawBuffer(); ! 787: ! 788: // and invalidate it on the screen so we redraw it ! 789: InvalidateRect(hwnd, &rc, FALSE); ! 790: } ! 791: ! 792: // free this for someone else to use ! 793: ReturnDrawBuffer(); ! 794: ! 795: // and change the pipe state, if necessary ! 796: if (pst->iStatus == SS_PAINTING) ! 797: pst->iStatus = SS_IDLE; ! 798: ! 799: } ! 800: ! 801: ! 802: #define CLR_BLACK RGB(0,0,0) ! 803: #define CLR_DARKBLUE RGB(0,0,127) ! 804: #define CLR_BLUE RGB(0,0,255) ! 805: #define CLR_CYAN RGB(0,255,255) ! 806: #define CLR_DARKGREEN RGB(0,127,0) ! 807: #define CLR_GREEN RGB(0,255,0) ! 808: #define CLR_YELLOW RGB(255,255,0) ! 809: #define CLR_RED RGB(255,0,0) ! 810: #define CLR_DARKRED RGB(127,0,0) ! 811: #define CLR_WHITE RGB(255,255,255) ! 812: #define CLR_PALEGRAY RGB(194,194,194) ! 813: #define CLR_DARKGRAY RGB(127,127,127) ! 814: ! 815: ! 816: static COLORREF ColorMapTable[] = { // size = NCOLORS ! 817: CLR_DARKBLUE, ! 818: CLR_BLUE, ! 819: CLR_CYAN, ! 820: CLR_DARKGREEN, ! 821: CLR_GREEN, ! 822: CLR_YELLOW, ! 823: CLR_RED, ! 824: CLR_DARKRED, ! 825: CLR_WHITE, ! 826: CLR_PALEGRAY, ! 827: CLR_DARKGRAY}; ! 828: ! 829: ! 830: /* ! 831: * MapColor -- ! 832: * ! 833: * This function maps an iteration count into a corresponding RGB color. ! 834: */ ! 835: ! 836: COLORREF ! 837: MapColor(DWORD dwIter, ! 838: DWORD dwThreshold) ! 839: { ! 840: ! 841: // if it's beyond the threshold, call it black ! 842: if (dwIter >= dwThreshold) { ! 843: return CLR_BLACK; ! 844: } ! 845: ! 846: // get a modulus based on the number of colors ! 847: dwIter = (dwIter / 3) % NCOLORS; // 11; ! 848: ! 849: // and return the appropriate color ! 850: return ColorMapTable[dwIter]; ! 851: ! 852: } ! 853: /* CalcHistogram ! 854: * This function is used to select the region that is the ! 855: * most complex and will be used to zoom in for the next picture; ! 856: * it contains the most colors. The number of colors are counted. ! 857: */ ! 858: ! 859: void ! 860: CalcHistogram(int x, ! 861: int y, ! 862: DWORD dwIter, ! 863: DWORD dwThreshold) ! 864: { ! 865: ! 866: // if it's beyond the threshold, call it black ! 867: if (dwIter >= dwThreshold) { ! 868: Histogram[x/(WIDTH/4)][y/(HEIGHT/4)][NCOLORS]++; ! 869: return; ! 870: } ! 871: // get a modulus based on the number of colors ! 872: dwIter = (dwIter / 3) % NCOLORS; // 11; ! 873: ! 874: // and bump the count for the appropriate color ! 875: Histogram[x/(WIDTH/4)][y/(HEIGHT/4)][dwIter]++; // region of map ! 876: ! 877: return; ! 878: ! 879: } ! 880: ! 881: ! 882: /* InitHistogram ! 883: * This function initializes the histogram data structures. ! 884: */ ! 885: ! 886: void InitHistogram(void) ! 887: { ! 888: int i, j, k; ! 889: ! 890: for (i = 0; i < 4; i++) ! 891: for (j = 0; j < 4; j++) ! 892: for (k = 0; k <= NCOLORS; k++) ! 893: Histogram[i][j][k] = 0; /* count of colors */ ! 894: } ! 895: ! 896: /* CountHistogram ! 897: * This function determines the number of colors represented ! 898: * within a region. The region with the most colors is ! 899: * selected using the maxi and maxj values. X and Y coordinates ! 900: * corresponding to these regions are stored in the HistRegion ! 901: * table and are used for the next picture. ! 902: */ ! 903: ! 904: void CountHistogram(void) ! 905: { ! 906: int i, j, k; ! 907: /* count the number of colors in each region */ ! 908: /* find the color that dominates each region */ ! 909: for (i = 0; i < 4; i++) { ! 910: for (j = 0; j < 4; j++) { ! 911: ColorCount[i][j] = 0; ! 912: Max[i][j] = 0; ! 913: for (k = 0; k <= NCOLORS; k++) { ! 914: if (Histogram[i][j][k] > Max[i][j]) ! 915: Max[i][j] = Histogram[i][j][k]; ! 916: if (Histogram[i][j][k] != 0) /* count of colors */ ! 917: ColorCount[i][j]++; ! 918: } ! 919: ! 920: } ! 921: } ! 922: iHistMaxI = 0; ! 923: iHistMaxJ = 0; ! 924: /* if several regions have the same number of colors, */ ! 925: /* select the region with the most variety: the smallest max */ ! 926: for (i = 0; i < 4; i++) { ! 927: for (j = 0; j < 4; j++) { ! 928: if ( (ColorCount[i][j] >= ColorCount[iHistMaxI][iHistMaxJ]) ! 929: && (Max[i][j] < Max[iHistMaxI][iHistMaxJ]) ) { ! 930: iHistMaxI = i; ! 931: iHistMaxJ = j; ! 932: } ! 933: } ! 934: } ! 935: InitHistogram(); /* initialize for next time */ ! 936: ! 937: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.