home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / rpc / mandel / mandel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-12  |  35.3 KB  |  1,233 lines

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