MANDEL.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:35k
源码类别:

Windows编程

开发平台:

Visual C++

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