|
|
1.1 root 1: 1.1.1.4 ! root 2: /**************************************************************************** ! 3: Microsoft RPC Version 1.0 ! 4: Copyright Microsoft Corp. 1992 ! 5: mandel Example ! 6: ! 7: FILE: mandel.c ! 8: ! 9: PURPOSE: Client side of the RPC distributed application 1.1 root 10: 1.1.1.4 ! root 11: COMMENTS: Main code for the Windows Mandelbrot Set distributed ! 12: drawing program. 1.1 root 13: 14: ****************************************************************************/ 15: 16: #include <stdio.h> 17: #include <stdlib.h> 1.1.1.4 ! root 18: #include <ctype.h> ! 19: #include <string.h> 1.1 root 20: #include <time.h> 1.1.1.4 ! root 21: #include <windows.h> // Required for all Windows applications ! 22: #include <windowsx.h> // Allow portability from Win16, Win32 1.1 root 23: 24: #ifdef RPC 1.1.1.4 ! root 25: #include "mdlrpc.h" // header file generated by the MIDL compiler 1.1 root 26: #endif 1.1.1.4 ! root 27: #include "mandel.h" 1.1 root 28: 1.1.1.4 ! root 29: ! 30: /* data structures */ 1.1 root 31: 32: #ifdef RPC 33: char szTitle[] = "Mandelbrot RPC"; 34: #else 35: char szTitle[] = "Mandelbrot Standalone"; 36: #endif 37: 1.1.1.4 ! root 38: CPOINT cptUL = { (double) -2.05, (double) 1.4 }; ! 39: double dPrec = (double) .01; ! 40: ! 41: HANDLE hInst; // current instance ! 42: ! 43: svr_table SvrTable; ! 44: int iLines = LINES; ! 45: ! 46: int fContinueZoom = TRUE; ! 47: int fZoomIn = TRUE; 1.1 root 48: 1.1.1.4 ! root 49: // split current picture into 16 regions ! 50: // zoom on most complex region; region with most colors represented ! 51: int Histogram[4][4][NCOLORS+1] = {0}; ! 52: int ColorCount[4][4] = {0}; ! 53: int Max[4][4] = {0}; ! 54: ! 55: int iHistMaxI = 2; ! 56: int iHistMaxJ = 3; ! 57: ! 58: RECT rcZoom; ! 59: BOOL fRectDefined = FALSE; 1.1 root 60: 1.1.1.3 root 61: #ifdef RPC 1.1.1.4 ! root 62: int fBound = FALSE; // flag indicates whether bound to svr ! 63: unsigned char * pszUuid = NULL; ! 64: unsigned char * pszProtocolSequence = "ncacn_np"; ! 65: unsigned char * pszEndpoint = "\\pipe\\mandel"; ! 66: unsigned char * pszOptions = NULL; ! 67: unsigned char * pszStringBinding; ! 68: unsigned char pszNetworkAddress[UNCLEN+1] = {'\0'}; 1.1.1.3 root 69: #endif 1.1 root 70: 1.1.1.4 ! root 71: /* function prototypes */ ! 72: ! 73: void DoSomeWork(HWND, BOOL); ! 74: void InitHistogram(void); ! 75: void CalcHistogram(int, int, DWORD, DWORD); ! 76: void PaintLine(HWND, svr_table *, HDC, int); ! 77: void DrawRect(HWND, PRECT, BOOL, HDC); ! 78: COLORREF MapColor(DWORD, DWORD); ! 79: ! 80: 1.1 root 81: /* 82: * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) 83: * 84: * PURPOSE: Calls initialization function, processes message loop 85: * 86: * COMMENTS: 87: * 88: * Windows recognizes this function by name as the initial entry point 89: * for the program. This function calls the application initialization 90: * routine, if no other instance of the program is running, and always 91: * calls the instance initialization routine. It then executes a message 92: * retrieval and dispatch loop that is the top-level control structure 93: * for the remainder of execution. The loop is terminated when a WM_QUIT 94: * message is received, at which time this function exits the application 95: * instance by returning the value passed by PostQuitMessage(). 96: * 97: * If this function must abort before entering the message loop, it 98: * returns the conventional value NULL. 99: */ 100: 1.1.1.4 ! root 101: int WINAPI WinMain( ! 102: HINSTANCE hInstance, /* current instance */ ! 103: HINSTANCE hPrevInstance, /* previous instance */ ! 104: LPSTR lpCmdLine, /* command line */ ! 105: int nCmdShow) /* show-window type (open/icon) */ 1.1 root 106: { 107: 1.1.1.4 ! root 108: MSG msg; 1.1 root 109: 1.1.1.3 root 110: UNREFERENCED_PARAMETER(lpCmdLine); 111: 1.1.1.4 ! root 112: if (!hPrevInstance) /* Other instances of app running? */ ! 113: if (!InitApplication(hInstance)) /* Initialize shared things */ ! 114: return(FALSE); /* Exits if unable to initialize */ 1.1 root 115: 116: /* Perform initializations that apply to a specific instance */ 117: if (!InitInstance(hInstance, nCmdShow)) 1.1.1.4 ! root 118: return(FALSE); 1.1 root 119: 120: /* Acquire and dispatch messages until a WM_QUIT message is received. */ 1.1.1.4 ! root 121: while (GetMessage(&msg, /* message structure */ ! 122: (HWND)NULL, /* handle of window receiving the message */ ! 123: 0, /* lowest message to examine */ ! 124: 0)) /* highest message to examine */ 1.1 root 125: { 1.1.1.4 ! root 126: TranslateMessage(&msg); /* Translates virtual key codes */ ! 127: DispatchMessage(&msg); /* Dispatches message to window */ 1.1 root 128: } 129: 1.1.1.4 ! root 130: return(msg.wParam); /* Returns the value from PostQuitMessage */ ! 131: ! 132: } 1.1 root 133: 134: 135: /* 1.1.1.4 ! root 136: * FUNCTION: InitApplication(HANDLE) 1.1 root 137: * 1.1.1.4 ! root 138: * PURPOSE: Initializes window data and registers window class 1.1 root 139: * 1.1.1.4 ! root 140: * COMMENTS: 1.1 root 141: * 1.1.1.4 ! root 142: * This function is called at initialization time only if no other ! 143: * instances of the application are running. This function performs ! 144: * initialization tasks that can be done once for any number of running ! 145: * instances. ! 146: * ! 147: * In this case, we initialize a window class by filling out a data ! 148: * structure of type WNDCLASS and calling the Windows RegisterClass() ! 149: * function. Since all instances of this application use the same window ! 150: * class, we only need to do this when the first instance is initialized. 1.1 root 151: */ 152: 1.1.1.4 ! root 153: BOOL InitApplication(HANDLE hInstance) /* current instance */ 1.1 root 154: { 1.1.1.4 ! root 155: 1.1 root 156: WNDCLASS wc; 157: 158: /* Fill in window class structure with parameters that describe the */ 159: /* main window. */ 160: wc.style = 0; /* Class style(s). */ 1.1.1.4 ! root 161: wc.lpfnWndProc = (WNDPROC)MainWndProc; ! 162: /* Function to retrieve messages for */ 1.1 root 163: /* windows of this class. */ 164: wc.cbClsExtra = 0; /* No per-class extra data. */ 165: wc.cbWndExtra = 0; /* No per-window extra data. */ 166: wc.hInstance = hInstance; /* Application that owns the class. */ 167: wc.hIcon = LoadIcon(hInstance, "RPC_ICON"); 1.1.1.4 ! root 168: wc.hCursor = LoadCursor(0, IDC_ARROW); 1.1 root 169: wc.hbrBackground = GetStockObject(WHITE_BRUSH); 1.1.1.4 ! root 170: wc.lpszMenuName = "MandelMenu"; /* Name of menu resource in .RC file. */ ! 171: wc.lpszClassName = "MandelClass"; /* Name used in call to CreateWindow. */ 1.1 root 172: 173: /* Register the window class and return success/failure code. */ 1.1.1.4 ! root 174: return(RegisterClass(&wc)); 1.1 root 175: 176: } 177: 1.1.1.4 ! root 178: 1.1 root 179: /* 1.1.1.4 ! root 180: * FUNCTION: InitInstance(HANDLE, int) 1.1 root 181: * 1.1.1.4 ! root 182: * PURPOSE: Saves instance handle and creates main window. 1.1 root 183: * 1.1.1.4 ! root 184: * COMMENTS: 1.1 root 185: * 1.1.1.4 ! root 186: * This function is called at initialization time for every instance of ! 187: * this application. This function performs initialization tasks that ! 188: * cannot be shared by multiple instances. 1.1 root 189: * 1.1.1.4 ! root 190: * In this case, we save the instance handle in a static variable and ! 191: * create and display the main program window. 1.1 root 192: */ 193: 1.1.1.4 ! root 194: BOOL InitInstance(HANDLE hInstance, /* Current instance identifier. */ ! 195: int nCmdShow) /* Param for first ShowWindow() call. */ 1.1 root 196: { 197: HWND hWnd; /* Main window handle. */ 1.1.1.4 ! root 198: HMENU hMenu; 1.1 root 199: RECT rc; 200: 201: /* Save the instance handle in static variable, which will be used in */ 202: /* many subsequence calls from this application to Windows. */ 203: hInst = hInstance; 204: 205: /* Create a main window for this application instance. */ 206: hWnd = CreateWindow( 1.1.1.4 ! root 207: "MandelClass", /* See RegisterClass() call. */ ! 208: szTitle, /* Text for window title bar. */ ! 209: WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX, ! 210: CW_USEDEFAULT, /* Default horizontal position. */ ! 211: CW_USEDEFAULT, /* Default vertical position. */ ! 212: WIDTH, /* Default width. */ ! 213: HEIGHT, /* Default height. */ ! 214: (HWND) NULL, /* Overlapped windows have no parent. */ ! 215: (HMENU) NULL, /* Use the window class menu. */ ! 216: hInstance, /* This instance owns this window. */ ! 217: (LPVOID) NULL /* Pointer not needed. */ ! 218: ); 1.1 root 219: 220: /* If window could not be created, return "failure" */ 221: if (!hWnd) 1.1.1.4 ! root 222: return(FALSE); 1.1 root 223: 224: /* Make the window visible; update its client area; and return "success" */ 1.1.1.4 ! root 225: ShowWindow(hWnd, nCmdShow); /* Show the window */ ! 226: UpdateWindow(hWnd); /* Sends WM_PAINT message */ 1.1 root 227: rc.top = rc.left = 0; 228: rc.bottom = HEIGHT-1; 229: rc.right = WIDTH-1; 230: 231: SetNewCalc(cptUL, dPrec, rc); 1.1.1.3 root 232: hMenu = GetMenu(hWnd); 233: 234: #ifndef RPC 235: EnableMenuItem(hMenu, IDM_SERVER, MF_GRAYED); /* disable option */ 236: #endif 1.1 root 237: 1.1.1.4 ! root 238: return(TRUE); /* Returns the value from PostQuitMessage */ 1.1 root 239: } 240: 241: 242: /* 1.1.1.4 ! root 243: * FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG) 1.1 root 244: * 1.1.1.4 ! root 245: * PURPOSE: Processes messages 1.1 root 246: * 1.1.1.4 ! root 247: * MESSAGES: ! 248: * WM_COMMAND - application menu ! 249: * WM_DESTROY - destroy window 1.1 root 250: * 1.1.1.4 ! root 251: * COMMENTS: 1.1 root 252: */ 253: 254: LONG APIENTRY MainWndProc( 1.1.1.4 ! root 255: HWND hWnd, /* window handle */ ! 256: UINT message, /* type of message */ ! 257: UINT wParam, /* additional information */ ! 258: LONG lParam) /* additional information */ 1.1 root 259: { 1.1.1.4 ! root 260: DLGPROC lpProc; /* pointer to the dialog box function */ 1.1 root 261: PAINTSTRUCT ps; 262: HDC hdc; 1.1.1.4 ! root 263: static HDC hdcMem; 1.1 root 264: static HBITMAP hbmMem; 1.1.1.4 ! root 265: static int width; ! 266: static int height; ! 267: RECT rc; ! 268: static BOOL fButtonDown = FALSE; ! 269: static POINT pSelected; ! 270: POINT pMove; ! 271: int iWidthNew; ! 272: int iHeightNew; ! 273: static int miOldLines; ! 274: double scaling; 1.1 root 275: 1.1.1.4 ! root 276: switch (message) { ! 277: ! 278: case WM_CREATE: 1.1 root 279: 1.1.1.3 root 280: #ifdef WIN16 1.1.1.4 ! root 281: PostMessage(hWnd, WM_COMMAND, IDM_SERVER, 0L); // force server spec 1.1.1.3 root 282: #else 1.1.1.4 ! root 283: PostMessage(hWnd, WM_COMMAND, IDM_BIND, 0L); // bind to server 1.1.1.3 root 284: #endif 1.1 root 285: 1.1.1.4 ! root 286: if (!InitRemote(hWnd)) ! 287: return(FALSE); 1.1 root 288: 1.1.1.4 ! root 289: InitHistogram(); 1.1 root 290: 1.1.1.4 ! root 291: hdc = GetDC(hWnd); ! 292: hdcMem = CreateCompatibleDC(hdc); ! 293: GetWindowRect(hWnd, &rc); ! 294: width = rc.right - rc.left; ! 295: height = rc.bottom - rc.top; ! 296: hbmMem = CreateCompatibleBitmap(hdc, width, height); ! 297: SelectObject(hdcMem, hbmMem); ! 298: ! 299: ReleaseDC(hWnd,hdc); ! 300: ! 301: rc.left = rc.top = 0; ! 302: rc.right = width+1; ! 303: rc.bottom = height + 1; ! 304: FillRect(hdcMem, &rc, GetStockObject(WHITE_BRUSH)); ! 305: ! 306: SetTimer(hWnd, 1, POLL_TIME, NULL); // set timer for polls ! 307: ! 308: CheckMenuItem(GetMenu(hWnd), IDM_4LINES, MF_CHECKED); ! 309: CheckMenuItem(GetMenu(hWnd), IDM_CONTINUOUS, MF_CHECKED); ! 310: miOldLines = IDM_4LINES; // save to uncheck ! 311: break; ! 312: ! 313: case WM_PAINT: ! 314: hdc = BeginPaint(hWnd, &ps); ! 315: BitBlt(hdc, ! 316: ps.rcPaint.left, ! 317: ps.rcPaint.top, ! 318: ps.rcPaint.right - ps.rcPaint.left, ! 319: ps.rcPaint.bottom - ps.rcPaint.top, ! 320: hdcMem, ! 321: ps.rcPaint.left, ! 322: ps.rcPaint.top, ! 323: SRCCOPY); ! 324: EndPaint(hWnd, &ps); ! 325: break; 1.1 root 326: 1.1.1.4 ! root 327: case WM_COMMAND: // message: command from application menu ! 328: switch(wParam) { 1.1 root 329: 1.1.1.4 ! root 330: case IDM_BIND: 1.1 root 331: 1.1.1.3 root 332: #ifdef RPC 1.1.1.4 ! root 333: if (Bind(hWnd) != RPC_S_OK) ! 334: PostMessage(hWnd, WM_DESTROY, 0, 0L); 1.1.1.3 root 335: #endif 1.1.1.4 ! root 336: break; 1.1 root 337: 1.1.1.4 ! root 338: case IDM_ABOUT: ! 339: lpProc = MakeProcInstance(About, hInst); 1.1 root 340: 1.1.1.4 ! root 341: DialogBox(hInst, // current instance ! 342: "AboutBox", // resource to use ! 343: hWnd, // parent handle ! 344: lpProc); // About() instance address 1.1 root 345: 1.1.1.4 ! root 346: FreeProcInstance(lpProc); ! 347: break; 1.1 root 348: 1.1.1.4 ! root 349: case IDM_ZOOMOUT: ! 350: if (dPrec > (double)MAXPREC) // don't allow the zoom out 1.1 root 351: break; 352: 1.1.1.4 ! root 353: rcZoom.left = WIDTH/4 + (WIDTH/8); // center square ! 354: rcZoom.top = HEIGHT/4 + (HEIGHT/8); ! 355: rcZoom.right = rcZoom.left + (WIDTH/4); ! 356: rcZoom.bottom = rcZoom.top + (HEIGHT/4); ! 357: ! 358: cptUL.real -= (rcZoom.left * dPrec); // inverse of zoom in ! 359: cptUL.imag += (rcZoom.top * dPrec); ! 360: iWidthNew = (rcZoom.right - rcZoom.left + 1); ! 361: iHeightNew = (rcZoom.bottom - rcZoom.top + 1); ! 362: scaling = ((double) ((iWidthNew > iHeightNew) ? iWidthNew : iHeightNew) / (double) width); ! 363: dPrec /= scaling; 1.1 root 364: 1.1.1.4 ! root 365: rc.left = rc.top = 0; ! 366: rc.bottom = height - 1; ! 367: rc.right = width - 1; ! 368: ! 369: SetNewCalc(cptUL, dPrec, rc); ! 370: fRectDefined = FALSE; ! 371: DoSomeWork(hWnd, FALSE); ! 372: break; 1.1 root 373: 1.1.1.4 ! root 374: case IDM_ZOOMIN: // zoom in on selected rectangle ! 375: // if no rectangle, don't zoom in ! 376: if (!fRectDefined) 1.1 root 377: break; 378: 1.1.1.4 ! root 379: if (dPrec < (double)MINPREC) // don't allow zoom in 1.1 root 380: break; 381: 1.1.1.4 ! root 382: DrawRect(hWnd, &rcZoom, TRUE, hdcMem); // draw new rect 1.1 root 383: 1.1.1.4 ! root 384: // calculate new upper-left ! 385: cptUL.real += (rcZoom.left * dPrec); ! 386: cptUL.imag -= (rcZoom.top * dPrec); ! 387: ! 388: iWidthNew = (rcZoom.right - rcZoom.left + 1); ! 389: iHeightNew = (rcZoom.bottom - rcZoom.top + 1); ! 390: scaling = ((double) ((iWidthNew > iHeightNew) ? iWidthNew : iHeightNew) / (double) width); 1.1 root 391: 1.1.1.4 ! root 392: dPrec *= scaling; 1.1 root 393: 1.1.1.4 ! root 394: rc.left = rc.top = 0; ! 395: rc.bottom = height - 1; ! 396: rc.right = width - 1; ! 397: ! 398: SetNewCalc(cptUL, dPrec, rc); ! 399: IncPictureID(); 1.1 root 400: 1.1.1.4 ! root 401: fRectDefined = FALSE; ! 402: DoSomeWork(hWnd, FALSE); ! 403: break; 1.1 root 404: 1.1.1.4 ! root 405: case IDM_CONTINUOUS: // continuous zoom in ! 406: if (fContinueZoom == TRUE) { ! 407: CheckMenuItem(GetMenu(hWnd), IDM_CONTINUOUS, MF_UNCHECKED); ! 408: fContinueZoom = FALSE; ! 409: } ! 410: else { ! 411: CheckMenuItem(GetMenu(hWnd), IDM_CONTINUOUS, MF_CHECKED); ! 412: fContinueZoom = TRUE; 1.1 root 413: } 414: break; 415: 1.1.1.4 ! root 416: case IDM_REDRAW: ! 417: if (fContinueZoom == TRUE) ! 418: InitHistogram(); ! 419: ! 420: rc.left = rc.top = 0; ! 421: rc.right = width+1; ! 422: rc.bottom = height + 1; ! 423: FillRect(hdcMem, &rc, GetStockObject(WHITE_BRUSH)); ! 424: InvalidateRect(hWnd, NULL, TRUE); ! 425: ! 426: rc.left = rc.top = 0; ! 427: rc.bottom = height - 1; ! 428: rc.right = width - 1; ! 429: SetNewCalc(cptUL, dPrec, rc); 1.1 root 430: 1.1.1.4 ! root 431: fRectDefined = FALSE; ! 432: DoSomeWork(hWnd, FALSE); 1.1 root 433: break; 434: 1.1.1.4 ! root 435: case IDM_EXIT: ! 436: DestroyWindow(hWnd); ! 437: FreeDrawBuffer(); 1.1 root 438: break; 439: 1.1.1.4 ! root 440: case IDM_TOP: ! 441: cptUL.real = (double) -2.05; ! 442: cptUL.imag = (double) 1.4; ! 443: dPrec = .01; 1.1 root 444: 1.1.1.4 ! root 445: rc.left = rc.top = 0; ! 446: rc.bottom = height - 1; ! 447: rc.right = width - 1; ! 448: ! 449: SetNewCalc(cptUL, dPrec, rc); ! 450: ResetPictureID(); // incremented past original 1.1 root 451: 1.1.1.4 ! root 452: fRectDefined = FALSE; ! 453: DoSomeWork(hWnd, FALSE); 1.1 root 454: break; 455: 1.1.1.4 ! root 456: case IDM_1LINE: ! 457: ! 458: case IDM_2LINES: ! 459: ! 460: case IDM_4LINES: ! 461: ! 462: CheckMenuItem(GetMenu(hWnd), miOldLines, MF_UNCHECKED); ! 463: miOldLines = wParam; ! 464: switch(wParam) { 1.1 root 465: 1.1.1.4 ! root 466: case IDM_1LINE: ! 467: iLines = 1; 1.1 root 468: break; 1.1.1.4 ! root 469: case IDM_2LINES: ! 470: iLines = 2; ! 471: break; ! 472: case IDM_4LINES: ! 473: iLines = 4; ! 474: break; ! 475: } 1.1 root 476: 1.1.1.4 ! root 477: CheckMenuItem(GetMenu(hWnd), miOldLines, MF_CHECKED); ! 478: break; 1.1 root 479: 1.1.1.4 ! root 480: #ifdef RPC ! 481: case IDM_SERVER: ! 482: lpProc = MakeProcInstance(Server, hInst); ! 483: DialogBox(hInst, // current instance ! 484: "ServerBox", // resource to use ! 485: hWnd, // parent handle ! 486: lpProc); // Server instance address ! 487: FreeProcInstance(lpProc); ! 488: break; 1.1 root 489: 1.1.1.4 ! root 490: #endif 1.1 root 491: 1.1.1.4 ! root 492: default: // Lets Windows process it ! 493: return(DefWindowProc(hWnd, message, wParam, lParam)); ! 494: ! 495: } ! 496: ! 497: break; ! 498: ! 499: case WM_DESTROY: // message: window being destroyed ! 500: PostQuitMessage(0); ! 501: DeleteDC(hdcMem); ! 502: DeleteObject(hbmMem); ! 503: break; ! 504: ! 505: case WM_DOSOMEWORK: // do another slice of calculation work ! 506: DoSomeWork(hWnd, FALSE); ! 507: break; ! 508: ! 509: case WM_PAINTLINE: // The shared buffer contains a line of data; draw it ! 510: PaintLine(hWnd, ! 511: &SvrTable, ! 512: hdcMem, ! 513: height); ! 514: break; ! 515: ! 516: case WM_TIMER: // timer means we should do another slice of work ! 517: DoSomeWork(hWnd, TRUE); ! 518: break; ! 519: ! 520: case WM_LBUTTONDOWN: // left button down; start to define a zoom rectangle ! 521: if (fRectDefined) ! 522: DrawRect(hWnd, &rcZoom, FALSE, hdcMem); // undraw old rectangle ! 523: ! 524: // initialize rectangle ! 525: rcZoom.left = rcZoom.right = pSelected.x = LOWORD(lParam); ! 526: rcZoom.top = rcZoom.bottom = pSelected.y = HIWORD(lParam); ! 527: ! 528: // draw the new rectangle ! 529: DrawRect(hWnd, &rcZoom, TRUE, hdcMem); ! 530: ! 531: fRectDefined = TRUE; ! 532: fButtonDown = TRUE; ! 533: SetCapture(hWnd); // capture all mouse events ! 534: break; ! 535: ! 536: case WM_MOUSEMOVE: // mouse move ! 537: // if the button is down, change the rect ! 538: if (!fButtonDown) 1.1 root 539: break; 540: 1.1.1.4 ! root 541: DrawRect(hWnd, &rcZoom, FALSE, hdcMem); // undraw old rect 1.1 root 542: 1.1.1.4 ! root 543: pMove.x = LOWORD(lParam); ! 544: pMove.y = HIWORD(lParam); ! 545: ! 546: // update the selection rectangle ! 547: if (pMove.x <= pSelected.x) ! 548: rcZoom.left = pMove.x; ! 549: if (pMove.x >= pSelected.x) ! 550: rcZoom.right = pMove.x; ! 551: if (pMove.y <= pSelected.y) ! 552: rcZoom.top = pMove.y; ! 553: if (pMove.y >= pSelected.y) ! 554: rcZoom.bottom = pMove.y; ! 555: ! 556: DrawRect(hWnd, &rcZoom, TRUE, hdcMem); // draw new rect ! 557: break; ! 558: ! 559: case WM_LBUTTONUP: // button up; end selection ! 560: fButtonDown = FALSE; ! 561: ReleaseCapture(); ! 562: break; ! 563: ! 564: case WM_EXCEPTION: ! 565: lpProc = MakeProcInstance(Exception, hInst); ! 566: DialogBox(hInst, // current instance ! 567: "ExceptionBox",// resource to use ! 568: hWnd, // parent handle ! 569: lpProc); // Server instance address ! 570: FreeProcInstance(lpProc); ! 571: UnlockDrawBuffer(); ! 572: ReturnDrawBuffer(); ! 573: break; 1.1 root 574: 1.1.1.4 ! root 575: default: // Passes it on if unproccessed ! 576: return(DefWindowProc(hWnd, message, wParam, lParam)); 1.1 root 577: 1.1.1.4 ! root 578: } ! 579: ! 580: return(0L); ! 581: } 1.1 root 582: 1.1.1.4 ! root 583: 1.1 root 584: /* 1.1.1.4 ! root 585: * FUNCTION: About(HWND, unsigned, WORD, LONG) 1.1 root 586: * 1.1.1.4 ! root 587: * PURPOSE: Processes messages for "About" dialog box 1.1 root 588: * 1.1.1.4 ! root 589: * MESSAGES: 1.1 root 590: * 1.1.1.4 ! root 591: * WM_INITDIALOG - initialize dialog box ! 592: * WM_COMMAND - Input received 1.1 root 593: * 1.1.1.4 ! root 594: * COMMENTS: 1.1 root 595: * 1.1.1.4 ! root 596: * No initialization is needed for this particular dialog box, but TRUE ! 597: * must be returned to Windows. 1.1 root 598: * 1.1.1.4 ! root 599: * Wait for user to click on "Ok" button, then close the dialog box. 1.1 root 600: */ 601: 602: BOOL APIENTRY About( 1.1.1.4 ! root 603: HWND hDlg, /* window handle of the dialog box */ ! 604: UINT message, /* type of message */ ! 605: UINT wParam, /* message-specific information */ ! 606: LONG lParam) 1.1 root 607: { 1.1.1.4 ! root 608: 1.1 root 609: UNREFERENCED_PARAMETER(lParam); 610: 1.1.1.4 ! root 611: switch (message) { 1.1 root 612: 1.1.1.4 ! root 613: case WM_INITDIALOG: /* message: initialize dialog box */ ! 614: return(TRUE); 1.1 root 615: 1.1.1.4 ! root 616: case WM_COMMAND: /* message: received a command */ ! 617: if (wParam == IDOK || wParam == IDCANCEL) ! 618: { ! 619: EndDialog(hDlg, TRUE); /* Exits the dialog box */ ! 620: return(TRUE); ! 621: } ! 622: break; 1.1 root 623: } 1.1.1.4 ! root 624: ! 625: return(FALSE); /* Didn't process a message */ ! 626: } ! 627: ! 628: ! 629: /* ! 630: * FUNCTION: Server(HWND, unsigned, WORD, LONG) ! 631: * ! 632: * PURPOSE: Processes messages for "Server" dialog box ! 633: * ! 634: * MESSAGES: ! 635: * ! 636: * WM_INITDIALOG - initialize dialog box ! 637: * WM_COMMAND - Input received ! 638: ! 639: * COMMENTS: ! 640: * ! 641: * No initialization is needed for this particular dialog box, but TRUE ! 642: * must be returned to Windows. ! 643: * ! 644: * Wait for user to click on "Ok" button, then close the dialog box. ! 645: */ ! 646: ! 647: BOOL APIENTRY Server( ! 648: HWND hDlg, /* window handle of the dialog box */ ! 649: UINT message, /* type of message */ ! 650: UINT wParam, /* message-specific information */ ! 651: LONG lParam) ! 652: { ! 653: ! 654: UNREFERENCED_PARAMETER(lParam); ! 655: ! 656: #ifdef RPC ! 657: ! 658: switch (message) { ! 659: ! 660: case WM_INITDIALOG: /* message: initialize dialog box */ ! 661: SetDlgItemText(hDlg, IDD_SERVERNAME, pszNetworkAddress); ! 662: return(TRUE); ! 663: ! 664: case WM_COMMAND: /* message: received a command */ ! 665: switch(wParam) { ! 666: ! 667: case IDCANCEL: /* System menu close command? */ ! 668: EndDialog(hDlg, FALSE); ! 669: return(TRUE); ! 670: ! 671: case IDOK: /* "OK" box selected? */ ! 672: GetDlgItemText(hDlg, IDD_SERVERNAME, pszNetworkAddress, UNCLEN); ! 673: ! 674: /* pszNetworkAddress must start with two backslashes */ ! 675: if (pszNetworkAddress[0] != '\0' && ! 676: strncmp(pszNetworkAddress, "\\\\", 2)) { ! 677: ! 678: unsigned char oldNetAddr[UNCLEN+1]; ! 679: ! 680: strcpy(oldNetAddr, pszNetworkAddress); ! 681: sprintf(pszNetworkAddress, "\\\\%s", oldNetAddr); ! 682: } ! 683: ! 684: if (Bind(hDlg) != RPC_S_OK) { ! 685: EndDialog(hDlg, FALSE); ! 686: return(FALSE); ! 687: } ! 688: ! 689: EndDialog(hDlg, TRUE); ! 690: return(TRUE); ! 691: } ! 692: ! 693: } ! 694: ! 695: #endif ! 696: ! 697: return(FALSE); /* Didn't process a message */ ! 698: 1.1 root 699: } 700: 1.1.1.4 ! root 701: ! 702: /* ! 703: * FUNCTION: Exception(HWND, unsigned, WORD, LONG) ! 704: * ! 705: * PURPOSE: Processes messages for "Exception" dialog box ! 706: * ! 707: * MESSAGES: ! 708: * ! 709: * WM_INITDIALOG - initialize dialog box ! 710: * WM_COMMAND - Input received ! 711: * ! 712: * COMMENTS: ! 713: * ! 714: * No initialization is needed for this particular dialog box, but TRUE ! 715: * must be returned to Windows. ! 716: * ! 717: * Wait for user to click on "Ok" button, then close the dialog box. ! 718: */ 1.1 root 719: 1.1.1.4 ! root 720: BOOL APIENTRY Exception( ! 721: HWND hDlg, /* window handle of the dialog box */ ! 722: UINT message, /* type of message */ ! 723: UINT wParam, /* message-specific information */ ! 724: LONG lParam) ! 725: { ! 726: ! 727: UNREFERENCED_PARAMETER(lParam); ! 728: ! 729: #ifdef RPC ! 730: ! 731: switch (message) { ! 732: ! 733: case WM_INITDIALOG: /* message: initialize dialog box */ ! 734: SetDlgItemText(hDlg, IDD_SERVERNAME, pszNetworkAddress); ! 735: SetDlgItemText(hDlg, IDD_ENDPOINT, pszEndpoint); ! 736: return(TRUE); ! 737: ! 738: case WM_COMMAND: /* message: received a command */ ! 739: switch(wParam) { ! 740: ! 741: case IDCANCEL: /* System menu close command? */ ! 742: EndDialog(hDlg, FALSE); ! 743: return(TRUE); ! 744: ! 745: case IDOK: /* "OK" box selected? */ ! 746: GetDlgItemText(hDlg, IDD_SERVERNAME, pszNetworkAddress, UNCLEN); ! 747: GetDlgItemText(hDlg, IDD_ENDPOINT, pszEndpoint, UNCLEN); ! 748: ! 749: /* pszNetworkAddress must start with two backslashes */ ! 750: if (pszNetworkAddress[0] != '\0' && ! 751: strncmp(pszNetworkAddress, "\\\\", 2)) { ! 752: ! 753: unsigned char oldNetAddr[UNCLEN+1]; ! 754: ! 755: strcpy(oldNetAddr, pszNetworkAddress); ! 756: sprintf(pszNetworkAddress, "\\\\%s", oldNetAddr); ! 757: } ! 758: ! 759: if (Bind(hDlg) != RPC_S_OK) { ! 760: EndDialog(hDlg, FALSE); ! 761: return(FALSE); ! 762: } ! 763: ! 764: EndDialog(hDlg, TRUE); ! 765: return(TRUE); ! 766: ! 767: case IDM_EXIT: ! 768: DestroyWindow(hDlg); ! 769: FreeDrawBuffer(); ! 770: exit(1); ! 771: } ! 772: ! 773: } ! 774: ! 775: #endif ! 776: ! 777: return(FALSE); /* Didn't process a message */ ! 778: ! 779: } 1.1 root 780: 781: 782: /* 783: * DoSomeWork -- 784: * 785: * This function does our work for us. It does it in little pieces, and 786: * will schedule itself as it sees fit. 787: */ 788: 789: void 1.1.1.4 ! root 790: DoSomeWork(HWND hwnd, ! 791: BOOL fTimer) 1.1 root 792: { 793: static WORD wIteration = 0; 794: 795: if (fTimer) { 796: wIteration++; 797: 798: // on every nth tick, we send out a poll 1.1.1.4 ! root 799: if (wIteration == 120) { // tune this? 1.1 root 800: wIteration = 0; 801: return; 802: } 803: 804: // on the half-poll, we check for responses 805: if ((wIteration == 2) || (wIteration == 10)) { 806: return; 807: } 808: } 809: 1.1.1.4 ! root 810: if (CheckDrawStatus(hwnd)) 1.1 root 811: SendMessage(hwnd, WM_DOSOMEWORK, 0, 0L); 812: 813: return; 814: } 815: 1.1.1.4 ! root 816: 1.1 root 817: /* 818: * DrawRect -- 819: * 820: * This function draws (or undraws) the zoom rectangle. 821: */ 822: 823: void 1.1.1.4 ! root 824: DrawRect(HWND hwnd, ! 825: PRECT prc, ! 826: BOOL fDrawIt, ! 827: HDC hdcBM) 1.1 root 828: { 1.1.1.4 ! root 829: HDC hdc; 1.1 root 830: DWORD dwRop; 831: 832: hdc = GetDC(hwnd); 833: 834: if (fDrawIt) 835: dwRop = NOTSRCCOPY; 836: else 837: dwRop = SRCCOPY; 838: 839: // top side 840: BitBlt(hdc, prc->left, prc->top, (prc->right - prc->left) + 1, 1.1.1.4 ! root 841: 1, hdcBM, prc->left, prc->top, dwRop); 1.1 root 842: 843: // bottom side 844: BitBlt(hdc, prc->left, prc->bottom, (prc->right - prc->left) + 1, 1.1.1.4 ! root 845: 1, hdcBM, prc->left, prc->bottom, dwRop); 1.1 root 846: 847: // left side 848: BitBlt(hdc,prc->left, prc->top, 1, (prc->bottom - prc->top) + 1, 1.1.1.4 ! root 849: hdcBM, prc->left, prc->top, dwRop); 1.1 root 850: 851: // right side 852: BitBlt(hdc,prc->right, prc->top, 1, (prc->bottom - prc->top) + 1, 1.1.1.4 ! root 853: hdcBM, prc->right, prc->top, dwRop); 1.1 root 854: 855: ReleaseDC(hwnd, hdc); 856: } 857: 1.1.1.4 ! root 858: 1.1 root 859: /* 860: * PaintLine -- 861: * 862: * This function paints a buffer of data into the bitmap. 863: */ 864: 865: void 1.1.1.4 ! root 866: PaintLine(HWND hwnd, ! 867: svr_table * pst, ! 868: HDC hdcBM, ! 869: int cHeight) 1.1 root 870: { 1.1.1.4 ! root 871: LPWORD pwDrawData; 1.1 root 872: int y; 873: int x; 874: DWORD dwThreshold; 875: RECT rc; 876: WORD lines; 877: 878: lines = (WORD) pst->cLines; 879: 880: // picture ID had better match, or else we skip it 881: if (CheckDrawingID(pst->cPicture)) 882: { 883: // figure out our threshold 884: dwThreshold = QueryThreshold(); 885: 886: // get a pointer to the draw buffer 1.1.1.4 ! root 887: pwDrawData = (LPWORD) LockDrawBuffer(); 1.1 root 888: if (pwDrawData == NULL) { 889: ReturnDrawBuffer(); 890: return; 891: } 892: 893: // starting x coordinate 894: x = (int) pst->dwLine; 895: 896: // now loop through the rectangle 897: while (lines-- > 0) 898: { 899: // bottom to top, since that's the order of the data in the buffer 900: y = (int) cHeight-1; 901: 1.1.1.4 ! root 902: while (y >= 0) ! 903: { 1.1 root 904: // draw a pixel 1.1.1.4 ! root 905: SetPixel(hdcBM, x,y, MapColor(*pwDrawData, dwThreshold)); ! 906: 1.1 root 907: if (fContinueZoom == TRUE) 1.1.1.4 ! root 908: CalcHistogram(x, y, *pwDrawData, dwThreshold); ! 909: 1.1 root 910: // now increment buffer pointer and y coord 911: y--; 912: pwDrawData++; 913: } 1.1.1.4 ! root 914: ! 915: // increment X coordinate ! 916: x++; 1.1 root 917: } 918: 919: // figure out the rectangle to invalidate 920: rc.top = 0; 921: rc.bottom = cHeight; 922: rc.left = (int)(pst->dwLine); 923: rc.right = (int)(pst->dwLine) + pst->cLines; 924: 1.1.1.4 ! root 925: UnlockDrawBuffer(); 1.1 root 926: 927: // and invalidate it on the screen so we redraw it 928: InvalidateRect(hwnd, &rc, FALSE); 929: } 930: 931: // free this for someone else to use 932: ReturnDrawBuffer(); 933: 934: // and change the pipe state, if necessary 935: if (pst->iStatus == SS_PAINTING) 936: pst->iStatus = SS_IDLE; 937: 938: } 939: 940: 941: #define CLR_BLACK RGB(0,0,0) 942: #define CLR_DARKBLUE RGB(0,0,127) 943: #define CLR_BLUE RGB(0,0,255) 944: #define CLR_CYAN RGB(0,255,255) 945: #define CLR_DARKGREEN RGB(0,127,0) 946: #define CLR_GREEN RGB(0,255,0) 947: #define CLR_YELLOW RGB(255,255,0) 948: #define CLR_RED RGB(255,0,0) 949: #define CLR_DARKRED RGB(127,0,0) 950: #define CLR_WHITE RGB(255,255,255) 951: #define CLR_PALEGRAY RGB(194,194,194) 952: #define CLR_DARKGRAY RGB(127,127,127) 953: 954: 1.1.1.4 ! root 955: static COLORREF ColorMapTable[] = { // size = NCOLORS 1.1 root 956: CLR_DARKBLUE, 957: CLR_BLUE, 958: CLR_CYAN, 959: CLR_DARKGREEN, 960: CLR_GREEN, 961: CLR_YELLOW, 962: CLR_RED, 963: CLR_DARKRED, 964: CLR_WHITE, 965: CLR_PALEGRAY, 966: CLR_DARKGRAY}; 967: 968: 969: /* 970: * MapColor -- 971: * 972: * This function maps an iteration count into a corresponding RGB color. 973: */ 974: 975: COLORREF 976: MapColor(DWORD dwIter, 977: DWORD dwThreshold) 978: { 979: 1.1.1.4 ! root 980: /* if it's beyond the threshold, call it black */ 1.1 root 981: if (dwIter >= dwThreshold) { 1.1.1.4 ! root 982: return(CLR_BLACK); 1.1 root 983: } 984: 1.1.1.4 ! root 985: /* get a modulus based on the number of colors */ 1.1 root 986: dwIter = (dwIter / 3) % NCOLORS; // 11; 987: 1.1.1.4 ! root 988: /* and return the appropriate color */ ! 989: return(ColorMapTable[dwIter]); 1.1 root 990: 991: } 1.1.1.4 ! root 992: ! 993: ! 994: /* ! 995: * CalcHistogram -- ! 996: * 1.1 root 997: * This function is used to select the region that is the 998: * most complex and will be used to zoom in for the next picture; 999: * it contains the most colors. The number of colors are counted. 1000: */ 1001: 1002: void 1.1.1.4 ! root 1003: CalcHistogram(int x, ! 1004: int y, ! 1005: DWORD dwIter, ! 1006: DWORD dwThreshold) 1.1 root 1007: { 1008: 1.1.1.4 ! root 1009: /* if it's beyond the threshold, call it black */ 1.1 root 1010: if (dwIter >= dwThreshold) { 1011: Histogram[x/(WIDTH/4)][y/(HEIGHT/4)][NCOLORS]++; 1.1.1.4 ! root 1012: return; 1.1 root 1013: } 1.1.1.4 ! root 1014: ! 1015: /* get a modulus based on the number of colors */ 1.1 root 1016: dwIter = (dwIter / 3) % NCOLORS; // 11; 1017: 1.1.1.4 ! root 1018: /* and bump the count for the appropriate color */ 1.1 root 1019: Histogram[x/(WIDTH/4)][y/(HEIGHT/4)][dwIter]++; // region of map 1020: 1021: return; 1022: 1023: } 1024: 1025: 1.1.1.4 ! root 1026: /* ! 1027: * InitHistogram -- ! 1028: * 1.1 root 1029: * This function initializes the histogram data structures. 1030: */ 1031: 1032: void InitHistogram(void) 1033: { 1034: int i, j, k; 1035: 1036: for (i = 0; i < 4; i++) 1037: for (j = 0; j < 4; j++) 1038: for (k = 0; k <= NCOLORS; k++) 1.1.1.4 ! root 1039: Histogram[i][j][k] = 0; // count of colors 1.1 root 1040: } 1041: 1.1.1.4 ! root 1042: ! 1043: /* ! 1044: * CountHistogram -- ! 1045: * 1.1 root 1046: * This function determines the number of colors represented 1047: * within a region. The region with the most colors is 1048: * selected using the maxi and maxj values. X and Y coordinates 1049: * corresponding to these regions are stored in the HistRegion 1050: * table and are used for the next picture. 1051: */ 1052: 1053: void CountHistogram(void) 1054: { 1.1.1.4 ! root 1055: 1.1 root 1056: int i, j, k; 1.1.1.4 ! root 1057: 1.1 root 1058: /* count the number of colors in each region */ 1059: /* find the color that dominates each region */ 1060: for (i = 0; i < 4; i++) { 1061: for (j = 0; j < 4; j++) { 1062: ColorCount[i][j] = 0; 1063: Max[i][j] = 0; 1064: for (k = 0; k <= NCOLORS; k++) { 1065: if (Histogram[i][j][k] > Max[i][j]) 1066: Max[i][j] = Histogram[i][j][k]; 1.1.1.4 ! root 1067: if (Histogram[i][j][k] != 0) // count of colors 1.1 root 1068: ColorCount[i][j]++; 1069: } 1070: } 1071: } 1.1.1.4 ! root 1072: 1.1 root 1073: iHistMaxI = 0; 1074: iHistMaxJ = 0; 1.1.1.4 ! root 1075: ! 1076: /* if several regions have the same number of colors, */ ! 1077: /* select the region with the most variety: the smallest max */ 1.1 root 1078: for (i = 0; i < 4; i++) { 1079: for (j = 0; j < 4; j++) { 1.1.1.4 ! root 1080: if ( (ColorCount[i][j] >= ColorCount[iHistMaxI][iHistMaxJ]) 1.1 root 1081: && (Max[i][j] < Max[iHistMaxI][iHistMaxJ]) ) { 1082: iHistMaxI = i; 1083: iHistMaxJ = j; 1084: } 1085: } 1086: } 1.1.1.4 ! root 1087: ! 1088: InitHistogram(); // initialize for next time 1.1 root 1089: 1090: } 1.1.1.2 root 1091: 1.1.1.4 ! root 1092: ! 1093: #ifdef RPC ! 1094: ! 1095: void __RPC_FAR * __RPC_API midl_user_allocate(size_t len) 1.1.1.2 root 1096: { 1097: UNREFERENCED_PARAMETER(len); 1098: return(NULL); 1099: } 1.1.1.3 root 1100: 1101: 1.1.1.4 ! root 1102: void __RPC_API midl_user_free(void __RPC_FAR * ptr) 1.1.1.3 root 1103: { 1.1.1.4 ! root 1104: UNREFERENCED_PARAMETER(ptr); ! 1105: return; 1.1.1.3 root 1106: } 1107: 1108: 1.1.1.4 ! root 1109: /* ! 1110: * FUNCTION: Bind(HWND) ! 1111: * ! 1112: * PURPOSE: Make RPC API calls to bind to the server application ! 1113: * ! 1114: * COMMENTS: ! 1115: * ! 1116: * The binding calls are made from InitInstance() and whenever ! 1117: * the user changes the server name or endpoint. If the bind ! 1118: * operation is successful, the global flag fBound is set to TRUE. ! 1119: * ! 1120: * The global flag fBound is used to determine whether to call ! 1121: * the RPC API function RpcBindingFree. ! 1122: */ 1.1.1.3 root 1123: 1124: RPC_STATUS Bind(HWND hWnd) 1125: { 1126: RPC_STATUS status; 1.1.1.4 ! root 1127: char pszFail[MSGLEN]; ! 1128: ! 1129: if (fBound == TRUE) { // unbind only if bound ! 1130: status = RpcStringFree(&pszStringBinding); ! 1131: if (status) { ! 1132: sprintf(pszFail, "RpcStringFree failed 0x%x", status); ! 1133: MessageBox(hWnd, ! 1134: pszFail, ! 1135: "RPC Sample Application", ! 1136: MB_ICONSTOP); ! 1137: return(status); ! 1138: } ! 1139: ! 1140: status = RpcBindingFree(&hMandel); ! 1141: if (status) { ! 1142: sprintf(pszFail, "RpcBindingFree failed 0x%x", status); ! 1143: MessageBox(hWnd, ! 1144: pszFail, ! 1145: "RPC Sample Application", ! 1146: MB_ICONSTOP); ! 1147: return(status); ! 1148: } 1.1.1.3 root 1149: 1.1.1.4 ! root 1150: fBound = FALSE; // unbind successful; reset flag 1.1.1.3 root 1151: } 1.1.1.4 ! root 1152: 1.1.1.3 root 1153: status = RpcStringBindingCompose(pszUuid, 1154: pszProtocolSequence, 1.1.1.4 ! root 1155: pszNetworkAddress, ! 1156: pszEndpoint, 1.1.1.3 root 1157: pszOptions, 1.1.1.4 ! root 1158: &pszStringBinding); ! 1159: if (status) { ! 1160: sprintf(pszFail, "RpcStringBindingCompose returned: (0x%x)\nNetwork Address = %s\n", ! 1161: status, pszNetworkAddress); ! 1162: MessageBox(hWnd, pszFail, "RPC Sample Application", MB_ICONINFORMATION); ! 1163: return(status); ! 1164: } 1.1.1.3 root 1165: 1166: status = RpcBindingFromStringBinding(pszStringBinding, 1.1.1.4 ! root 1167: &hMandel); ! 1168: if (status) { ! 1169: sprintf(pszFail, "RpcBindingFromStringBinding returned: (0x%x)\nString = %s\n", ! 1170: status, pszStringBinding); ! 1171: MessageBox(hWnd, pszFail, "RPC Sample Application", MB_ICONINFORMATION); ! 1172: return(status); ! 1173: } 1.1.1.3 root 1174: 1.1.1.4 ! root 1175: fBound = TRUE; // bind successful; reset flag 1.1.1.3 root 1176: 1177: return(status); 1178: } 1.1.1.4 ! root 1179: 1.1.1.3 root 1180: #endif 1181: 1.1.1.4 ! root 1182: 1.1.1.3 root 1183: /* end mandel.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.